github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/objects/merge.go (about)

     1  package objects
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/MontFerret/ferret/pkg/runtime/core"
     7  	"github.com/MontFerret/ferret/pkg/runtime/values"
     8  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
     9  )
    10  
    11  // MERGE merge the given objects into a single object.
    12  // @param {Object, repeated} objects - Objects to merge.
    13  // @return {Object} - Object created by merging.
    14  func Merge(_ context.Context, args ...core.Value) (core.Value, error) {
    15  	err := core.ValidateArgs(args, 1, core.MaxArgs)
    16  
    17  	if err != nil {
    18  		return values.None, err
    19  	}
    20  
    21  	objs := values.NewArrayWith(args...)
    22  
    23  	if len(args) == 1 && args[0].Type().Equals(types.Array) {
    24  		objs = args[0].(*values.Array)
    25  	}
    26  
    27  	err = validateArrayOf(types.Object, objs)
    28  
    29  	if err != nil {
    30  		return values.None, err
    31  	}
    32  
    33  	return mergeArray(objs), nil
    34  }
    35  
    36  func mergeArray(arr *values.Array) *values.Object {
    37  	merged, obj := values.NewObject(), values.NewObject()
    38  
    39  	arr.ForEach(func(arrValue core.Value, arrIdx int) bool {
    40  		obj = arrValue.(*values.Object)
    41  		obj.ForEach(func(objValue core.Value, objKey string) bool {
    42  			cloneable, ok := objValue.(core.Cloneable)
    43  
    44  			if ok {
    45  				objValue = cloneable.Clone()
    46  			}
    47  
    48  			merged.Set(values.NewString(objKey), objValue)
    49  
    50  			return true
    51  		})
    52  		return true
    53  	})
    54  
    55  	return merged
    56  }
    57  
    58  func validateArrayOf(typ core.Type, arr *values.Array) (err error) {
    59  	for idx := values.NewInt(0); idx < arr.Length(); idx++ {
    60  		if err != nil {
    61  			break
    62  		}
    63  		err = core.ValidateType(arr.Get(idx), typ)
    64  	}
    65  	return
    66  }