github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/tpl/collections/collections.go (about)

     1  // Copyright 2019 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  // Package collections provides template functions for manipulating collections
    15  // such as arrays, maps, and slices.
    16  package collections
    17  
    18  import (
    19  	"fmt"
    20  	"html/template"
    21  	"math/rand"
    22  	"net/url"
    23  	"reflect"
    24  	"strings"
    25  	"time"
    26  
    27  	"github.com/gohugoio/hugo/common/collections"
    28  	"github.com/gohugoio/hugo/common/maps"
    29  	"github.com/gohugoio/hugo/common/types"
    30  	"github.com/gohugoio/hugo/deps"
    31  	"github.com/gohugoio/hugo/helpers"
    32  	"github.com/pkg/errors"
    33  	"github.com/spf13/cast"
    34  )
    35  
    36  func init() {
    37  	rand.Seed(time.Now().UTC().UnixNano())
    38  }
    39  
    40  // New returns a new instance of the collections-namespaced template functions.
    41  func New(deps *deps.Deps) *Namespace {
    42  	return &Namespace{
    43  		deps: deps,
    44  	}
    45  }
    46  
    47  // Namespace provides template functions for the "collections" namespace.
    48  type Namespace struct {
    49  	deps *deps.Deps
    50  }
    51  
    52  // After returns all the items after the first N in a rangeable list.
    53  func (ns *Namespace) After(index interface{}, seq interface{}) (interface{}, error) {
    54  	if index == nil || seq == nil {
    55  		return nil, errors.New("both limit and seq must be provided")
    56  	}
    57  
    58  	indexv, err := cast.ToIntE(index)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	if indexv < 0 {
    64  		return nil, errors.New("sequence bounds out of range [" + cast.ToString(indexv) + ":]")
    65  	}
    66  
    67  	seqv := reflect.ValueOf(seq)
    68  	seqv, isNil := indirect(seqv)
    69  	if isNil {
    70  		return nil, errors.New("can't iterate over a nil value")
    71  	}
    72  
    73  	switch seqv.Kind() {
    74  	case reflect.Array, reflect.Slice, reflect.String:
    75  		// okay
    76  	default:
    77  		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
    78  	}
    79  
    80  	if indexv >= seqv.Len() {
    81  		return seqv.Slice(0, 0).Interface(), nil
    82  	}
    83  
    84  	return seqv.Slice(indexv, seqv.Len()).Interface(), nil
    85  }
    86  
    87  // Delimit takes a given sequence and returns a delimited HTML string.
    88  // If last is passed to the function, it will be used as the final delimiter.
    89  func (ns *Namespace) Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, error) {
    90  	d, err := cast.ToStringE(delimiter)
    91  	if err != nil {
    92  		return "", err
    93  	}
    94  
    95  	var dLast *string
    96  	if len(last) > 0 {
    97  		l := last[0]
    98  		dStr, err := cast.ToStringE(l)
    99  		if err != nil {
   100  			dLast = nil
   101  		} else {
   102  			dLast = &dStr
   103  		}
   104  	}
   105  
   106  	seqv := reflect.ValueOf(seq)
   107  	seqv, isNil := indirect(seqv)
   108  	if isNil {
   109  		return "", errors.New("can't iterate over a nil value")
   110  	}
   111  
   112  	var str string
   113  	switch seqv.Kind() {
   114  	case reflect.Map:
   115  		sortSeq, err := ns.Sort(seq)
   116  		if err != nil {
   117  			return "", err
   118  		}
   119  		seqv = reflect.ValueOf(sortSeq)
   120  		fallthrough
   121  	case reflect.Array, reflect.Slice, reflect.String:
   122  		for i := 0; i < seqv.Len(); i++ {
   123  			val := seqv.Index(i).Interface()
   124  			valStr, err := cast.ToStringE(val)
   125  			if err != nil {
   126  				continue
   127  			}
   128  			switch {
   129  			case i == seqv.Len()-2 && dLast != nil:
   130  				str += valStr + *dLast
   131  			case i == seqv.Len()-1:
   132  				str += valStr
   133  			default:
   134  				str += valStr + d
   135  			}
   136  		}
   137  
   138  	default:
   139  		return "", fmt.Errorf("can't iterate over %v", seq)
   140  	}
   141  
   142  	return template.HTML(str), nil
   143  }
   144  
   145  // Dictionary creates a map[string]interface{} from the given parameters by
   146  // walking the parameters and treating them as key-value pairs.  The number
   147  // of parameters must be even.
   148  // The keys can be string slices, which will create the needed nested structure.
   149  func (ns *Namespace) Dictionary(values ...interface{}) (map[string]interface{}, error) {
   150  	if len(values)%2 != 0 {
   151  		return nil, errors.New("invalid dictionary call")
   152  	}
   153  
   154  	root := make(map[string]interface{})
   155  
   156  	for i := 0; i < len(values); i += 2 {
   157  		dict := root
   158  		var key string
   159  		switch v := values[i].(type) {
   160  		case string:
   161  			key = v
   162  		case []string:
   163  			for i := 0; i < len(v)-1; i++ {
   164  				key = v[i]
   165  				var m map[string]interface{}
   166  				v, found := dict[key]
   167  				if found {
   168  					m = v.(map[string]interface{})
   169  				} else {
   170  					m = make(map[string]interface{})
   171  					dict[key] = m
   172  				}
   173  				dict = m
   174  			}
   175  			key = v[len(v)-1]
   176  		default:
   177  			return nil, errors.New("invalid dictionary key")
   178  		}
   179  		dict[key] = values[i+1]
   180  	}
   181  
   182  	return root, nil
   183  }
   184  
   185  // EchoParam returns a given value if it is set; otherwise, it returns an
   186  // empty string.
   187  func (ns *Namespace) EchoParam(a, key interface{}) interface{} {
   188  	av, isNil := indirect(reflect.ValueOf(a))
   189  	if isNil {
   190  		return ""
   191  	}
   192  
   193  	var avv reflect.Value
   194  	switch av.Kind() {
   195  	case reflect.Array, reflect.Slice:
   196  		index, ok := key.(int)
   197  		if ok && av.Len() > index {
   198  			avv = av.Index(index)
   199  		}
   200  	case reflect.Map:
   201  		kv := reflect.ValueOf(key)
   202  		if kv.Type().AssignableTo(av.Type().Key()) {
   203  			avv = av.MapIndex(kv)
   204  		}
   205  	}
   206  
   207  	avv, isNil = indirect(avv)
   208  
   209  	if isNil {
   210  		return ""
   211  	}
   212  
   213  	if avv.IsValid() {
   214  		switch avv.Kind() {
   215  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   216  			return avv.Int()
   217  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   218  			return avv.Uint()
   219  		case reflect.Float32, reflect.Float64:
   220  			return avv.Float()
   221  		case reflect.String:
   222  			return avv.String()
   223  		}
   224  	}
   225  
   226  	return ""
   227  }
   228  
   229  // First returns the first N items in a rangeable list.
   230  func (ns *Namespace) First(limit interface{}, seq interface{}) (interface{}, error) {
   231  	if limit == nil || seq == nil {
   232  		return nil, errors.New("both limit and seq must be provided")
   233  	}
   234  
   235  	limitv, err := cast.ToIntE(limit)
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  
   240  	if limitv < 0 {
   241  		return nil, errors.New("sequence length must be non-negative")
   242  	}
   243  
   244  	seqv := reflect.ValueOf(seq)
   245  	seqv, isNil := indirect(seqv)
   246  	if isNil {
   247  		return nil, errors.New("can't iterate over a nil value")
   248  	}
   249  
   250  	switch seqv.Kind() {
   251  	case reflect.Array, reflect.Slice, reflect.String:
   252  		// okay
   253  	default:
   254  		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
   255  	}
   256  
   257  	if limitv > seqv.Len() {
   258  		limitv = seqv.Len()
   259  	}
   260  
   261  	return seqv.Slice(0, limitv).Interface(), nil
   262  }
   263  
   264  // In returns whether v is in the set l.  l may be an array or slice.
   265  func (ns *Namespace) In(l interface{}, v interface{}) (bool, error) {
   266  	if l == nil || v == nil {
   267  		return false, nil
   268  	}
   269  
   270  	lv := reflect.ValueOf(l)
   271  	vv := reflect.ValueOf(v)
   272  
   273  	vvk := normalize(vv)
   274  
   275  	switch lv.Kind() {
   276  	case reflect.Array, reflect.Slice:
   277  		for i := 0; i < lv.Len(); i++ {
   278  			lvv, isNil := indirectInterface(lv.Index(i))
   279  			if isNil {
   280  				continue
   281  			}
   282  
   283  			lvvk := normalize(lvv)
   284  
   285  			if lvvk == vvk {
   286  				return true, nil
   287  			}
   288  		}
   289  	}
   290  	ss, err := cast.ToStringE(l)
   291  	if err != nil {
   292  		return false, nil
   293  	}
   294  
   295  	su, err := cast.ToStringE(v)
   296  	if err != nil {
   297  		return false, nil
   298  	}
   299  	return strings.Contains(ss, su), nil
   300  }
   301  
   302  // Intersect returns the common elements in the given sets, l1 and l2.  l1 and
   303  // l2 must be of the same type and may be either arrays or slices.
   304  func (ns *Namespace) Intersect(l1, l2 interface{}) (interface{}, error) {
   305  	if l1 == nil || l2 == nil {
   306  		return make([]interface{}, 0), nil
   307  	}
   308  
   309  	var ins *intersector
   310  
   311  	l1v := reflect.ValueOf(l1)
   312  	l2v := reflect.ValueOf(l2)
   313  
   314  	switch l1v.Kind() {
   315  	case reflect.Array, reflect.Slice:
   316  		ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)}
   317  		switch l2v.Kind() {
   318  		case reflect.Array, reflect.Slice:
   319  			for i := 0; i < l1v.Len(); i++ {
   320  				l1vv := l1v.Index(i)
   321  				if !l1vv.Type().Comparable() {
   322  					return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types")
   323  				}
   324  
   325  				for j := 0; j < l2v.Len(); j++ {
   326  					l2vv := l2v.Index(j)
   327  					if !l2vv.Type().Comparable() {
   328  						return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types")
   329  					}
   330  
   331  					ins.handleValuePair(l1vv, l2vv)
   332  				}
   333  			}
   334  			return ins.r.Interface(), nil
   335  		default:
   336  			return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
   337  		}
   338  	default:
   339  		return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
   340  	}
   341  }
   342  
   343  // Group groups a set of elements by the given key.
   344  // This is currently only supported for Pages.
   345  func (ns *Namespace) Group(key interface{}, items interface{}) (interface{}, error) {
   346  	if key == nil {
   347  		return nil, errors.New("nil is not a valid key to group by")
   348  	}
   349  
   350  	if g, ok := items.(collections.Grouper); ok {
   351  		return g.Group(key, items)
   352  	}
   353  
   354  	in := newSliceElement(items)
   355  
   356  	if g, ok := in.(collections.Grouper); ok {
   357  		return g.Group(key, items)
   358  	}
   359  
   360  	return nil, fmt.Errorf("grouping not supported for type %T %T", items, in)
   361  }
   362  
   363  // IsSet returns whether a given array, channel, slice, or map has a key
   364  // defined.
   365  func (ns *Namespace) IsSet(a interface{}, key interface{}) (bool, error) {
   366  	av := reflect.ValueOf(a)
   367  	kv := reflect.ValueOf(key)
   368  
   369  	switch av.Kind() {
   370  	case reflect.Array, reflect.Chan, reflect.Slice:
   371  		k, err := cast.ToIntE(key)
   372  		if err != nil {
   373  			return false, fmt.Errorf("isset unable to use key of type %T as index", key)
   374  		}
   375  		if av.Len() > k {
   376  			return true, nil
   377  		}
   378  	case reflect.Map:
   379  		if kv.Type() == av.Type().Key() {
   380  			return av.MapIndex(kv).IsValid(), nil
   381  		}
   382  	default:
   383  		helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), a)
   384  	}
   385  
   386  	return false, nil
   387  }
   388  
   389  // Last returns the last N items in a rangeable list.
   390  func (ns *Namespace) Last(limit interface{}, seq interface{}) (interface{}, error) {
   391  	if limit == nil || seq == nil {
   392  		return nil, errors.New("both limit and seq must be provided")
   393  	}
   394  
   395  	limitv, err := cast.ToIntE(limit)
   396  	if err != nil {
   397  		return nil, err
   398  	}
   399  
   400  	if limitv < 0 {
   401  		return nil, errors.New("sequence length must be non-negative")
   402  	}
   403  
   404  	seqv := reflect.ValueOf(seq)
   405  	seqv, isNil := indirect(seqv)
   406  	if isNil {
   407  		return nil, errors.New("can't iterate over a nil value")
   408  	}
   409  
   410  	switch seqv.Kind() {
   411  	case reflect.Array, reflect.Slice, reflect.String:
   412  		// okay
   413  	default:
   414  		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
   415  	}
   416  
   417  	if limitv > seqv.Len() {
   418  		limitv = seqv.Len()
   419  	}
   420  
   421  	return seqv.Slice(seqv.Len()-limitv, seqv.Len()).Interface(), nil
   422  }
   423  
   424  // Querify encodes the given parameters in URL-encoded form ("bar=baz&foo=quux") sorted by key.
   425  func (ns *Namespace) Querify(params ...interface{}) (string, error) {
   426  	qs := url.Values{}
   427  
   428  	if len(params) == 1 {
   429  		switch v := params[0].(type) {
   430  		case []string:
   431  			if len(v)%2 != 0 {
   432  				return "", errors.New("invalid query")
   433  			}
   434  
   435  			for i := 0; i < len(v); i += 2 {
   436  				qs.Add(v[i], v[i+1])
   437  			}
   438  
   439  			return qs.Encode(), nil
   440  
   441  		case []interface{}:
   442  			params = v
   443  
   444  		default:
   445  			return "", errors.New("query keys must be strings")
   446  		}
   447  	}
   448  
   449  	if len(params)%2 != 0 {
   450  		return "", errors.New("invalid query")
   451  	}
   452  
   453  	for i := 0; i < len(params); i += 2 {
   454  		switch v := params[i].(type) {
   455  		case string:
   456  			qs.Add(v, fmt.Sprintf("%v", params[i+1]))
   457  		default:
   458  			return "", errors.New("query keys must be strings")
   459  		}
   460  	}
   461  
   462  	return qs.Encode(), nil
   463  }
   464  
   465  // Reverse creates a copy of slice and reverses it.
   466  func (ns *Namespace) Reverse(slice interface{}) (interface{}, error) {
   467  	if slice == nil {
   468  		return nil, nil
   469  	}
   470  	v := reflect.ValueOf(slice)
   471  
   472  	switch v.Kind() {
   473  	case reflect.Slice:
   474  	default:
   475  		return nil, errors.New("argument must be a slice")
   476  	}
   477  
   478  	sliceCopy := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
   479  
   480  	for i := v.Len() - 1; i >= 0; i-- {
   481  		element := sliceCopy.Index(i)
   482  		element.Set(v.Index(v.Len() - 1 - i))
   483  	}
   484  
   485  	return sliceCopy.Interface(), nil
   486  }
   487  
   488  // Seq creates a sequence of integers.  It's named and used as GNU's seq.
   489  //
   490  // Examples:
   491  //     3 => 1, 2, 3
   492  //     1 2 4 => 1, 3
   493  //     -3 => -1, -2, -3
   494  //     1 4 => 1, 2, 3, 4
   495  //     1 -2 => 1, 0, -1, -2
   496  func (ns *Namespace) Seq(args ...interface{}) ([]int, error) {
   497  	if len(args) < 1 || len(args) > 3 {
   498  		return nil, errors.New("invalid number of arguments to Seq")
   499  	}
   500  
   501  	intArgs := cast.ToIntSlice(args)
   502  	if len(intArgs) < 1 || len(intArgs) > 3 {
   503  		return nil, errors.New("invalid arguments to Seq")
   504  	}
   505  
   506  	inc := 1
   507  	var last int
   508  	first := intArgs[0]
   509  
   510  	if len(intArgs) == 1 {
   511  		last = first
   512  		if last == 0 {
   513  			return []int{}, nil
   514  		} else if last > 0 {
   515  			first = 1
   516  		} else {
   517  			first = -1
   518  			inc = -1
   519  		}
   520  	} else if len(intArgs) == 2 {
   521  		last = intArgs[1]
   522  		if last < first {
   523  			inc = -1
   524  		}
   525  	} else {
   526  		inc = intArgs[1]
   527  		last = intArgs[2]
   528  		if inc == 0 {
   529  			return nil, errors.New("'increment' must not be 0")
   530  		}
   531  		if first < last && inc < 0 {
   532  			return nil, errors.New("'increment' must be > 0")
   533  		}
   534  		if first > last && inc > 0 {
   535  			return nil, errors.New("'increment' must be < 0")
   536  		}
   537  	}
   538  
   539  	// sanity check
   540  	if last < -100000 {
   541  		return nil, errors.New("size of result exceeds limit")
   542  	}
   543  	size := ((last - first) / inc) + 1
   544  
   545  	// sanity check
   546  	if size <= 0 || size > 2000 {
   547  		return nil, errors.New("size of result exceeds limit")
   548  	}
   549  
   550  	seq := make([]int, size)
   551  	val := first
   552  	for i := 0; ; i++ {
   553  		seq[i] = val
   554  		val += inc
   555  		if (inc < 0 && val < last) || (inc > 0 && val > last) {
   556  			break
   557  		}
   558  	}
   559  
   560  	return seq, nil
   561  }
   562  
   563  // Shuffle returns the given rangeable list in a randomised order.
   564  func (ns *Namespace) Shuffle(seq interface{}) (interface{}, error) {
   565  	if seq == nil {
   566  		return nil, errors.New("both count and seq must be provided")
   567  	}
   568  
   569  	seqv := reflect.ValueOf(seq)
   570  	seqv, isNil := indirect(seqv)
   571  	if isNil {
   572  		return nil, errors.New("can't iterate over a nil value")
   573  	}
   574  
   575  	switch seqv.Kind() {
   576  	case reflect.Array, reflect.Slice, reflect.String:
   577  		// okay
   578  	default:
   579  		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
   580  	}
   581  
   582  	shuffled := reflect.MakeSlice(reflect.TypeOf(seq), seqv.Len(), seqv.Len())
   583  
   584  	randomIndices := rand.Perm(seqv.Len())
   585  
   586  	for index, value := range randomIndices {
   587  		shuffled.Index(value).Set(seqv.Index(index))
   588  	}
   589  
   590  	return shuffled.Interface(), nil
   591  }
   592  
   593  // Slice returns a slice of all passed arguments.
   594  func (ns *Namespace) Slice(args ...interface{}) interface{} {
   595  	if len(args) == 0 {
   596  		return args
   597  	}
   598  
   599  	return collections.Slice(args...)
   600  }
   601  
   602  type intersector struct {
   603  	r    reflect.Value
   604  	seen map[interface{}]bool
   605  }
   606  
   607  func (i *intersector) appendIfNotSeen(v reflect.Value) {
   608  	vi := v.Interface()
   609  	if !i.seen[vi] {
   610  		i.r = reflect.Append(i.r, v)
   611  		i.seen[vi] = true
   612  	}
   613  }
   614  
   615  func (i *intersector) handleValuePair(l1vv, l2vv reflect.Value) {
   616  	switch kind := l1vv.Kind(); {
   617  	case kind == reflect.String:
   618  		l2t, err := toString(l2vv)
   619  		if err == nil && l1vv.String() == l2t {
   620  			i.appendIfNotSeen(l1vv)
   621  		}
   622  	case isNumber(kind):
   623  		f1, err1 := numberToFloat(l1vv)
   624  		f2, err2 := numberToFloat(l2vv)
   625  		if err1 == nil && err2 == nil && f1 == f2 {
   626  			i.appendIfNotSeen(l1vv)
   627  		}
   628  	case kind == reflect.Ptr, kind == reflect.Struct:
   629  		if l1vv.Interface() == l2vv.Interface() {
   630  			i.appendIfNotSeen(l1vv)
   631  		}
   632  	case kind == reflect.Interface:
   633  		i.handleValuePair(reflect.ValueOf(l1vv.Interface()), l2vv)
   634  	}
   635  }
   636  
   637  // Union returns the union of the given sets, l1 and l2. l1 and
   638  // l2 must be of the same type and may be either arrays or slices.
   639  // If l1 and l2 aren't of the same type then l1 will be returned.
   640  // If either l1 or l2 is nil then the non-nil list will be returned.
   641  func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) {
   642  	if l1 == nil && l2 == nil {
   643  		return []interface{}{}, nil
   644  	} else if l1 == nil && l2 != nil {
   645  		return l2, nil
   646  	} else if l1 != nil && l2 == nil {
   647  		return l1, nil
   648  	}
   649  
   650  	l1v := reflect.ValueOf(l1)
   651  	l2v := reflect.ValueOf(l2)
   652  
   653  	var ins *intersector
   654  
   655  	switch l1v.Kind() {
   656  	case reflect.Array, reflect.Slice:
   657  		switch l2v.Kind() {
   658  		case reflect.Array, reflect.Slice:
   659  			ins = &intersector{r: reflect.MakeSlice(l1v.Type(), 0, 0), seen: make(map[interface{}]bool)}
   660  
   661  			if l1v.Type() != l2v.Type() &&
   662  				l1v.Type().Elem().Kind() != reflect.Interface &&
   663  				l2v.Type().Elem().Kind() != reflect.Interface {
   664  				return ins.r.Interface(), nil
   665  			}
   666  
   667  			var (
   668  				l1vv  reflect.Value
   669  				isNil bool
   670  			)
   671  
   672  			for i := 0; i < l1v.Len(); i++ {
   673  				l1vv, isNil = indirectInterface(l1v.Index(i))
   674  
   675  				if !l1vv.Type().Comparable() {
   676  					return []interface{}{}, errors.New("union does not support slices or arrays of uncomparable types")
   677  				}
   678  
   679  				if !isNil {
   680  					ins.appendIfNotSeen(l1vv)
   681  				}
   682  			}
   683  
   684  			if !l1vv.IsValid() {
   685  				// The first slice may be empty. Pick the first value of the second
   686  				// to use as a prototype.
   687  				if l2v.Len() > 0 {
   688  					l1vv = l2v.Index(0)
   689  				}
   690  			}
   691  
   692  			for j := 0; j < l2v.Len(); j++ {
   693  				l2vv := l2v.Index(j)
   694  
   695  				switch kind := l1vv.Kind(); {
   696  				case kind == reflect.String:
   697  					l2t, err := toString(l2vv)
   698  					if err == nil {
   699  						ins.appendIfNotSeen(reflect.ValueOf(l2t))
   700  					}
   701  				case isNumber(kind):
   702  					var err error
   703  					l2vv, err = convertNumber(l2vv, kind)
   704  					if err == nil {
   705  						ins.appendIfNotSeen(l2vv)
   706  					}
   707  				case kind == reflect.Interface, kind == reflect.Struct, kind == reflect.Ptr:
   708  					ins.appendIfNotSeen(l2vv)
   709  
   710  				}
   711  			}
   712  
   713  			return ins.r.Interface(), nil
   714  		default:
   715  			return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
   716  		}
   717  	default:
   718  		return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
   719  	}
   720  }
   721  
   722  // Uniq takes in a slice or array and returns a slice with subsequent
   723  // duplicate elements removed.
   724  func (ns *Namespace) Uniq(seq interface{}) (interface{}, error) {
   725  	if seq == nil {
   726  		return make([]interface{}, 0), nil
   727  	}
   728  
   729  	v := reflect.ValueOf(seq)
   730  	var slice reflect.Value
   731  
   732  	switch v.Kind() {
   733  	case reflect.Slice:
   734  		slice = reflect.MakeSlice(v.Type(), 0, 0)
   735  
   736  	case reflect.Array:
   737  		slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0)
   738  	default:
   739  		return nil, errors.Errorf("type %T not supported", seq)
   740  	}
   741  
   742  	seen := make(map[interface{}]bool)
   743  
   744  	for i := 0; i < v.Len(); i++ {
   745  		ev, _ := indirectInterface(v.Index(i))
   746  
   747  		key := normalize(ev)
   748  
   749  		if _, found := seen[key]; !found {
   750  			slice = reflect.Append(slice, ev)
   751  			seen[key] = true
   752  		}
   753  	}
   754  
   755  	return slice.Interface(), nil
   756  }
   757  
   758  // KeyVals creates a key and values wrapper.
   759  func (ns *Namespace) KeyVals(key interface{}, vals ...interface{}) (types.KeyValues, error) {
   760  	return types.KeyValues{Key: key, Values: vals}, nil
   761  }
   762  
   763  // NewScratch creates a new Scratch which can be used to store values in a
   764  // thread safe way.
   765  func (ns *Namespace) NewScratch() *maps.Scratch {
   766  	return maps.NewScratch()
   767  }