hcl/hcldec/public.go
Martin Atkins 6c4344623b Unfold the "hcl" directory up into the root
The main HCL package is more visible this way, and so it's easier than
having to pick it out from dozens of other package directories.
2019-09-09 16:08:19 -07:00

82 lines
3.0 KiB
Go

package hcldec
import (
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
)
// Decode interprets the given body using the given specification and returns
// the resulting value. If the given body is not valid per the spec, error
// diagnostics are returned and the returned value is likely to be incomplete.
//
// The ctx argument may be nil, in which case any references to variables or
// functions will produce error diagnostics.
func Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
val, _, diags := decode(body, nil, ctx, spec, false)
return val, diags
}
// PartialDecode is like Decode except that it permits "leftover" items in
// the top-level body, which are returned as a new body to allow for
// further processing.
//
// Any descendent block bodies are _not_ decoded partially and thus must
// be fully described by the given specification.
func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics) {
return decode(body, nil, ctx, spec, true)
}
// ImpliedType returns the value type that should result from decoding the
// given spec.
func ImpliedType(spec Spec) cty.Type {
return impliedType(spec)
}
// SourceRange interprets the given body using the given specification and
// then returns the source range of the value that would be used to
// fulfill the spec.
//
// This can be used if application-level validation detects value errors, to
// obtain a reasonable SourceRange to use for generated diagnostics. It works
// best when applied to specific body items (e.g. using AttrSpec, BlockSpec, ...)
// as opposed to entire bodies using ObjectSpec, TupleSpec. The result will
// be less useful the broader the specification, so e.g. a spec that returns
// the entirety of all of the blocks of a given type is likely to be
// _particularly_ arbitrary and useless.
//
// If the given body is not valid per the given spec, the result is best-effort
// and may not actually be something ideal. It's expected that an application
// will already have used Decode or PartialDecode earlier and thus had an
// opportunity to detect and report spec violations.
func SourceRange(body hcl.Body, spec Spec) hcl.Range {
return sourceRange(body, nil, spec)
}
// ChildBlockTypes returns a map of all of the child block types declared
// by the given spec, with block type names as keys and the associated
// nested body specs as values.
func ChildBlockTypes(spec Spec) map[string]Spec {
ret := map[string]Spec{}
// visitSameBodyChildren walks through the spec structure, calling
// the given callback for each descendent spec encountered. We are
// interested in the specs that reference attributes and blocks.
var visit visitFunc
visit = func(s Spec) {
if bs, ok := s.(blockSpec); ok {
for _, blockS := range bs.blockHeaderSchemata() {
nested := bs.nestedSpec()
if nested != nil { // nil can be returned to dynamically opt out of this interface
ret[blockS.Type] = nested
}
}
}
s.visitSameBodyChildren(visit)
}
visit(spec)
return ret
}