@@ -27,6 +27,11 @@ const (
2727 // the key for the value.
2828 SquashTag string = "squash"
2929
30+ // Blocks is attached to a slice of objects and indicates that
31+ // the slice should be treated as multiple separate blocks rather than
32+ // a list.
33+ Blocks string = "blocks"
34+
3035 // UnusedKeysTag is a flag that indicates any unused keys found by the
3136 // decoder are stored in this field of type []string. This has the same
3237 // behavior as the OmitTag and is not encoded.
@@ -55,14 +60,19 @@ type fieldMeta struct {
5560 name string
5661 key bool
5762 squash bool
63+ repeatBlock bool
5864 unusedKeys bool
5965 decodedFields bool
6066 omit bool
6167 omitEmpty bool
6268}
6369
64- // encode converts a reflected valued into an HCL ast.Node in a depth-first manner.
6570func encode (in reflect.Value ) (node ast.Node , key []* ast.ObjectKey , err error ) {
71+ return encodeField (in , fieldMeta {})
72+ }
73+
74+ // encode converts a reflected valued into an HCL ast.Node in a depth-first manner.
75+ func encodeField (in reflect.Value , meta fieldMeta ) (node ast.Node , key []* ast.ObjectKey , err error ) {
6676 in , isNil := deref (in )
6777 if isNil {
6878 return nil , nil , nil
@@ -76,7 +86,7 @@ func encode(in reflect.Value) (node ast.Node, key []*ast.ObjectKey, err error) {
7686 return encodePrimitive (in )
7787
7888 case reflect .Slice :
79- return encodeList (in )
89+ return encodeList (in , meta . repeatBlock )
8090
8191 case reflect .Map :
8292 return encodeMap (in )
@@ -87,7 +97,6 @@ func encode(in reflect.Value) (node ast.Node, key []*ast.ObjectKey, err error) {
8797 default :
8898 return nil , nil , fmt .Errorf ("cannot encode kind %s to HCL" , in .Kind ())
8999 }
90-
91100}
92101
93102// encodePrimitive converts a primitive value into an ast.LiteralType. An
@@ -103,7 +112,7 @@ func encodePrimitive(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
103112
104113// encodeList converts a slice to an appropriate ast.Node type depending on its
105114// element value type. An ast.ObjectKey is never returned.
106- func encodeList (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
115+ func encodeList (in reflect.Value , repeatBlock bool ) (ast.Node , []* ast.ObjectKey , error ) {
107116 childType := in .Type ().Elem ()
108117
109118childLoop:
@@ -118,7 +127,7 @@ childLoop:
118127
119128 switch childType .Kind () {
120129 case reflect .Map , reflect .Struct , reflect .Interface :
121- return encodeBlockList (in )
130+ return encodeBlockList (in , repeatBlock )
122131 default :
123132 return encodePrimitiveList (in )
124133 }
@@ -145,7 +154,7 @@ func encodePrimitiveList(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
145154
146155// encodeBlockList converts a slice of non-primitive types to an ast.ObjectList. An
147156// ast.ObjectKey is never returned.
148- func encodeBlockList (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
157+ func encodeBlockList (in reflect.Value , repeatBlock bool ) (ast.Node , []* ast.ObjectKey , error ) {
149158 l := in .Len ()
150159 n := & ast.ObjectList {Items : make ([]* ast.ObjectItem , 0 , l )}
151160
@@ -157,7 +166,7 @@ func encodeBlockList(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
157166 if child == nil {
158167 continue
159168 }
160- if childKey == nil {
169+ if childKey == nil && ! repeatBlock {
161170 return encodePrimitiveList (in )
162171 }
163172
@@ -248,7 +257,7 @@ func encodeStruct(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
248257 }
249258 }
250259
251- val , childKeys , err := encode (rawVal )
260+ val , childKeys , err := encodeField (rawVal , meta )
252261 if err != nil {
253262 return nil , nil , err
254263 }
@@ -375,6 +384,8 @@ func extractFieldMeta(f reflect.StructField) (meta fieldMeta) {
375384 meta .decodedFields = true
376385 case UnusedKeysTag :
377386 meta .unusedKeys = true
387+ case Blocks :
388+ meta .repeatBlock = true
378389 }
379390 }
380391 }
0 commit comments