@@ -48,6 +48,9 @@ const (
4848 // OmitEmptyTag will omit this field if it is a zero value. This
4949 // is similar behavior to `json:",omitempty"`
5050 OmitEmptyTag string = "omitempty"
51+
52+ // Node will omit quotes from the output, useful for references.
53+ Node string = "node"
5154)
5255
5356type fieldMeta struct {
@@ -59,10 +62,11 @@ type fieldMeta struct {
5962 decodedFields bool
6063 omit bool
6164 omitEmpty bool
65+ node bool
6266}
6367
6468// encode converts a reflected valued into an HCL ast.Node in a depth-first manner.
65- func encode (in reflect.Value ) (node ast.Node , key []* ast.ObjectKey , err error ) {
69+ func encode (in reflect.Value , isNode bool ) (node ast.Node , key []* ast.ObjectKey , err error ) {
6670 in , isNil := deref (in )
6771 if isNil {
6872 return nil , nil , nil
@@ -73,16 +77,16 @@ func encode(in reflect.Value) (node ast.Node, key []*ast.ObjectKey, err error) {
7377 case reflect .Bool , reflect .Float64 , reflect .String ,
7478 reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 ,
7579 reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
76- return encodePrimitive (in )
80+ return encodePrimitive (in , isNode )
7781
7882 case reflect .Slice :
79- return encodeList (in )
83+ return encodeList (in , isNode )
8084
8185 case reflect .Map :
82- return encodeMap (in )
86+ return encodeMap (in , isNode )
8387
8488 case reflect .Struct :
85- return encodeStruct (in )
89+ return encodeStruct (in , isNode )
8690
8791 default :
8892 return nil , nil , fmt .Errorf ("cannot encode kind %s to HCL" , in .Kind ())
@@ -92,8 +96,8 @@ func encode(in reflect.Value) (node ast.Node, key []*ast.ObjectKey, err error) {
9296
9397// encodePrimitive converts a primitive value into an ast.LiteralType. An
9498// ast.ObjectKey is never returned.
95- func encodePrimitive (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
96- tkn , err := tokenize (in , false )
99+ func encodePrimitive (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
100+ tkn , err := tokenize (in , isNode )
97101 if err != nil {
98102 return nil , nil , err
99103 }
@@ -103,7 +107,7 @@ func encodePrimitive(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
103107
104108// encodeList converts a slice to an appropriate ast.Node type depending on its
105109// element value type. An ast.ObjectKey is never returned.
106- func encodeList (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
110+ func encodeList (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
107111 childType := in .Type ().Elem ()
108112
109113childLoop:
@@ -118,20 +122,20 @@ childLoop:
118122
119123 switch childType .Kind () {
120124 case reflect .Map , reflect .Struct , reflect .Interface :
121- return encodeBlockList (in )
125+ return encodeBlockList (in , isNode )
122126 default :
123- return encodePrimitiveList (in )
127+ return encodePrimitiveList (in , isNode )
124128 }
125129}
126130
127131// encodePrimitiveList converts a slice of primitive values to an ast.ListType. An
128132// ast.ObjectKey is never returned.
129- func encodePrimitiveList (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
133+ func encodePrimitiveList (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
130134 l := in .Len ()
131135 n := & ast.ListType {List : make ([]ast.Node , 0 , l )}
132136
133137 for i := 0 ; i < l ; i ++ {
134- child , _ , err := encode (in .Index (i ))
138+ child , _ , err := encode (in .Index (i ), isNode )
135139 if err != nil {
136140 return nil , nil , err
137141 }
@@ -145,20 +149,20 @@ func encodePrimitiveList(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
145149
146150// encodeBlockList converts a slice of non-primitive types to an ast.ObjectList. An
147151// ast.ObjectKey is never returned.
148- func encodeBlockList (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
152+ func encodeBlockList (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
149153 l := in .Len ()
150154 n := & ast.ObjectList {Items : make ([]* ast.ObjectItem , 0 , l )}
151155
152156 for i := 0 ; i < l ; i ++ {
153- child , childKey , err := encode (in .Index (i ))
157+ child , childKey , err := encode (in .Index (i ), isNode )
154158 if err != nil {
155159 return nil , nil , err
156160 }
157161 if child == nil {
158162 continue
159163 }
160164 if childKey == nil {
161- return encodePrimitiveList (in )
165+ return encodePrimitiveList (in , isNode )
162166 }
163167
164168 item := & ast.ObjectItem {Val : child }
@@ -171,7 +175,7 @@ func encodeBlockList(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
171175
172176// encodeMap converts a map type into an ast.ObjectType. Maps must have string
173177// key values to be encoded. An ast.ObjectKey is never returned.
174- func encodeMap (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
178+ func encodeMap (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
175179 if keyType := in .Type ().Key ().Kind (); keyType != reflect .String {
176180 return nil , nil , fmt .Errorf ("map keys must be strings, %s given" , keyType )
177181 }
@@ -180,7 +184,7 @@ func encodeMap(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
180184 for _ , key := range in .MapKeys () {
181185 tkn , _ := tokenize (key , true ) // error impossible since we've already checked key kind
182186
183- val , childKey , err := encode (in .MapIndex (key ))
187+ val , childKey , err := encode (in .MapIndex (key ), isNode )
184188 if err != nil {
185189 return nil , nil , err
186190 }
@@ -222,7 +226,7 @@ func encodeMap(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
222226// encodeStruct converts a struct type into an ast.ObjectType. An ast.ObjectKey
223227// may be returned if a KeyTag is present that should be used by a parent
224228// ast.ObjectItem if this node is nested.
225- func encodeStruct (in reflect.Value ) (ast.Node , []* ast.ObjectKey , error ) {
229+ func encodeStruct (in reflect.Value , isNode bool ) (ast.Node , []* ast.ObjectKey , error ) {
226230 l := in .NumField ()
227231 list := & ast.ObjectList {Items : make ([]* ast.ObjectItem , 0 , l )}
228232 keys := make ([]* ast.ObjectKey , 0 )
@@ -248,7 +252,8 @@ func encodeStruct(in reflect.Value) (ast.Node, []*ast.ObjectKey, error) {
248252 }
249253 }
250254
251- val , childKeys , err := encode (rawVal )
255+ isNode = isNode || meta .node
256+ val , childKeys , err := encode (rawVal , isNode )
252257 if err != nil {
253258 return nil , nil , err
254259 }
@@ -386,6 +391,8 @@ func extractFieldMeta(f reflect.StructField) (meta fieldMeta) {
386391 meta .omit = true
387392 case OmitEmptyTag :
388393 meta .omitEmpty = true
394+ case Node :
395+ meta .node = true
389396 }
390397 }
391398
0 commit comments