block_register.go (59 lines of code) (raw):
package golden
import (
"github.com/emirpasic/gods/sets"
"github.com/emirpasic/gods/sets/hashset"
"github.com/lonegunmanb/go-defaults"
"reflect"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
type blockConstructor = func(Config, *HclBlock) Block
type blockRegistry map[string]blockConstructor
var validBlockTypes sets.Set = hashset.New()
var refIters = map[string]refIterator{}
var baseFactory = map[string]func() any{}
func RegisterBaseBlock(factory func() BlockType) {
bb := factory()
baseFactory[bb.BlockType()] = func() any {
return factory()
}
}
func RegisterBlock(t Block) {
bt := t.BlockType()
refKeyWord := bt
if s, ok := t.(BlockCustomizedRefType); ok {
refKeyWord = s.CustomizedRefType()
}
registry, ok := factories[bt]
if !ok {
registry = make(blockRegistry)
factories[bt] = registry
}
_, ok = refIters[refKeyWord]
if !ok {
refIters[refKeyWord] = iterator(refKeyWord, t.AddressLength())
}
validBlockTypes.Add(bt)
registry[t.Type()] = func(c Config, hb *HclBlock) Block {
newBlock := reflect.New(reflect.TypeOf(t).Elem()).Elem()
newBaseBlock := NewBaseBlock(c, hb)
newBaseBlock.setForEach(hb.ForEach)
newBaseBlock.setMetaNestedBlock()
newBlock.FieldByName("BaseBlock").Set(reflect.ValueOf(newBaseBlock))
b := newBlock.Addr().Interface().(Block)
if f, ok := baseFactory[bt]; ok {
blockName := cases.Title(language.English).String(bt)
newBlock.FieldByName("Base" + blockName).Set(reflect.ValueOf(f()))
}
defaults.SetDefaults(b)
return b
}
}
func IsBlockTypeWanted(bt string) bool {
return validBlockTypes.Contains(bt)
}
func registerCommonBlock() {
RegisterBlock(new(LocalBlock))
RegisterBlock(new(VariableBlock))
}
var factories = map[string]blockRegistry{}