func (b *Block) DecoderSpec() hcldec.Spec {
	ret := hcldec.ObjectSpec{}
	if b == nil {
		return ret
	}
	for name, attrS := range b.Attributes {
		ret[name] = attrS.decoderSpec(name)
	}
	for name, blockS := range b.BlockTypes {
		if _, exists := ret[name]; exists {
			continue
		}
		childSpec := blockS.Block.DecoderSpec()
		minItems := 0
		if blockS.MinItems > 1 {
			minItems = 1
		}
		switch blockS.Nesting {
		case NestingSingle, NestingGroup:
			ret[name] = &hcldec.BlockSpec{
				TypeName: name,
				Nested:   childSpec,
				Required: blockS.MinItems == 1,
			}
			if blockS.Nesting == NestingGroup {
				ret[name] = &hcldec.DefaultSpec{
					Primary: ret[name],
					Default: &hcldec.LiteralSpec{
						Value: blockS.EmptyValue(),
					},
				}
			}
		case NestingList:
			if blockS.Block.ImpliedType().HasDynamicTypes() {
				ret[name] = &hcldec.BlockTupleSpec{
					TypeName: name,
					Nested:   childSpec,
					MinItems: minItems,
				}
			} else {
				ret[name] = &hcldec.BlockListSpec{
					TypeName: name,
					Nested:   childSpec,
					MinItems: minItems,
				}
			}
		case NestingSet:
			ret[name] = &hcldec.BlockSetSpec{
				TypeName: name,
				Nested:   childSpec,
				MinItems: minItems,
			}
		case NestingMap:
			if blockS.Block.ImpliedType().HasDynamicTypes() {
				ret[name] = &hcldec.BlockObjectSpec{
					TypeName:   name,
					Nested:     childSpec,
					LabelNames: mapLabelNames,
				}
			} else {
				ret[name] = &hcldec.BlockMapSpec{
					TypeName:   name,
					Nested:     childSpec,
					LabelNames: mapLabelNames,
				}
			}
		default:
			continue
		}
	}
	return ret
}
DecoderSpec returns a hcldec.Spec that can be used to decode a HCL Body
using the facilities in the hcldec package.

The returned specification is guaranteed to return a value of the same type
returned by method ImpliedType, but it may contain null values if any of the
block attributes are defined as optional and/or computed respectively.
package configschema
import (
	"github.com/hashicorp/hcl/v2/hcldec"
)
var mapLabelNames = []string{"key"}