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
}
}