this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cmd/cue: hook up encoding/toml for import and export

This includes adding TOML to internal/filetypes and internal/encoding
so that other APIs such as cue/load work with TOML too.

Note that this required tweaking encoding/toml's decoder so that
it returns ast.Expr nodes as the internal/encoding types expect.
This is not a hard change to make, as a TOML document is just a list
of top-level fields which can be represented by a struct literal too.

Fixes #68.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: I0eeeaf198a336e82caaed96aac3b5bbcbae57d57
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1198540
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+83 -14
+1 -1
cmd/cue/cmd/common.go
··· 433 433 f.Interpretation = p.cfg.interpretation 434 434 } 435 435 switch f.Encoding { 436 - case build.Protobuf, build.YAML, build.JSON, build.JSONL, 436 + case build.Protobuf, build.YAML, build.TOML, build.JSON, build.JSONL, 437 437 build.Text, build.Binary: 438 438 if f.Interpretation == build.ProtobufJSON { 439 439 // Need a schema.
+4 -1
cmd/cue/cmd/import.go
··· 54 54 Mode Extensions 55 55 json Look for JSON files (.json, .jsonl, .ldjson). 56 56 yaml Look for YAML files (.yaml .yml). 57 + toml Look for TOML files (.toml). 57 58 text Look for text files (.txt). 58 59 binary Look for files with extensions specified by --ext 59 60 and interpret them as binary. ··· 267 268 268 269 func runImport(cmd *Command, args []string) (err error) { 269 270 c := &config{ 270 - fileFilter: `\.(json|yaml|yml|jsonl|ldjson)$`, 271 + fileFilter: `\.(json|yaml|yml|toml|jsonl|ldjson)$`, 271 272 interpretation: build.Auto, 272 273 loadCfg: &load.Config{DataFiles: true}, 273 274 } ··· 290 291 c.fileFilter = `\.(json|jsonl|ldjson)$` 291 292 case "yaml": 292 293 c.fileFilter = `\.(yaml|yml)$` 294 + case "toml": 295 + c.fileFilter = `\.toml$` 293 296 case "text": 294 297 c.fileFilter = `\.txt$` 295 298 case "binary":
+46
cmd/cue/cmd/testdata/script/encoding_toml.txtar
··· 1 + # Test that the TOML encoding is fully supported in cmd/cue. 2 + 3 + exec cue export --out toml . 4 + cmp stdout export.toml 5 + 6 + exec cue export --out json export.toml 7 + cmp stdout export.json 8 + 9 + exec cue import -o - export.toml 10 + cmp stdout import.cue 11 + exec cue import -o - toml . 12 + cmp stdout import.cue 13 + 14 + -- export.toml -- 15 + message = 'Hello World!' 16 + 17 + [nested] 18 + a1 = 'one level' 19 + 20 + [nested.a2] 21 + b = 'two levels' 22 + -- export.json -- 23 + { 24 + "message": "Hello World!", 25 + "nested": { 26 + "a1": "one level", 27 + "a2": { 28 + "b": "two levels" 29 + } 30 + } 31 + } 32 + -- import.cue -- 33 + message: "Hello World!" 34 + nested: a1: "one level" 35 + nested: a2: b: "two levels" 36 + -- data.cue -- 37 + package hello 38 + 39 + _who: "World" 40 + -- hello.cue -- 41 + package hello 42 + 43 + message: "Hello \(_who)!" // who declared in data.cue 44 + 45 + nested: a1: "one level" 46 + nested: a2: b: "two levels"
+1 -3
cue/build/file.go
··· 36 36 CUE Encoding = "cue" 37 37 JSON Encoding = "json" 38 38 YAML Encoding = "yaml" 39 + TOML Encoding = "toml" 39 40 JSONL Encoding = "jsonl" 40 41 Text Encoding = "text" 41 42 Binary Encoding = "binary" 42 43 Protobuf Encoding = "proto" 43 44 TextProto Encoding = "textproto" 44 45 BinaryProto Encoding = "pb" 45 - 46 - // TODO: 47 - // TOML 48 46 49 47 Code Encoding = "code" // Programming languages 50 48 )
+7 -6
encoding/toml/decode.go
··· 55 55 seenTableKeys map[rootedKey]bool 56 56 57 57 // topFile is the top-level CUE file we are decoding into. 58 - topFile *ast.File 58 + // TODO(mvdan): make an *ast.File once the decoder returns ast.Node rather than ast.Expr. 59 + topFile *ast.StructLit 59 60 60 61 // openTableArrays keeps track of all the declared table arrays so that 61 62 // later headers can append a new table array element, or add a field ··· 108 109 // Decode parses the input stream as TOML and converts it to a CUE [*ast.File]. 109 110 // Because TOML files only contain a single top-level expression, 110 111 // subsequent calls to this method may return [io.EOF]. 111 - func (d *Decoder) Decode() (ast.Node, error) { 112 + func (d *Decoder) Decode() (ast.Expr, error) { 112 113 if d.decoded { 113 114 return nil, io.EOF 114 115 } ··· 122 123 // Note that if the input is empty the result will be the same 123 124 // as for an empty table: an empty struct. 124 125 // The TOML spec and other decoders also work this way. 125 - d.topFile = &ast.File{} 126 + d.topFile = &ast.StructLit{} 126 127 for d.parser.NextExpression() { 127 128 if err := d.nextRootNode(d.parser.Expression()); err != nil { 128 129 return nil, err ··· 167 168 if d.currentTable != nil { 168 169 d.currentTable.Elts = append(d.currentTable.Elts, field) 169 170 } else { 170 - d.topFile.Decls = append(d.topFile.Decls, field) 171 + d.topFile.Elts = append(d.topFile.Elts, field) 171 172 } 172 173 173 174 case toml.Table: ··· 196 197 leafField.Value = d.currentTable 197 198 } else { // [new_table] 198 199 topField, leafField := inlineFields(keyElems, token.Newline) 199 - d.topFile.Decls = append(d.topFile.Decls, topField) 200 + d.topFile.Elts = append(d.topFile.Elts, topField) 200 201 leafField.Value = d.currentTable 201 202 } 202 203 d.currentTableKey = key ··· 228 229 if array == nil { 229 230 // [[new_array]] - at the top level 230 231 topField, leafField := inlineFields(keyElems, token.Newline) 231 - d.topFile.Decls = append(d.topFile.Decls, topField) 232 + d.topFile.Elts = append(d.topFile.Elts, topField) 232 233 leafField.Value = list 233 234 } else { 234 235 // [[last_array.new_array]] - on the last array element
+6 -3
encoding/toml/decode_test.go
··· 23 23 "github.com/go-quicktest/qt" 24 24 gotoml "github.com/pelletier/go-toml/v2" 25 25 26 - "cuelang.org/go/cue/ast" 26 + "cuelang.org/go/cue/ast/astutil" 27 27 "cuelang.org/go/cue/cuecontext" 28 28 "cuelang.org/go/cue/format" 29 29 "cuelang.org/go/encoding/toml" ··· 729 729 } 730 730 qt.Assert(t, qt.IsNil(err)) 731 731 732 + file, err := astutil.ToFile(node) 733 + qt.Assert(t, qt.IsNil(err)) 734 + 732 735 node2, err := dec.Decode() 733 736 qt.Assert(t, qt.IsNil(node2)) 734 737 qt.Assert(t, qt.Equals(err, io.EOF)) ··· 736 739 wantFormatted, err := format.Source([]byte(test.wantCUE)) 737 740 qt.Assert(t, qt.IsNil(err), qt.Commentf("wantCUE:\n%s", test.wantCUE)) 738 741 739 - formatted, err := format.Node(node) 742 + formatted, err := format.Node(file) 740 743 qt.Assert(t, qt.IsNil(err)) 741 744 t.Logf("CUE:\n%s", formatted) 742 745 qt.Assert(t, qt.Equals(string(formatted), string(wantFormatted))) ··· 745 748 ctx := cuecontext.New() 746 749 // TODO(mvdan): cue.Context can only build ast.Expr or ast.File, not ast.Node; 747 750 // it's then likely not the right choice for the interface to return ast.Node. 748 - val := ctx.BuildFile(node.(*ast.File)) 751 + val := ctx.BuildFile(file) 749 752 qt.Assert(t, qt.IsNil(val.Err())) 750 753 qt.Assert(t, qt.IsNil(val.Validate())) 751 754
+6
internal/encoding/encoder.go
··· 32 32 "cuelang.org/go/encoding/openapi" 33 33 "cuelang.org/go/encoding/protobuf/jsonpb" 34 34 "cuelang.org/go/encoding/protobuf/textproto" 35 + "cuelang.org/go/encoding/toml" 35 36 "cuelang.org/go/internal" 36 37 "cuelang.org/go/internal/filetypes" 37 38 "cuelang.org/go/pkg/encoding/yaml" ··· 194 195 _, err = fmt.Fprint(w, str) 195 196 return err 196 197 } 198 + 199 + case build.TOML: 200 + e.concrete = true 201 + enc := toml.NewEncoder(w) 202 + e.encValue = enc.Encode 197 203 198 204 case build.TextProto: 199 205 // TODO: verify that the schema is given. Otherwise err out.
+4
internal/encoding/encoding.go
··· 37 37 "cuelang.org/go/encoding/protobuf" 38 38 "cuelang.org/go/encoding/protobuf/jsonpb" 39 39 "cuelang.org/go/encoding/protobuf/textproto" 40 + "cuelang.org/go/encoding/toml" 40 41 "cuelang.org/go/internal" 41 42 "cuelang.org/go/internal/encoding/yaml" 42 43 "cuelang.org/go/internal/filetypes" ··· 246 247 b, err := io.ReadAll(r) 247 248 i.err = err 248 249 i.next = yaml.NewDecoder(path, b).Decode 250 + i.Next() 251 + case build.TOML: 252 + i.next = toml.NewDecoder(r).Decode 249 253 i.Next() 250 254 case build.Text: 251 255 b, err := io.ReadAll(r)
+8
internal/filetypes/types.cue
··· 92 92 extensions: ".json": interpretation: *"auto" | _ 93 93 extensions: ".yaml": interpretation: *"auto" | _ 94 94 extensions: ".yml": interpretation: *"auto" | _ 95 + extensions: ".toml": interpretation: *"auto" | _ 95 96 } 96 97 97 98 modes: export: { ··· 168 169 ".ndjson": tags.jsonl 169 170 ".yaml": tags.yaml 170 171 ".yml": tags.yaml 172 + ".toml": tags.toml 171 173 ".txt": tags.text 172 174 ".go": tags.go 173 175 ".wasm": tags.binary ··· 190 192 stream: *false | true 191 193 docs: false 192 194 attributes: false 195 + } 196 + 197 + encodings: yaml: { 198 + forms.graph 199 + stream: false | *true 193 200 } 194 201 195 202 encodings: yaml: { ··· 332 339 json: encoding: "json" 333 340 jsonl: encoding: "jsonl" 334 341 yaml: encoding: "yaml" 342 + toml: encoding: "toml" 335 343 proto: encoding: "proto" 336 344 textproto: encoding: "textproto" 337 345 // "binpb": encodings.binproto