| // Package customdecode contains a HCL extension that allows, in certain |
| // contexts, expression evaluation to be overridden by custom static analysis. |
| // |
| // This mechanism is only supported in certain specific contexts where |
| // expressions are decoded with a specific target type in mind. For more |
| // information, see the documentation on CustomExpressionDecoder. |
| package customdecode |
| |
| import ( |
| "github.com/hashicorp/hcl/v2" |
| "github.com/zclconf/go-cty/cty" |
| ) |
| |
| type customDecoderImpl int |
| |
| // CustomExpressionDecoder is a value intended to be used as a cty capsule |
| // type ExtensionData key for capsule types whose values are to be obtained |
| // by static analysis of an expression rather than normal evaluation of that |
| // expression. |
| // |
| // When a cooperating capsule type is asked for ExtensionData with this key, |
| // it must return a non-nil CustomExpressionDecoderFunc value. |
| // |
| // This mechanism is not universally supported; instead, it's handled in a few |
| // specific places where expressions are evaluated with the intent of producing |
| // a cty.Value of a type given by the calling application. |
| // |
| // Specifically, this currently works for type constraints given in |
| // hcldec.AttrSpec and hcldec.BlockAttrsSpec, and it works for arguments to |
| // function calls in the HCL native syntax. HCL extensions implemented outside |
| // of the main HCL module may also implement this; consult their own |
| // documentation for details. |
| const CustomExpressionDecoder = customDecoderImpl(1) |
| |
| // CustomExpressionDecoderFunc is the type of value that must be returned by |
| // a capsule type handling the key CustomExpressionDecoder in its ExtensionData |
| // implementation. |
| // |
| // If no error diagnostics are returned, the result value MUST be of the |
| // capsule type that the decoder function was derived from. If the returned |
| // error diagnostics prevent producing a value at all, return cty.NilVal. |
| type CustomExpressionDecoderFunc func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) |
| |
| // CustomExpressionDecoderForType takes any cty type and returns its |
| // custom expression decoder implementation if it has one. If it is not a |
| // capsule type or it does not implement a custom expression decoder, this |
| // function returns nil. |
| func CustomExpressionDecoderForType(ty cty.Type) CustomExpressionDecoderFunc { |
| if !ty.IsCapsuleType() { |
| return nil |
| } |
| if fn, ok := ty.CapsuleExtensionData(CustomExpressionDecoder).(CustomExpressionDecoderFunc); ok { |
| return fn |
| } |
| return nil |
| } |