github.com/jxskiss/gopkg@v0.17.3/set/template.go (about)

     1  // +build ignore
     2  
     3  // This program generates set implementation for concrete types.
     4  // It can be invoked by running `go generate`.
     5  package main
     6  
     7  import (
     8  	"log"
     9  	"os"
    10  	"text/template"
    11  	"time"
    12  )
    13  
    14  type Type struct {
    15  	Type      string
    16  	SetType   string
    17  	ZeroValue string
    18  }
    19  
    20  var targetTypes = []Type{
    21  	{"int", "Int", "0"},
    22  	{"int32", "Int32", "0"},
    23  	{"uint32", "Uint32", "0"},
    24  	{"int64", "Int64", "0"},
    25  	{"uint64", "Uint64", "0"},
    26  	{"string", "String", `""`},
    27  }
    28  
    29  func main() {
    30  	timestamp := func() func() string {
    31  		now := time.Now().Format(time.RFC3339)
    32  		return func() string { return now }
    33  	}()
    34  
    35  	tmpl := template.Must(template.New("").
    36  		Funcs(template.FuncMap{"Timestamp": timestamp}).
    37  		Parse(codetmpl))
    38  
    39  	for _, t := range targetTypes {
    40  		func() {
    41  			f, err := os.Create(t.Type + ".go")
    42  			if err != nil {
    43  				log.Fatal(err)
    44  			}
    45  			defer f.Close()
    46  			if err = tmpl.Execute(f, t); err != nil {
    47  				log.Fatal(err)
    48  			}
    49  		}()
    50  	}
    51  }
    52  
    53  var codetmpl = `// Code generated by go generate at {{ Timestamp }}; DO NOT EDIT.
    54  
    55  package set
    56  
    57  import "encoding/json"
    58  
    59  // {{ .SetType }} is {{ .Type }} set collection.
    60  // The zero value of {{ .SetType }} is an empty instance ready to use. A zero {{ .SetType }}
    61  // value shall not be copied, or it may result incorrect behavior.
    62  type {{ .SetType }} struct {
    63  	m map[{{ .Type }}]struct{}
    64  }
    65  
    66  // New{{ .SetType }} creates {{ .SetType }} instance.
    67  func New{{ .SetType }}(vals ...{{ .Type }}) {{ .SetType }} {
    68  	size := max(len(vals), minSize)
    69  	set := {{ .SetType }}{
    70  		m: make(map[{{ .Type }}]struct{}, size),
    71  	}
    72  	set.Add(vals...)
    73  	return set
    74  }
    75  
    76  // New{{ .SetType }}WithSize creates {{ .SetType }} instance with given initial size.
    77  func New{{ .SetType }}WithSize(size int) {{ .SetType }} {
    78  	set := {{ .SetType }}{
    79  		m: make(map[{{ .Type }}]struct{}, size),
    80  	}
    81  	return set
    82  }
    83  
    84  // Size returns the size of set.
    85  func (s {{ .SetType }}) Size() int { return len(s.m) }
    86  
    87  // Add adds values into the set.
    88  func (s *{{ .SetType }}) Add(vals ...{{ .Type }}) {
    89  	if s.m == nil {
    90  		size := max(len(vals), minSize)
    91  		s.m = make(map[{{ .Type }}]struct{}, size)
    92  	}
    93  	for idx := range vals {
    94  		s.m[vals[idx]] = struct{}{}
    95  	}
    96  }
    97  
    98  // Del deletes values from the set.
    99  func (s *{{ .SetType }}) Del(vals ...{{ .Type }}) {
   100  	for idx := range vals {
   101  		delete(s.m, vals[idx])
   102  	}
   103  }
   104  
   105  // Pop pops an element from the set, in no particular order.
   106  func (s *{{ .SetType }}) Pop() {{ .Type }} {
   107  	for val := range s.m {
   108  		delete(s.m, val)
   109  		return val
   110  	}
   111  	return {{ .ZeroValue }}
   112  }
   113  
   114  // Iterate iterates the set in no particular order and call the given function
   115  // for each set element.
   116  func (s {{ .SetType }}) Iterate(fn func({{ .Type }})) {
   117  	for val := range s.m {
   118  		fn(val)
   119  	}
   120  }
   121  
   122  // Contains returns true if the set contains all the values.
   123  func (s {{ .SetType }}) Contains(vals ...{{ .Type }}) bool {
   124  	if len(vals) == 0 {
   125  		return false
   126  	}
   127  	for _, v := range vals {
   128  		if _, ok := s.m[v]; !ok {
   129  			return false
   130  		}
   131  	}
   132  	return true
   133  }
   134  
   135  // ContainsAny returns true if the set contains any of the values.
   136  func (s {{ .SetType }}) ContainsAny(vals ...{{ .Type }}) bool {
   137  	for _, v := range vals {
   138  		if _, ok := s.m[v]; ok {
   139  			return true
   140  		}
   141  	}
   142  	return false
   143  }
   144  
   145  // Diff returns new {{ .SetType }} about the values which other set doesn't contain.
   146  func (s {{ .SetType }}) Diff(other {{ .SetType }}) {{ .SetType }} {
   147  	res := New{{ .SetType }}WithSize(s.Size())
   148  
   149  	for val := range s.m {
   150  		if _, ok := other.m[val]; !ok {
   151  			res.m[val] = struct{}{}
   152  		}
   153  	}
   154  	return res
   155  }
   156  
   157  // DiffSlice is similar to Diff, but takes a slice as parameter.
   158  func (s {{ .SetType }}) DiffSlice(other []{{ .Type }}) {{ .SetType }} {
   159  	if len(s.m) > len(other) {
   160  		tmp := New{{ .SetType }}WithSize(len(other))
   161  		dup := 0
   162  		for _, val := range other {
   163  			if _, ok := s.m[val]; ok {
   164  				dup++
   165  			}
   166  			tmp.m[val] = struct{}{}
   167  		}
   168  		res := New{{ .SetType }}WithSize(max(s.Size()-dup, 0))
   169  		for val := range s.m {
   170  			if _, ok := tmp.m[val]; !ok {
   171  				res.m[val] = struct{}{}
   172  			}
   173  		}
   174  		return res
   175  	} else {
   176  		res := New{{ .SetType }}WithSize(s.Size())
   177  		for val := range s.m {
   178  			res.m[val] = struct{}{}
   179  		}
   180  		for _, val := range other {
   181  			if _, ok := res.m[val]; ok {
   182  				delete(res.m, val)
   183  			}
   184  		}
   185  		return res
   186  	}
   187  }
   188  
   189  // FilterInclude returns a new slice which contains values that present in
   190  // the provided slice and also present in the {{ .SetType }} set.
   191  func (s {{ .SetType }}) FilterInclude(slice []{{ .Type }}) []{{ .Type }} {
   192  	res := make([]{{ .Type }}, 0, min(s.Size(), len(slice)))
   193  	for _, val := range slice {
   194  		if _, ok := s.m[val]; ok {
   195  			res = append(res, val)
   196  		}
   197  	}
   198  	return res
   199  }
   200  
   201  // FilterExclude returns a new slice which contains values that present in
   202  // the provided slice but don't present in the {{ .SetType }} set.
   203  func (s {{ .SetType }}) FilterExclude(slice []{{ .Type }}) []{{ .Type }} {
   204  	res := make([]{{ .Type }}, 0, len(slice))
   205  	for _, val := range slice {
   206  		if _, ok := s.m[val]; !ok {
   207  			res = append(res, val)
   208  		}
   209  	}
   210  	return res
   211  }
   212  
   213  // Intersect returns new {{ .SetType }} about values which other set also contains.
   214  func (s {{ .SetType }}) Intersect(other {{ .SetType }}) {{ .SetType }} {
   215  	res := New{{ .SetType }}WithSize(min(s.Size(), other.Size()))
   216  
   217  	// loop over the smaller set
   218  	if len(s.m) <= len(other.m) {
   219  		for val := range s.m {
   220  			if _, ok := other.m[val]; ok {
   221  				res.m[val] = struct{}{}
   222  			}
   223  		}
   224  	} else {
   225  		for val := range other.m {
   226  			if _, ok := s.m[val]; ok {
   227  				res.m[val] = struct{}{}
   228  			}
   229  		}
   230  	}
   231  	return res
   232  }
   233  
   234  // IntersectSlice is similar to Intersect, but takes a slice as parameter.
   235  func (s {{ .SetType }}) IntersectSlice(other []{{ .Type }}) {{ .SetType }} {
   236  	res := New{{ .SetType }}WithSize(min(s.Size(), len(other)))
   237  
   238  	for _, val := range other {
   239  		if _, ok := s.m[val]; ok {
   240  			res.m[val] = struct{}{}
   241  		}
   242  	}
   243  	return res
   244  }
   245  
   246  // Union returns new {{ .SetType }} about values either in the set or the other set.
   247  func (s {{ .SetType }}) Union(other {{ .SetType }}) {{ .SetType }} {
   248  	res := New{{ .SetType }}WithSize(s.Size() + other.Size())
   249  
   250  	for val := range s.m {
   251  		res.m[val] = struct{}{}
   252  	}
   253  	for val := range other.m {
   254  		res.m[val] = struct{}{}
   255  	}
   256  	return res
   257  }
   258  
   259  // UnionSlice is similar to Union, but takes a slice as parameter.
   260  func (s {{ .SetType }}) UnionSlice(other []{{ .Type }}) {{ .SetType }} {
   261  	res := New{{ .SetType }}WithSize(s.Size() + len(other))
   262  
   263  	for val := range s.m {
   264  		res.m[val] = struct{}{}
   265  	}
   266  	for _, val := range other {
   267  		res.m[val] = struct{}{}
   268  	}
   269  	return res
   270  }
   271  
   272  // Slice converts set into {{ .Type }} slice.
   273  func (s {{ .SetType }}) Slice() []{{ .Type }} {
   274  	res := make([]{{ .Type }}, 0, len(s.m))
   275  
   276  	for val := range s.m {
   277  		res = append(res, val)
   278  	}
   279  	return res
   280  }
   281  
   282  // Map converts set into map[{{ .Type }}]bool.
   283  func (s {{ .SetType }}) Map() map[{{ .Type }}]bool {
   284  	res := make(map[{{ .Type }}]bool, len(s.m))
   285  
   286  	for val := range s.m {
   287  		res[val] = true
   288  	}
   289  	return res
   290  }
   291  
   292  // MarshalJSON implements json.Marshaler interface, the set will be
   293  // marshaled as an {{ .Type }} array.
   294  func (s {{ .SetType }}) MarshalJSON() ([]byte, error) {
   295  	res := s.Slice()
   296  	return json.Marshal(res)
   297  }
   298  
   299  // UnmarshalJSON implements json.Unmarshaler interface, it will unmarshal
   300  // an {{ .Type }} array to the set.
   301  func (s *{{ .SetType }}) UnmarshalJSON(b []byte) error {
   302  	vals := make([]{{ .Type }}, 0)
   303  	err := json.Unmarshal(b, &vals)
   304  	if err == nil {
   305  		s.Add(vals...)
   306  	}
   307  	return err
   308  }
   309  
   310  // MarshalYAML implements yaml.Marshaler interface of the yaml package,
   311  // the set will be marshaled as an {{ .Type }} array.
   312  func (s {{ .SetType }}) MarshalYAML() (interface{}, error) {
   313  	res := s.Slice()
   314  	return res, nil
   315  }
   316  
   317  // UnmarshalYAML implements yaml.Unmarshaler interface of the yaml package,
   318  // it will unmarshal an {{ .Type }} array to the set.
   319  func (s *{{ .SetType }}) UnmarshalYAML(unmarshal func(interface{}) error) error {
   320  	vals := make([]{{ .Type }}, 0)
   321  	err := unmarshal(&vals)
   322  	if err == nil {
   323  		s.Add(vals...)
   324  	}
   325  	return err
   326  }
   327  `