func zip()

in wstl1/mapping_engine/mapping/engine.go [252:310]


func zip(values []jsonutil.JSONMetaNode, iterables []bool) ([][]jsonutil.JSONMetaNode, error) {
	if len(values) != len(iterables) {
		return nil, fmt.Errorf("this is an internal bug: number of values (%d) did not match number of iterable flags (%d)", len(values), len(iterables))
	}

	// Validate that things flagged to be iterated are actually iterated.
	baseLen := 0
	basePath := ""
	if iterables != nil {
		for i, a := range values {
			if !iterables[i] {
				continue
			}
			if a == nil {
				a = jsonutil.JSONMetaArrayNode{}
				values[i] = a
			}

			arr, ok := a.(jsonutil.JSONMetaArrayNode)
			if !ok {
				return nil, fmt.Errorf("can't iterate non-array %q (it was the %s argument in the function call)", a.ProvenanceString(), errs.SuffixNumber(i+1))
			}

			if baseLen == 0 {
				baseLen = len(arr.Items)
				basePath = arr.ProvenanceString()
			}

			if len(arr.Items) != baseLen && len(arr.Items) > 0 {
				return nil, fmt.Errorf("can't zip/iterate arrays of different sizes together (%q had %d items, but %q had %d)", basePath, baseLen, arr.ProvenanceString(), len(arr.Items))
			}
		}
	}

	if baseLen == 0 {
		return [][]jsonutil.JSONMetaNode{}, nil
	}

	// Zip together iterables and non-iterables.
	var res [][]jsonutil.JSONMetaNode
	for i := 0; i < baseLen; i++ {
		z := []jsonutil.JSONMetaNode{}
		for j, a := range values {
			if iterables != nil && iterables[j] {
				arr := values[j].(jsonutil.JSONMetaArrayNode)
				if len(arr.Items) > 0 {
					z = append(z, arr.Items[i])
				} else {
					z = append(z, nil)
				}
			} else {
				z = append(z, a)
			}
		}
		res = append(res, z)
	}

	return res, nil
}