4 "github.com/hashicorp/hcl2/hcldec"
7 var mapLabelNames = []string{"key"}
9 // DecoderSpec returns a hcldec.Spec that can be used to decode a HCL Body
10 // using the facilities in the hcldec package.
12 // The returned specification is guaranteed to return a value of the same type
13 // returned by method ImpliedType, but it may contain null values if any of the
14 // block attributes are defined as optional and/or computed respectively.
15 func (b *Block) DecoderSpec() hcldec.Spec {
16 ret := hcldec.ObjectSpec{}
21 for name, attrS := range b.Attributes {
22 ret[name] = attrS.decoderSpec(name)
25 for name, blockS := range b.BlockTypes {
26 if _, exists := ret[name]; exists {
27 // This indicates an invalid schema, since it's not valid to
28 // define both an attribute and a block type of the same name.
29 // However, we don't raise this here since it's checked by
34 childSpec := blockS.Block.DecoderSpec()
36 switch blockS.Nesting {
37 case NestingSingle, NestingGroup:
38 ret[name] = &hcldec.BlockSpec{
41 Required: blockS.MinItems == 1 && blockS.MaxItems >= 1,
43 if blockS.Nesting == NestingGroup {
44 ret[name] = &hcldec.DefaultSpec{
46 Default: &hcldec.LiteralSpec{
47 Value: blockS.EmptyValue(),
52 // We prefer to use a list where possible, since it makes our
53 // implied type more complete, but if there are any
54 // dynamically-typed attributes inside we must use a tuple
55 // instead, at the expense of our type then not being predictable.
56 if blockS.Block.ImpliedType().HasDynamicTypes() {
57 ret[name] = &hcldec.BlockTupleSpec{
60 MinItems: blockS.MinItems,
61 MaxItems: blockS.MaxItems,
64 ret[name] = &hcldec.BlockListSpec{
67 MinItems: blockS.MinItems,
68 MaxItems: blockS.MaxItems,
72 // We forbid dynamically-typed attributes inside NestingSet in
73 // InternalValidate, so we don't do anything special to handle
74 // that here. (There is no set analog to tuple and object types,
75 // because cty's set implementation depends on knowing the static
76 // type in order to properly compute its internal hashes.)
77 ret[name] = &hcldec.BlockSetSpec{
80 MinItems: blockS.MinItems,
81 MaxItems: blockS.MaxItems,
84 // We prefer to use a list where possible, since it makes our
85 // implied type more complete, but if there are any
86 // dynamically-typed attributes inside we must use a tuple
87 // instead, at the expense of our type then not being predictable.
88 if blockS.Block.ImpliedType().HasDynamicTypes() {
89 ret[name] = &hcldec.BlockObjectSpec{
92 LabelNames: mapLabelNames,
95 ret[name] = &hcldec.BlockMapSpec{
98 LabelNames: mapLabelNames,
102 // Invalid nesting type is just ignored. It's checked by
111 func (a *Attribute) decoderSpec(name string) hcldec.Spec {
112 return &hcldec.AttrSpec{
115 Required: a.Required,