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 // We can only validate 0 or 1 for MinItems, because a dynamic block
37 // may satisfy any number of min items while only having a single
38 // block in the config.
40 if blockS.MinItems > 1 {
44 switch blockS.Nesting {
45 case NestingSingle, NestingGroup:
46 ret[name] = &hcldec.BlockSpec{
49 Required: blockS.MinItems == 1 && blockS.MaxItems >= 1,
51 if blockS.Nesting == NestingGroup {
52 ret[name] = &hcldec.DefaultSpec{
54 Default: &hcldec.LiteralSpec{
55 Value: blockS.EmptyValue(),
60 // We prefer to use a list where possible, since it makes our
61 // implied type more complete, but if there are any
62 // dynamically-typed attributes inside we must use a tuple
63 // instead, at the expense of our type then not being predictable.
64 if blockS.Block.ImpliedType().HasDynamicTypes() {
65 ret[name] = &hcldec.BlockTupleSpec{
69 MaxItems: blockS.MaxItems,
72 ret[name] = &hcldec.BlockListSpec{
76 MaxItems: blockS.MaxItems,
80 // We forbid dynamically-typed attributes inside NestingSet in
81 // InternalValidate, so we don't do anything special to handle
82 // that here. (There is no set analog to tuple and object types,
83 // because cty's set implementation depends on knowing the static
84 // type in order to properly compute its internal hashes.)
85 ret[name] = &hcldec.BlockSetSpec{
89 MaxItems: blockS.MaxItems,
92 // We prefer to use a list where possible, since it makes our
93 // implied type more complete, but if there are any
94 // dynamically-typed attributes inside we must use a tuple
95 // instead, at the expense of our type then not being predictable.
96 if blockS.Block.ImpliedType().HasDynamicTypes() {
97 ret[name] = &hcldec.BlockObjectSpec{
100 LabelNames: mapLabelNames,
103 ret[name] = &hcldec.BlockMapSpec{
106 LabelNames: mapLabelNames,
110 // Invalid nesting type is just ignored. It's checked by
119 func (a *Attribute) decoderSpec(name string) hcldec.Spec {
120 return &hcldec.AttrSpec{
123 Required: a.Required,