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  }