@@ -17,15 +17,6 @@ package json
17
17
import (
18
18
"bytes"
19
19
"encoding/json"
20
- "math/big"
21
- "strings"
22
-
23
- "cuelang.org/go/cue/ast"
24
- "cuelang.org/go/cue/errors"
25
- "cuelang.org/go/cue/literal"
26
- "cuelang.org/go/cue/token"
27
- "cuelang.org/go/internal"
28
- "cuelang.org/go/internal/astinternal"
29
20
)
30
21
31
22
// Marshal is a replacement for [json.Marshal] without HTML escaping.
@@ -41,282 +32,3 @@ func Marshal(v any) ([]byte, error) {
41
32
p = bytes .TrimSuffix (p , []byte ("\n " ))
42
33
return p , nil
43
34
}
44
-
45
- // Encode converts a CUE AST to unescaped JSON.
46
- //
47
- // The given file must only contain values that can be directly supported by
48
- // JSON:
49
- //
50
- // Type Restrictions
51
- // BasicLit
52
- // File no imports, aliases, or definitions
53
- // StructLit no embeddings, aliases, or definitions
54
- // List
55
- // Field must be regular; label must be a BasicLit or Ident
56
- //
57
- // Comments and attributes are ignored.
58
- func Encode (n ast.Node ) (b []byte , err error ) {
59
- e := encoder {}
60
- err = e .encode (n )
61
- if err != nil {
62
- return nil , err
63
- }
64
- return e .w .Bytes (), nil
65
- }
66
-
67
- type encoder struct {
68
- w bytes.Buffer
69
- tab []byte
70
- indentsAtLevel []int
71
- indenting bool
72
- unIndenting int
73
- }
74
-
75
- func (e * encoder ) writeIndent (b byte ) {
76
- if e .indenting {
77
- e .indentsAtLevel [len (e .indentsAtLevel )- 1 ]++
78
- } else {
79
- e .indentsAtLevel = append (e .indentsAtLevel , 0 )
80
- }
81
- e .indenting = true
82
- _ = e .w .WriteByte (b )
83
- }
84
-
85
- func (e * encoder ) writeUnindent (b byte , pos , def token.Pos ) {
86
- if e .unIndenting > 0 {
87
- e .unIndenting --
88
- } else {
89
- e .unIndenting = e .indentsAtLevel [len (e .indentsAtLevel )- 1 ]
90
- e .indentsAtLevel = e .indentsAtLevel [:len (e .indentsAtLevel )- 1 ]
91
- }
92
- e .indenting = false
93
- e .ws (pos , def .RelPos ())
94
- _ = e .w .WriteByte (b )
95
- }
96
-
97
- func (e * encoder ) writeString (s string ) {
98
- _ , _ = e .w .WriteString (s )
99
- e .indenting = false
100
- }
101
-
102
- func (e * encoder ) writeByte (b byte ) {
103
- _ = e .w .WriteByte (b )
104
- }
105
-
106
- func (e * encoder ) write (b []byte ) {
107
- _ , _ = e .w .Write (b )
108
- e .indenting = false
109
- }
110
-
111
- func (e * encoder ) indent () {
112
- for range e .indentsAtLevel {
113
- e .write (e .tab )
114
- }
115
- }
116
-
117
- func (e * encoder ) ws (pos token.Pos , default_ token.RelPos ) {
118
- rel := pos .RelPos ()
119
- if pos == token .NoPos {
120
- rel = default_
121
- }
122
- switch rel {
123
- case token .NoSpace :
124
- case token .Blank :
125
- e .writeByte (' ' )
126
- case token .Newline :
127
- e .writeByte ('\n' )
128
- e .indent ()
129
- case token .NewSection :
130
- e .writeString ("\n \n " )
131
- e .indent ()
132
- }
133
- }
134
- func (e * encoder ) encode (n ast.Node ) error {
135
- if e .tab == nil {
136
- e .tab = []byte (" " )
137
- }
138
- const defPos = token .NoSpace
139
- switch x := n .(type ) {
140
- case * ast.BasicLit :
141
- e .ws (x .Pos (), defPos )
142
- return e .encodeScalar (x , true )
143
-
144
- case * ast.ListLit :
145
- e .ws (foldNewline (x .Pos ()), token .NoRelPos )
146
- if len (x .Elts ) == 0 {
147
- e .writeString ("[]" )
148
- return nil
149
- }
150
- e .writeIndent ('[' )
151
- for i , x := range x .Elts {
152
- if i > 0 {
153
- e .writeString ("," )
154
- }
155
- if err := e .encode (x ); err != nil {
156
- return err
157
- }
158
- }
159
- e .writeUnindent (']' , x .Rbrack , compactNewline (x .Elts [0 ].Pos ()))
160
- return nil
161
-
162
- case * ast.StructLit :
163
- e .ws (foldNewline (n .Pos ()), token .NoRelPos )
164
- return e .encodeDecls (x .Elts , x .Rbrace )
165
-
166
- case * ast.File :
167
- return e .encodeDecls (x .Decls , token .NoPos )
168
-
169
- case * ast.UnaryExpr :
170
- e .ws (foldNewline (x .Pos ()), defPos )
171
- l , ok := x .X .(* ast.BasicLit )
172
- if ok && x .Op == token .SUB && (l .Kind == token .INT || l .Kind == token .FLOAT ) {
173
- e .writeByte ('-' )
174
- return e .encodeScalar (l , false )
175
- }
176
- }
177
- return errors .Newf (n .Pos (), "json: unsupported node %s (%T)" , astinternal .DebugStr (n ), n )
178
- }
179
-
180
- func (e * encoder ) encodeScalar (l * ast.BasicLit , allowMinus bool ) error {
181
- switch l .Kind {
182
- case token .INT :
183
- var x big.Int
184
- return e .setNum (l , allowMinus , & x )
185
-
186
- case token .FLOAT :
187
- var x big.Float
188
- return e .setNum (l , allowMinus , & x )
189
-
190
- case token .TRUE :
191
- e .writeString ("true" )
192
-
193
- case token .FALSE :
194
- e .writeString ("false" )
195
-
196
- case token .NULL :
197
- e .writeString ("null" )
198
-
199
- case token .STRING :
200
- str , err := literal .Unquote (l .Value )
201
- if err != nil {
202
- return err
203
- }
204
- b , err := Marshal (str )
205
- if err != nil {
206
- return err
207
- }
208
- e .write (b )
209
-
210
- default :
211
- return errors .Newf (l .Pos (), "unknown literal type %v" , l .Kind )
212
- }
213
- return nil
214
- }
215
-
216
- func (e * encoder ) setNum (l * ast.BasicLit , allowMinus bool , x interface {}) error {
217
- if ! allowMinus && strings .HasPrefix (l .Value , "-" ) {
218
- return errors .Newf (l .Pos (), "double minus not allowed" )
219
- }
220
- var ni literal.NumInfo
221
- if err := literal .ParseNum (l .Value , & ni ); err != nil {
222
- return err
223
- }
224
- e .writeString (ni .String ())
225
- return nil
226
- }
227
-
228
- // encodeDecls converts a sequence of declarations to a value. If it encounters
229
- // an embedded value, it will return this expression. This is more relaxed for
230
- // structs than is currently allowed for CUE, but the expectation is that this
231
- // will be allowed at some point. The input would still be illegal CUE.
232
- func (e * encoder ) encodeDecls (decls []ast.Decl , endPos token.Pos ) error {
233
- var embed ast.Expr
234
- var fields []* ast.Field
235
-
236
- for _ , d := range decls {
237
- switch x := d .(type ) {
238
- default :
239
- return errors .Newf (x .Pos (), "json: unsupported node %s (%T)" , astinternal .DebugStr (x ), x )
240
-
241
- case * ast.Package :
242
- if embed != nil || fields != nil {
243
- return errors .Newf (x .Pos (), "invalid package clause" )
244
- }
245
- continue
246
-
247
- case * ast.Field :
248
- if ! internal .IsRegularField (x ) {
249
- return errors .Newf (x .TokenPos , "json: definition or hidden field not allowed" )
250
- }
251
- if x .Optional != token .NoPos {
252
- return errors .Newf (x .Optional , "json: optional fields not allowed" )
253
- }
254
- fields = append (fields , x )
255
-
256
- case * ast.EmbedDecl :
257
- if embed != nil {
258
- return errors .Newf (x .Pos (), "json: multiple embedded values" )
259
- }
260
- embed = x .Expr
261
-
262
- case * ast.CommentGroup :
263
- }
264
- }
265
-
266
- if embed != nil {
267
- if fields != nil {
268
- return errors .Newf (embed .Pos (), "json: embedding mixed with fields" )
269
- }
270
- return e .encode (embed )
271
- }
272
-
273
- if len (fields ) == 0 {
274
- e .writeString ("{}" )
275
- return nil
276
- }
277
-
278
- e .writeIndent ('{' )
279
- pos := compactNewline (fields [0 ].Pos ())
280
- if endPos == token .NoPos && pos .RelPos () == token .Blank {
281
- pos = token .NoPos
282
- }
283
- firstPos := pos
284
- const defPos = token .NoRelPos
285
- for i , x := range fields {
286
- if i > 0 {
287
- e .writeByte (',' )
288
- pos = x .Pos ()
289
- }
290
- name , _ , err := ast .LabelName (x .Label )
291
- if err != nil {
292
- return errors .Newf (x .Label .Pos (), "json: only literal labels allowed" )
293
- }
294
- b , err := Marshal (name )
295
- if err != nil {
296
- return err
297
- }
298
- e .ws (pos , defPos )
299
- e .write (b )
300
- e .writeByte (':' )
301
-
302
- if err := e .encode (x .Value ); err != nil {
303
- return err
304
- }
305
- }
306
- e .writeUnindent ('}' , endPos , firstPos )
307
- return nil
308
- }
309
-
310
- func compactNewline (pos token.Pos ) token.Pos {
311
- if pos .RelPos () == token .NewSection {
312
- pos = token .Newline .Pos ()
313
- }
314
- return pos
315
- }
316
-
317
- func foldNewline (pos token.Pos ) token.Pos {
318
- if pos .RelPos () >= token .Newline {
319
- pos = token .Blank .Pos ()
320
- }
321
- return pos
322
- }
0 commit comments