github.com/hashicorp/hcl/v2@v2.20.0/hcldec/public.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package hcldec 5 6 import ( 7 "github.com/hashicorp/hcl/v2" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 // Decode interprets the given body using the given specification and returns 12 // the resulting value. If the given body is not valid per the spec, error 13 // diagnostics are returned and the returned value is likely to be incomplete. 14 // 15 // The ctx argument may be nil, in which case any references to variables or 16 // functions will produce error diagnostics. 17 func Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 18 val, _, diags := decode(body, nil, ctx, spec, false) 19 return val, diags 20 } 21 22 // PartialDecode is like Decode except that it permits "leftover" items in 23 // the top-level body, which are returned as a new body to allow for 24 // further processing. 25 // 26 // Any descendent block bodies are _not_ decoded partially and thus must 27 // be fully described by the given specification. 28 func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics) { 29 return decode(body, nil, ctx, spec, true) 30 } 31 32 // ImpliedType returns the value type that should result from decoding the 33 // given spec. 34 func ImpliedType(spec Spec) cty.Type { 35 return impliedType(spec) 36 } 37 38 // SourceRange interprets the given body using the given specification and 39 // then returns the source range of the value that would be used to 40 // fulfill the spec. 41 // 42 // This can be used if application-level validation detects value errors, to 43 // obtain a reasonable SourceRange to use for generated diagnostics. It works 44 // best when applied to specific body items (e.g. using AttrSpec, BlockSpec, ...) 45 // as opposed to entire bodies using ObjectSpec, TupleSpec. The result will 46 // be less useful the broader the specification, so e.g. a spec that returns 47 // the entirety of all of the blocks of a given type is likely to be 48 // _particularly_ arbitrary and useless. 49 // 50 // If the given body is not valid per the given spec, the result is best-effort 51 // and may not actually be something ideal. It's expected that an application 52 // will already have used Decode or PartialDecode earlier and thus had an 53 // opportunity to detect and report spec violations. 54 func SourceRange(body hcl.Body, spec Spec) hcl.Range { 55 return sourceRange(body, nil, spec) 56 } 57 58 // ChildBlockTypes returns a map of all of the child block types declared 59 // by the given spec, with block type names as keys and the associated 60 // nested body specs as values. 61 func ChildBlockTypes(spec Spec) map[string]Spec { 62 ret := map[string]Spec{} 63 64 // visitSameBodyChildren walks through the spec structure, calling 65 // the given callback for each descendent spec encountered. We are 66 // interested in the specs that reference attributes and blocks. 67 var visit visitFunc 68 visit = func(s Spec) { 69 if bs, ok := s.(blockSpec); ok { 70 for _, blockS := range bs.blockHeaderSchemata() { 71 nested := bs.nestedSpec() 72 if nested != nil { // nil can be returned to dynamically opt out of this interface 73 ret[blockS.Type] = nested 74 } 75 } 76 } 77 78 s.visitSameBodyChildren(visit) 79 } 80 81 visit(spec) 82 83 return ret 84 }