func search()

in intrinsics/intrinsics.go [156:242]


func search(input interface{}, template interface{}, options *ProcessorOptions) interface{} {

	switch value := input.(type) {

	case map[string]interface{}:

		// We've found an object in the JSON, it might be an intrinsic, it might not.
		// To check, we need to see if it contains a specific key that matches the name
		// of an intrinsic function. As golang maps do not guarentee ordering, we need
		// to check every key, not just the first.
		processed := map[string]interface{}{}
		for key, val := range value {

			// See if we have an intrinsic handler function for this object key provided in the
			if h, ok := handler(key, options); ok {
				// This is an intrinsic function, so replace the intrinsic function object
				// with the result of calling the intrinsic function handler for this type
				return h(key, search(val, template, options), template)
			}

			if key == "Condition" && (options != nil && options.EvaluateConditions) {
				// This can lead to infinite recursion A -> B; B -> A;
				// pass state of the conditions that we're evaluating so we can detect cycles
				// in case of cycle or not found, do nothing
				if con := condition(key, search(val, template, options), template, options); con != nil {
					return con
				}
			}

			// This is not an intrinsic function, recurse through it normally
			processed[key] = search(val, template, options)

		}
		return processed

	case []interface{}:

		// We found an array in the JSON - recurse through it's elements looking for intrinsic functions
		processed := []interface{}{}
		for _, val := range value {
			processed = append(processed, search(val, template, options))
		}
		return processed

	case nil:
		return value
	case bool:
		return value
	case float64:
		return value
	case string:

		// Check if the string can be unmarshalled into an intrinsic object
		var decoded []byte
		decoded, err := base64.StdEncoding.DecodeString(value)
		if err != nil {
			// The string value is not base64 encoded, so it's not an intrinsic so just pass it back
			return value
		}

		var intrinsic map[string]interface{}
		if err := json.Unmarshal([]byte(decoded), &intrinsic); err != nil {
			// The string value is not JSON, so it's not an intrinsic so just pass it back
			return value
		}

		// An intrinsic should be an object, with a single key containing a valid intrinsic name
		if len(intrinsic) != 1 {
			return value
		}

		for key, val := range intrinsic {
			// See if this is a valid intrinsic function, by comparing the name with our list of registered handlers
			if _, ok := handler(key, options); ok {
				return map[string]interface{}{
					key: search(val, template, options),
				}
			}
		}

		return value
	default:
		return nil

	}

}