├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENCE ├── README.md ├── build.zig ├── examples ├── serialize-custom │ ├── build.zig │ └── src │ │ └── main.zig ├── serialize │ ├── build.zig │ └── src │ │ └── main.zig └── simple │ ├── build.zig │ └── src │ └── main.zig ├── flake.lock ├── flake.nix ├── gyro.zzz ├── src ├── fuzz.zig ├── integration_tests.zig ├── lexer.zig ├── main.zig ├── parser.zig ├── print_failing_tests.zig ├── serializer.zig └── toml2json.zig ├── tests ├── .gitattributes ├── COPYING ├── fuzzing │ ├── id-000000,sig-06,src-000024,time-10060,execs-1850,op-havoc,rep-4 │ ├── id-000000,sig-06,src-000035,time-345,execs-551,op-havoc,rep-2 │ └── id-000000,sig-06,src-000052+000007,time-701543,execs-28399,op-splice,rep-2 ├── invalid │ ├── array │ │ ├── double-comma-1.toml │ │ ├── double-comma-2.toml │ │ ├── extending-table.toml │ │ ├── missing-separator.toml │ │ ├── no-close-2.toml │ │ ├── no-close-table-2.toml │ │ ├── no-close-table.toml │ │ ├── no-close.toml │ │ ├── tables-1.toml │ │ ├── tables-2.toml │ │ ├── text-after-array-entries.toml │ │ ├── text-before-array-separator.toml │ │ └── text-in-array.toml │ ├── bool │ │ ├── almost-false-with-extra.toml │ │ ├── almost-false.toml │ │ ├── almost-true-with-extra.toml │ │ ├── almost-true.toml │ │ ├── just-f.toml │ │ ├── just-t.toml │ │ ├── mixed-case.toml │ │ ├── starting-same-false.toml │ │ ├── starting-same-true.toml │ │ ├── wrong-case-false.toml │ │ └── wrong-case-true.toml │ ├── control │ │ ├── bare-cr.toml │ │ ├── bare-formfeed.toml │ │ ├── bare-null.toml │ │ ├── bare-vertical-tab.toml │ │ ├── comment-cr.toml │ │ ├── comment-del.toml │ │ ├── comment-lf.toml │ │ ├── comment-null.toml │ │ ├── comment-us.toml │ │ ├── control.multi │ │ ├── multi-del.toml │ │ ├── multi-lf.toml │ │ ├── multi-null.toml │ │ ├── multi-us.toml │ │ ├── rawmulti-del.toml │ │ ├── rawmulti-lf.toml │ │ ├── rawmulti-null.toml │ │ ├── rawmulti-us.toml │ │ ├── rawstring-del.toml │ │ ├── rawstring-lf.toml │ │ ├── rawstring-null.toml │ │ ├── rawstring-us.toml │ │ ├── string-bs.toml │ │ ├── string-del.toml │ │ ├── string-lf.toml │ │ ├── string-null.toml │ │ └── string-us.toml │ ├── datetime │ │ ├── hour-over.toml │ │ ├── mday-over.toml │ │ ├── mday-under.toml │ │ ├── minute-over.toml │ │ ├── month-over.toml │ │ ├── month-under.toml │ │ ├── no-leads-with-milli.toml │ │ ├── no-leads.toml │ │ ├── no-secs.toml │ │ ├── no-t.toml │ │ ├── second-over.toml │ │ ├── time-no-leads-2.toml │ │ ├── time-no-leads.toml │ │ └── trailing-t.toml │ ├── encoding │ │ ├── bad-utf8-at-end.toml │ │ ├── bad-utf8-in-comment.toml │ │ ├── bad-utf8-in-string.toml │ │ ├── bom-not-at-start-1.toml │ │ ├── bom-not-at-start-2.toml │ │ ├── utf16-bom.toml │ │ └── utf16.toml │ ├── float │ │ ├── double-point-1.toml │ │ ├── double-point-2.toml │ │ ├── exp-double-e-1.toml │ │ ├── exp-double-e-2.toml │ │ ├── exp-double-us.toml │ │ ├── exp-leading-us.toml │ │ ├── exp-point-1.toml │ │ ├── exp-point-2.toml │ │ ├── exp-trailing-us.toml │ │ ├── float.multi │ │ ├── inf-incomplete-1.toml │ │ ├── inf-incomplete-2.toml │ │ ├── inf-incomplete-3.toml │ │ ├── inf_underscore.toml │ │ ├── leading-point-neg.toml │ │ ├── leading-point-plus.toml │ │ ├── leading-point.toml │ │ ├── leading-us.toml │ │ ├── leading-zero-neg.toml │ │ ├── leading-zero-plus.toml │ │ ├── leading-zero.toml │ │ ├── nan-incomplete-1.toml │ │ ├── nan-incomplete-2.toml │ │ ├── nan-incomplete-3.toml │ │ ├── nan_underscore.toml │ │ ├── trailing-point-min.toml │ │ ├── trailing-point-plus.toml │ │ ├── trailing-point.toml │ │ ├── trailing-us-exp.toml │ │ ├── trailing-us.toml │ │ ├── us-after-point.toml │ │ └── us-before-point.toml │ ├── inline-table │ │ ├── add.toml │ │ ├── double-comma.toml │ │ ├── duplicate-key.toml │ │ ├── empty.toml │ │ ├── linebreak-1.toml │ │ ├── linebreak-2.toml │ │ ├── linebreak-3.toml │ │ ├── linebreak-4.toml │ │ ├── no-comma.toml │ │ ├── overwrite.toml │ │ └── trailing-comma.toml │ ├── integer │ │ ├── capital-bin.toml │ │ ├── capital-hex.toml │ │ ├── capital-oct.toml │ │ ├── double-sign-nex.toml │ │ ├── double-sign-plus.toml │ │ ├── double-us.toml │ │ ├── incomplete-bin.toml │ │ ├── incomplete-hex.toml │ │ ├── incomplete-oct.toml │ │ ├── integer.multi │ │ ├── invalid-bin.toml │ │ ├── invalid-hex.toml │ │ ├── invalid-oct.toml │ │ ├── leading-us-bin.toml │ │ ├── leading-us-hex.toml │ │ ├── leading-us-oct.toml │ │ ├── leading-us.toml │ │ ├── leading-zero-1.toml │ │ ├── leading-zero-2.toml │ │ ├── leading-zero-3.toml │ │ ├── leading-zero-sign-1.toml │ │ ├── leading-zero-sign-2.toml │ │ ├── leading-zero-sign-3.toml │ │ ├── negative-bin.toml │ │ ├── negative-hex.toml │ │ ├── negative-oct.toml │ │ ├── positive-bin.toml │ │ ├── positive-hex.toml │ │ ├── positive-oct.toml │ │ ├── text-after-integer.toml │ │ ├── trailing-us-bin.toml │ │ ├── trailing-us-hex.toml │ │ ├── trailing-us-oct.toml │ │ ├── trailing-us.toml │ │ ├── us-after-bin.toml │ │ ├── us-after-hex.toml │ │ └── us-after-oct.toml │ ├── key │ │ ├── after-array.toml │ │ ├── after-table.toml │ │ ├── after-value.toml │ │ ├── bare-invalid-character.toml │ │ ├── dotted-redefine-table.toml │ │ ├── duplicate-keys.toml │ │ ├── duplicate.toml │ │ ├── empty.toml │ │ ├── escape.toml │ │ ├── hash.toml │ │ ├── multiline.toml │ │ ├── newline.toml │ │ ├── no-eol.toml │ │ ├── open-bracket.toml │ │ ├── partial-quoted.toml │ │ ├── quoted-unclosed-1.toml │ │ ├── quoted-unclosed-2.toml │ │ ├── single-open-bracket.toml │ │ ├── space.toml │ │ ├── special-character.toml │ │ ├── start-bracket.toml │ │ ├── start-dot.toml │ │ ├── two-equals.toml │ │ ├── two-equals2.toml │ │ ├── two-equals3.toml │ │ ├── without-value-1.toml │ │ ├── without-value-2.toml │ │ ├── without-value-3.toml │ │ └── without-value-4.toml │ ├── string │ │ ├── bad-byte-escape.toml │ │ ├── bad-codepoint.toml │ │ ├── bad-concat.toml │ │ ├── bad-escape-1.toml │ │ ├── bad-escape-2.toml │ │ ├── bad-multiline.toml │ │ ├── bad-slash-escape.toml │ │ ├── bad-uni-esc-1.toml │ │ ├── bad-uni-esc-2.toml │ │ ├── bad-uni-esc-3.toml │ │ ├── bad-uni-esc-4.toml │ │ ├── bad-uni-esc-5.toml │ │ ├── basic-byte-escapes.toml │ │ ├── basic-multiline-out-of-range-unicode-escape-1.toml │ │ ├── basic-multiline-out-of-range-unicode-escape-2.toml │ │ ├── basic-multiline-quotes.toml │ │ ├── basic-multiline-unknown-escape.toml │ │ ├── basic-out-of-range-unicode-escape-1.toml │ │ ├── basic-out-of-range-unicode-escape-2.toml │ │ ├── basic-unknown-escape.toml │ │ ├── literal-multiline-quotes-1.toml │ │ ├── literal-multiline-quotes-2.toml │ │ ├── missing-quotes.toml │ │ ├── multiline-bad-escape-1.toml │ │ ├── multiline-bad-escape-2.toml │ │ ├── multiline-bad-escape-3.toml │ │ ├── multiline-escape-space.toml │ │ ├── multiline-no-close-2.toml │ │ ├── multiline-no-close.toml │ │ ├── multiline-quotes-1.toml │ │ ├── no-close.toml │ │ ├── text-after-string.toml │ │ └── wrong-close.toml │ └── table │ │ ├── append-with-dotted-keys-1.toml │ │ ├── append-with-dotted-keys-2.toml │ │ ├── array-empty.toml │ │ ├── array-implicit.toml │ │ ├── array-missing-bracket.toml │ │ ├── duplicate-key-dotted-table.toml │ │ ├── duplicate-key-dotted-table2.toml │ │ ├── duplicate-key-table.toml │ │ ├── duplicate-table-array.toml │ │ ├── duplicate-table-array2.toml │ │ ├── duplicate.toml │ │ ├── empty-implicit-table.toml │ │ ├── empty.toml │ │ ├── equals-sign.toml │ │ ├── llbrace.toml │ │ ├── nested-brackets-close.toml │ │ ├── nested-brackets-open.toml │ │ ├── quoted-no-close.toml │ │ ├── redefine.toml │ │ ├── rrbrace.toml │ │ ├── text-after-table.toml │ │ ├── whitespace.toml │ │ └── with-pound.toml └── valid │ ├── array │ ├── array.json │ ├── array.toml │ ├── bool.json │ ├── bool.toml │ ├── empty.json │ ├── empty.toml │ ├── hetergeneous.json │ ├── hetergeneous.toml │ ├── mixed-int-array.json │ ├── mixed-int-array.toml │ ├── mixed-int-float.json │ ├── mixed-int-float.toml │ ├── mixed-int-string.json │ ├── mixed-int-string.toml │ ├── mixed-string-table.json │ ├── mixed-string-table.toml │ ├── nested-double.json │ ├── nested-double.toml │ ├── nested-inline-table.json │ ├── nested-inline-table.toml │ ├── nested.json │ ├── nested.toml │ ├── nospaces.json │ ├── nospaces.toml │ ├── string-quote-comma-2.json │ ├── string-quote-comma-2.toml │ ├── string-quote-comma.json │ ├── string-quote-comma.toml │ ├── string-with-comma.json │ ├── string-with-comma.toml │ ├── strings.json │ ├── strings.toml │ ├── table-array-string-backslash.json │ └── table-array-string-backslash.toml │ ├── bool │ ├── bool.json │ └── bool.toml │ ├── comment │ ├── at-eof.json │ ├── at-eof.toml │ ├── at-eof2.json │ ├── at-eof2.toml │ ├── everywhere.json │ ├── everywhere.toml │ ├── noeol.json │ ├── noeol.toml │ ├── tricky.json │ └── tricky.toml │ ├── datetime │ ├── datetime.json │ ├── datetime.toml │ ├── local-date.json │ ├── local-date.toml │ ├── local-time.json │ ├── local-time.toml │ ├── local.json │ ├── local.toml │ ├── milliseconds.json │ ├── milliseconds.toml │ ├── timezone.json │ └── timezone.toml │ ├── empty-file.json │ ├── empty-file.toml │ ├── example.json │ ├── example.toml │ ├── float │ ├── exponent.json │ ├── exponent.toml │ ├── float.json │ ├── float.toml │ ├── inf-and-nan.json │ ├── inf-and-nan.toml │ ├── long.json │ ├── long.toml │ ├── underscore.json │ ├── underscore.toml │ ├── zero.json │ └── zero.toml │ ├── implicit-and-explicit-after.json │ ├── implicit-and-explicit-after.toml │ ├── implicit-and-explicit-before.json │ ├── implicit-and-explicit-before.toml │ ├── implicit-groups.json │ ├── implicit-groups.toml │ ├── inline-table │ ├── array.json │ ├── array.toml │ ├── bool.json │ ├── bool.toml │ ├── empty.json │ ├── empty.toml │ ├── end-in-bool.json │ ├── end-in-bool.toml │ ├── inline-table.json │ ├── inline-table.toml │ ├── key-dotted.json │ ├── key-dotted.toml │ ├── multiline.json │ ├── multiline.toml │ ├── nest.json │ └── nest.toml │ ├── integer │ ├── integer.json │ ├── integer.toml │ ├── literals.json │ ├── literals.toml │ ├── long.json │ ├── long.toml │ ├── underscore.json │ ├── underscore.toml │ ├── zero.json │ └── zero.toml │ ├── key │ ├── alphanum.json │ ├── alphanum.toml │ ├── case-sensitive.json │ ├── case-sensitive.toml │ ├── dotted.json │ ├── dotted.toml │ ├── empty.json │ ├── empty.toml │ ├── equals-nospace.json │ ├── equals-nospace.toml │ ├── escapes.json │ ├── escapes.toml │ ├── numeric-dotted.json │ ├── numeric-dotted.toml │ ├── numeric.json │ ├── numeric.toml │ ├── quoted-dots.json │ ├── quoted-dots.toml │ ├── space.json │ ├── space.toml │ ├── special-chars.json │ ├── special-chars.toml │ ├── special-word.json │ └── special-word.toml │ ├── newline-crlf.json │ ├── newline-crlf.toml │ ├── newline-lf.json │ ├── newline-lf.toml │ ├── spec-example-1-compact.json │ ├── spec-example-1-compact.toml │ ├── spec-example-1.json │ ├── spec-example-1.toml │ ├── string │ ├── double-quote-escape.json │ ├── double-quote-escape.toml │ ├── empty.json │ ├── empty.toml │ ├── escape-esc.json │ ├── escape-esc.toml │ ├── escape-tricky.json │ ├── escape-tricky.toml │ ├── escaped-escape.json │ ├── escaped-escape.toml │ ├── escapes.json │ ├── escapes.toml │ ├── multiline-escaped-crlf.json │ ├── multiline-escaped-crlf.toml │ ├── multiline-quotes.json │ ├── multiline-quotes.toml │ ├── multiline.json │ ├── multiline.toml │ ├── nl.json │ ├── nl.toml │ ├── raw-multiline.json │ ├── raw-multiline.toml │ ├── raw.json │ ├── raw.toml │ ├── simple.json │ ├── simple.toml │ ├── unicode-escape.json │ ├── unicode-escape.toml │ ├── unicode-literal.json │ ├── unicode-literal.toml │ ├── with-pound.json │ └── with-pound.toml │ └── table │ ├── array-implicit.json │ ├── array-implicit.toml │ ├── array-many.json │ ├── array-many.toml │ ├── array-nest.json │ ├── array-nest.toml │ ├── array-one.json │ ├── array-one.toml │ ├── array-table-array.json │ ├── array-table-array.toml │ ├── empty.json │ ├── empty.toml │ ├── keyword.json │ ├── keyword.toml │ ├── names.json │ ├── names.toml │ ├── no-eol.json │ ├── no-eol.toml │ ├── sub-empty.json │ ├── sub-empty.toml │ ├── whitespace.json │ ├── whitespace.toml │ ├── with-literal-string.json │ ├── with-literal-string.toml │ ├── with-pound.json │ ├── with-pound.toml │ ├── with-single-quotes.json │ ├── with-single-quotes.toml │ ├── without-super.json │ └── without-super.toml ├── toml.dict └── zigmod.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.zig text eol=lf 3 | zigmod.* text eol=lf 4 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | on: 3 | pull_request: 4 | push: 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | with: 11 | submodules: true 12 | - uses: cachix/install-nix-action@v20 13 | with: 14 | nix_path: nixpkgs=channel:nixos-unstable 15 | - uses: cachix/cachix-action@v12 16 | with: 17 | name: mattyhall 18 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 19 | - run: nix develop -c zig fmt --check . 20 | - run: nix develop -c zig build 21 | - run: nix develop -c zig build test 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | zig-out/ 2 | zig-cache/ 3 | .zig-cache/ 4 | .zigmod 5 | deps.zig 6 | .gyro 7 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Matthew Hall 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tomlz 2 | 3 | A TOML parser for Zig targeting TOML v1.0.0, an easy API and safety. 4 | Also supports encoding/serializing values(implemented by @0x5a4)! 5 | 6 | ```zig 7 | const std = @import("std") 8 | const tomlz = @import("tomlz") 9 | 10 | var gpa = std.heap.page_allocator; 11 | var table = try tomlz.parse(gpa, 12 | \\foo = 1 13 | \\bar = 2 14 | ); 15 | defer table.deinit(gpa); 16 | 17 | table.getInteger("foo").?; // 1 18 | 19 | 20 | // --- or --- 21 | const S = struct { foo: i64, bar: i64 }; 22 | const s = try tomlz.decode(S, gpa, 23 | \\foo = 1 24 | \\bar = 2 25 | ); 26 | 27 | // serialize a value like this (also see the examples) 28 | try tomlz.serialize( 29 | gpa, 30 | std.io.getStdout.writer() 31 | s, 32 | ); 33 | // foo = 1 34 | // bar = 2 35 | ``` 36 | 37 | ## Current status 38 | 39 | All types other than datetimes are supported. We pass 321/334 of the 40 | [toml tests](https://github.com/BurntSushi/toml-test) 11 of those are due to not 41 | having datetime support and the other two are minor lexing issues (allowing 42 | whitespace between the square brackets of an array header). 43 | 44 | We allow both parsing into a special TOML type, a `Table`, but also support 45 | decoding into a struct directly - including types that must be allocated like 46 | arrays and strings. 47 | 48 | The Serializer allows encoding every kind of zig type, overwriting it's default behaviour 49 | by implementing a function called `tomlzSerialize`, has the option to work 50 | without an allocator and can therefore even work at `comptime`! 51 | Note that for some types like `std.HashMap` its not possible to just encode 52 | all their fields, so custom logic is needed. We can't provide this, but it's not 53 | too difficult to implement it yourself(See examples). 54 | 55 | ## Installation 56 | 57 | tomlz supports being included as a module. 58 | 59 | Create a file called `build.zig.zon` if you do not already have one, and add `tomlz` as a dependency 60 | 61 | ``` 62 | .{ 63 | .name = "myproject", 64 | .version = "0.1.0", 65 | .dependencies = .{ 66 | .tomlz = .{ 67 | .url = "https://github.com/mattyhall/tomlz/archive/.tar.gz", 68 | .hash = "12206cf9e90462ee6e14f593ea6e0802b9fe434429ba10992a1451e32900f741005c", 69 | }, 70 | } 71 | } 72 | ``` 73 | 74 | You'll have to replace the `` part with an actual, recent commit-hash. 75 | The hash also needs changing, but `zig build` will complain and give you the correct one. 76 | 77 | In your `build.zig` file create and use the dependency 78 | 79 | ``` 80 | pub fn build(b: *std.Build) void { 81 | // ... setup ... 82 | 83 | const tomlz = b.dependency("tomlz", .{ 84 | .target = target, 85 | .optimize = optimize, 86 | }); 87 | 88 | // add the tomlz module 89 | exe.root_module.addImport("tomlz", tomlz.module("tomlz")); 90 | 91 | // .. continue ... 92 | } 93 | ``` 94 | 95 | ## Usage 96 | 97 | ### Table 98 | 99 | We currently provide a single entry point for parsing which returns a toml 100 | `Table` type. This type has helper methods for getting values out: 101 | 102 | ```zig 103 | const std = @import("std"); 104 | const tomlz = @import("tomlz"); 105 | 106 | var gpa = std.heap.page_allocator; 107 | var table = try tomlz.parse(gpa, 108 | \\int = 1 109 | \\float = 2.0 110 | \\boolean = true 111 | \\string = "hello, world" 112 | \\array = [1, 2, 3] 113 | \\table = { subvalue = 1, we.can.nest.keys = 2 } 114 | ); 115 | defer table.deinit(gpa); 116 | 117 | table.getInteger("int"); 118 | table.getFloat("float"); 119 | table.getBool("boolean"); 120 | table.getString("string"); 121 | table.getArray("array"); 122 | table.getTable("table"); 123 | ``` 124 | 125 | A simple example is 126 | [provided](https://github.com/mattyhall/tomlz/tree/main/examples/simple/). 127 | 128 | ### Decode 129 | 130 | ```zig 131 | const std = @import("std"); 132 | const tomlz = @import("tomlz"); 133 | 134 | var gpa = std.heap.page_allocator; 135 | const TripleCrowns = struct { worlds: i64, masters: i64, uks: i64 }; 136 | 137 | const Player = struct { 138 | name: []const u8, 139 | age: i64, 140 | hobbies: []const []const u8, 141 | triplecrowns: TripleCrowns, 142 | 143 | const Self = @This(); 144 | 145 | pub fn deinit(self: *Self, gpa: std.mem.Allocator) void { 146 | gpa.free(self.name); 147 | 148 | for (self.hobbies) |hobby| { 149 | gpa.free(hobby); 150 | } 151 | gpa.free(self.hobbies); 152 | } 153 | }; 154 | 155 | const Game = struct { 156 | name: []const u8, 157 | goat: Player, 158 | 159 | const Self = @This(); 160 | 161 | pub fn deinit(self: *Self, gpa: std.mem.Allocator) void { 162 | gpa.free(self.name); 163 | self.goat.deinit(gpa); 164 | } 165 | }; 166 | 167 | var s = try tomlz.decode(Game, gpa, 168 | \\name = "snooker" 169 | \\ 170 | \\[goat] 171 | \\name = "Ronnie o' Sullivan" 172 | \\age = 46 # as of Nov 2022 173 | \\hobbies = ["running", "hustling at pool"] 174 | \\ 175 | \\[goat.triplecrowns] 176 | \\worlds = 7 177 | \\masters = 7 178 | \\uks = 7 179 | ); 180 | defer s.deinit(gpa); 181 | ``` 182 | 183 | ### Encode 184 | 185 | Have a look at [the example](examples/serialize/src/main.zig). 186 | 187 | ## Goals and non-goals 188 | 189 | Goals and non-goals are subject to change based on how the project is used and 190 | my own time constraints. If you feel a goal or non-goal isn't quite right please 191 | open an issue and we can discuss it. 192 | 193 | ### Goals 194 | 195 | - TOML v1.0.0. The datetime portion of this is probably going to be 196 | unachievable until Zig gets a good standard library type for it or a library 197 | gets dominance. Other than that however we should pass all the 198 | [tests](https://github.com/BurntSushi/toml-test) 199 | - A nice API. Getting values from the `Value` type should be painless as 200 | possible and we should also provide deserialising a `Table` into a struct, 201 | similarly to how `std.json` does it 202 | - Easy installation. We should try to make using the library as a vendored 203 | dependency and as a package - on e.g. [gyro](https://github.com/mattnite/gyro) 204 | \- as easy as possible 205 | - Safety. The parser should never crash no matter the input. To achieve this we 206 | should run fuzzing against it 207 | - Support Zig master and the latest tagged release until Zig v1.0. This will be 208 | done by having the main branch track Zig master and a branch for each Zig 209 | release. Any improvements should be backported to the most recent release 210 | branch 211 | - Good error messages 212 | 213 | ### Non-goals 214 | 215 | - Super duper performance. We want to be as performant as possible without 216 | making the code harder to read. It is unlikely that parsing a TOML file is 217 | going to be the bottleneck in your application so "good" performance should be 218 | sufficient 219 | - Previous versions of TOML 220 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) !void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const lib = b.addStaticLibrary(.{ 8 | .name = "tomlz", 9 | .root_source_file = b.path("src/main.zig"), 10 | .target = target, 11 | .optimize = optimize, 12 | }); 13 | b.installArtifact(lib); 14 | 15 | _ = b.addModule("tomlz", .{ .root_source_file = b.path("src/main.zig") }); 16 | 17 | const main_tests = b.addTest(.{ 18 | .root_source_file = b.path("src/main.zig"), 19 | .target = target, 20 | .optimize = optimize, 21 | }); 22 | 23 | const run_main_tests = b.addRunArtifact(main_tests); 24 | 25 | const test_step = b.step("test", "Run library tests"); 26 | test_step.dependOn(&run_main_tests.step); 27 | 28 | const fuzz_exe = b.addExecutable(.{ 29 | .name = "fuzz", 30 | .root_source_file = b.path("src/fuzz.zig"), 31 | .target = target, 32 | }); 33 | fuzz_exe.linkLibC(); 34 | b.installArtifact(fuzz_exe); 35 | const fuzz_compile_run = b.step("fuzz", "Build executable for fuzz testing afl-fuzz"); 36 | fuzz_compile_run.dependOn(&fuzz_exe.step); 37 | } 38 | -------------------------------------------------------------------------------- /examples/serialize-custom/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const exe = b.addExecutable(.{ 8 | .name = "simple", 9 | .root_source_file = .{ .path = "src/main.zig" }, 10 | .target = target, 11 | .optimize = optimize, 12 | }); 13 | 14 | // If we have the project in our repository then we can just add it as a module 15 | const tomlz = b.addModule("tomlz", .{ 16 | .root_source_file = .{ .path = "../../src/main.zig" }, 17 | }); 18 | 19 | exe.root_module.addImport("tomlz", tomlz); 20 | 21 | const run_cmd = b.addRunArtifact(exe); 22 | run_cmd.step.dependOn(b.getInstallStep()); 23 | 24 | if (b.args) |args| { 25 | run_cmd.addArgs(args); 26 | } 27 | 28 | const run_step = b.step("run", "Run the app"); 29 | run_step.dependOn(&run_cmd.step); 30 | } 31 | -------------------------------------------------------------------------------- /examples/serialize-custom/src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const tomlz = @import("tomlz"); 3 | 4 | pub fn main() !void { 5 | // setup a basic allocator 6 | var gpa_instance = std.heap.GeneralPurposeAllocator(.{}){}; 7 | const gpa = gpa_instance.allocator(); 8 | defer _ = gpa_instance.deinit(); 9 | 10 | const stdout_writer = std.io.getStdOut().writer(); 11 | 12 | // structs and unions can have their default serialize function overwritten like this 13 | // see `tomlz.serializer.Writer` for documentation on the writer 14 | const MyCustomStruct = struct { 15 | my_fancy_number: usize, 16 | string1: []const u8, 17 | string2: []const u8, 18 | 19 | pub fn tomlzSerialize(self: *const @This(), writer: anytype) !void { 20 | // When writing a struct, you always need to do this. 21 | try writer.beginTable(); 22 | 23 | try writer.writeKeyValue("number", self.my_fancy_number); // can be used to rename fields for example 24 | 25 | // If you want to e.g. stitch two string together you'd normally need an allocator, 26 | // but sadly we don't have one. Instead use the underlying stream to do so. 27 | // You have to be VERY cautious with this, since it could easily produce an invalid 28 | // output. 29 | 30 | // You also need to push a key where this can be written to 31 | try writer.pushKey("string"); 32 | defer writer.popKey(); //...and remove it when you're done 33 | 34 | // This writes "key = " to the stream, you now have to fill in the value 35 | try writer.beginAssignment(); 36 | 37 | // The underlying stream is just a standard stdlib writer 38 | // (you can put all of this into a single `out_stream.print`, it's just easier to explain like this) 39 | try writer.out_stream.writeByte('"'); // don't forget the quotation marks! 40 | try writer.out_stream.print("{s}{s}", .{ self.string1, self.string2 }); 41 | try writer.out_stream.writeByte('"'); 42 | try writer.out_stream.writeByte('\n'); // you're also in charge of ending the line 43 | // yes this is a very raw API 44 | } 45 | }; 46 | 47 | const test_struct = MyCustomStruct{ 48 | .my_fancy_number = 42, 49 | .string1 = "the", 50 | .string2 = "truth", 51 | }; 52 | 53 | try stdout_writer.writeAll("# Custom serializer:\n"); 54 | try tomlz.serialize(gpa, stdout_writer, test_struct); 55 | 56 | // Finally lets have a look how to implement custom serialize logic for a type you dont own 57 | // (Such as `std.HashMap`) 58 | 59 | try stdout_writer.writeAll("\n# Custom serializer for foreign type:\n"); 60 | 61 | var my_map = std.StringHashMap(usize).init(gpa); 62 | defer my_map.deinit(); 63 | try my_map.put("key1", 1); 64 | try my_map.put("key2", 2); 65 | 66 | // We need to use the internall write stream, since we need 67 | // to access it directly and not just write a value. 68 | var stream = tomlz.serializer.writeStream(gpa, stdout_writer); 69 | defer stream.deinit(); 70 | 71 | var map_iter = my_map.iterator(); 72 | while (map_iter.next()) |entry| { 73 | try stream.writeKeyValue(entry.key_ptr.*, entry.value_ptr.*); 74 | } 75 | 76 | // Note: 77 | // If you'd want to properly wrap the type, you should create a wrapper struct. 78 | // See the example for "owned" types above. 79 | // 80 | // If you're now wondering "But what if it's a very big foreign type, 81 | // but only in a few cases the default doesnt work?". Sadly you're out of luck 82 | // and need to handle the whole type :/ 83 | } 84 | -------------------------------------------------------------------------------- /examples/serialize/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const exe = b.addExecutable(.{ 8 | .name = "simple", 9 | .root_source_file = .{ .path = "src/main.zig" }, 10 | .target = target, 11 | .optimize = optimize, 12 | }); 13 | 14 | // If we have the project in our repository then we can just add it as a module 15 | const tomlz = b.addModule("tomlz", .{ 16 | .root_source_file = .{ .path = "../../src/main.zig" }, 17 | }); 18 | 19 | exe.root_module.addImport("tomlz", tomlz); 20 | 21 | const run_cmd = b.addRunArtifact(exe); 22 | run_cmd.step.dependOn(b.getInstallStep()); 23 | 24 | if (b.args) |args| { 25 | run_cmd.addArgs(args); 26 | } 27 | 28 | const run_step = b.step("run", "Run the app"); 29 | run_step.dependOn(&run_cmd.step); 30 | } 31 | -------------------------------------------------------------------------------- /examples/serialize/src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const tomlz = @import("tomlz"); 3 | 4 | pub fn main() !void { 5 | // setup a basic allocator 6 | var gpa_instance = std.heap.GeneralPurposeAllocator(.{}){}; 7 | const gpa = gpa_instance.allocator(); 8 | defer _ = gpa_instance.deinit(); 9 | 10 | const stdout_writer = std.io.getStdOut().writer(); 11 | 12 | // anything that isn't a table(numbers, strings, etc) 13 | // need to be written with a key 14 | try stdout_writer.writeAll("# Simple value:\n"); 15 | try tomlz.serializeKeyValue(gpa, stdout_writer, "truth", 42); 16 | 17 | // serialize a simple struct like this 18 | const my_point = .{ 19 | .x = 5, 20 | .y = 5, 21 | }; 22 | 23 | // try switching this to a `tomlz.serializeKeyValue` and see why that's 24 | // a problem! 25 | try stdout_writer.writeAll("\n# Table:\n"); 26 | try tomlz.serialize(gpa, stdout_writer, my_point); 27 | 28 | // Finally lets look how we can avoid having to use an allocator 29 | // Every type has a certain "depth" to it, describing how many of its 30 | // fields need to be written in table form 31 | const my_nested_type = .{ 32 | .number1 = 1, // depth 1(default) 33 | .child = .{ // depth 2, this is a table 34 | .number2 = 2, 35 | .child = .{ // depth 3, we're even deeper 36 | .number3 = 3, 37 | }, 38 | }, 39 | .otherchild = .{ // depth 2, this is also a table 40 | .number4 = 4, 41 | }, 42 | }; 43 | // We can see the highest depth is 3, so that's what we need to prepare for 44 | 45 | try stdout_writer.writeAll("\n# No allocator:\n"); 46 | try tomlz.serializer.serializeFixedDepth( 47 | 3, // specify the depth here 48 | stdout_writer, 49 | my_nested_type, 50 | ); 51 | 52 | // In a lot of cases you can just use a "big" number like 64 here and it'll work 53 | // but we can't make that assumption for you, so the default uses an allocator to 54 | // allow for arbitrarily deep types. 55 | } 56 | -------------------------------------------------------------------------------- /examples/simple/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const exe = b.addExecutable(.{ 8 | .name = "simple", 9 | .root_source_file = .{ .path = "src/main.zig" }, 10 | .target = target, 11 | .optimize = optimize, 12 | }); 13 | 14 | // If we have the project in our repository then we can just add it as a module 15 | const tomlz = b.addModule("tomlz", .{ 16 | .root_source_file = .{ .path = "../../src/main.zig" }, 17 | }); 18 | 19 | exe.root_module.addImport("tomlz", tomlz); 20 | 21 | const run_cmd = b.addRunArtifact(exe); 22 | run_cmd.step.dependOn(b.getInstallStep()); 23 | 24 | if (b.args) |args| { 25 | run_cmd.addArgs(args); 26 | } 27 | 28 | const run_step = b.step("run", "Run the app"); 29 | run_step.dependOn(&run_cmd.step); 30 | } 31 | -------------------------------------------------------------------------------- /examples/simple/src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const tomlz = @import("tomlz"); 3 | 4 | pub fn main() !void { 5 | const toml = 6 | \\[goat] 7 | \\name = "Ronnie O' Sullivan" 8 | \\age = 46 9 | \\world_titles = [2001, 2004, 2008, 2012, 2013, 2020, 2022] 10 | ; 11 | 12 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 13 | defer _ = gpa.deinit(); 14 | 15 | var table = try tomlz.parse(gpa.allocator(), toml); 16 | defer table.deinit(gpa.allocator()); 17 | 18 | const goat = table.getTable("goat").?; 19 | std.debug.print("GOAT: {s} (age {})\n", .{ goat.getString("name").?, goat.getInteger("age").? }); 20 | std.debug.print("Number of world titles: {}\n", .{goat.getArray("world_titles").?.items().len}); 21 | } 22 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-compat": { 4 | "flake": false, 5 | "locked": { 6 | "lastModified": 1696426674, 7 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 8 | "owner": "edolstra", 9 | "repo": "flake-compat", 10 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 11 | "type": "github" 12 | }, 13 | "original": { 14 | "owner": "edolstra", 15 | "repo": "flake-compat", 16 | "type": "github" 17 | } 18 | }, 19 | "flake-compat_2": { 20 | "flake": false, 21 | "locked": { 22 | "lastModified": 1696426674, 23 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 24 | "owner": "edolstra", 25 | "repo": "flake-compat", 26 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 27 | "type": "github" 28 | }, 29 | "original": { 30 | "owner": "edolstra", 31 | "repo": "flake-compat", 32 | "type": "github" 33 | } 34 | }, 35 | "flake-compat_3": { 36 | "flake": false, 37 | "locked": { 38 | "lastModified": 1696426674, 39 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 40 | "owner": "edolstra", 41 | "repo": "flake-compat", 42 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 43 | "type": "github" 44 | }, 45 | "original": { 46 | "owner": "edolstra", 47 | "repo": "flake-compat", 48 | "type": "github" 49 | } 50 | }, 51 | "flake-utils": { 52 | "inputs": { 53 | "systems": "systems" 54 | }, 55 | "locked": { 56 | "lastModified": 1710146030, 57 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", 58 | "owner": "numtide", 59 | "repo": "flake-utils", 60 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", 61 | "type": "github" 62 | }, 63 | "original": { 64 | "owner": "numtide", 65 | "repo": "flake-utils", 66 | "type": "github" 67 | } 68 | }, 69 | "flake-utils_2": { 70 | "inputs": { 71 | "systems": "systems_2" 72 | }, 73 | "locked": { 74 | "lastModified": 1705309234, 75 | "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", 76 | "owner": "numtide", 77 | "repo": "flake-utils", 78 | "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", 79 | "type": "github" 80 | }, 81 | "original": { 82 | "owner": "numtide", 83 | "repo": "flake-utils", 84 | "type": "github" 85 | } 86 | }, 87 | "flake-utils_3": { 88 | "inputs": { 89 | "systems": "systems_3" 90 | }, 91 | "locked": { 92 | "lastModified": 1710146030, 93 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", 94 | "owner": "numtide", 95 | "repo": "flake-utils", 96 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", 97 | "type": "github" 98 | }, 99 | "original": { 100 | "owner": "numtide", 101 | "repo": "flake-utils", 102 | "type": "github" 103 | } 104 | }, 105 | "flake-utils_4": { 106 | "inputs": { 107 | "systems": "systems_4" 108 | }, 109 | "locked": { 110 | "lastModified": 1705309234, 111 | "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", 112 | "owner": "numtide", 113 | "repo": "flake-utils", 114 | "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", 115 | "type": "github" 116 | }, 117 | "original": { 118 | "owner": "numtide", 119 | "repo": "flake-utils", 120 | "type": "github" 121 | } 122 | }, 123 | "gitignore": { 124 | "inputs": { 125 | "nixpkgs": [ 126 | "zls", 127 | "nixpkgs" 128 | ] 129 | }, 130 | "locked": { 131 | "lastModified": 1709087332, 132 | "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", 133 | "owner": "hercules-ci", 134 | "repo": "gitignore.nix", 135 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 136 | "type": "github" 137 | }, 138 | "original": { 139 | "owner": "hercules-ci", 140 | "repo": "gitignore.nix", 141 | "type": "github" 142 | } 143 | }, 144 | "langref": { 145 | "flake": false, 146 | "locked": { 147 | "narHash": "sha256-O6p2tiKD8ZMhSX+DeA/o5hhAvcPkU2J9lFys/r11peY=", 148 | "type": "file", 149 | "url": "https://raw.githubusercontent.com/ziglang/zig/0fb2015fd3422fc1df364995f9782dfe7255eccd/doc/langref.html.in" 150 | }, 151 | "original": { 152 | "type": "file", 153 | "url": "https://raw.githubusercontent.com/ziglang/zig/0fb2015fd3422fc1df364995f9782dfe7255eccd/doc/langref.html.in" 154 | } 155 | }, 156 | "nixpkgs": { 157 | "locked": { 158 | "lastModified": 1718606988, 159 | "narHash": "sha256-pmjP5ePc1jz+Okona3HxD7AYT0wbrCwm9bXAlj08nDM=", 160 | "owner": "NixOS", 161 | "repo": "nixpkgs", 162 | "rev": "38d3352a65ac9d621b0cd3074d3bef27199ff78f", 163 | "type": "github" 164 | }, 165 | "original": { 166 | "owner": "NixOS", 167 | "ref": "nixpkgs-unstable", 168 | "repo": "nixpkgs", 169 | "type": "github" 170 | } 171 | }, 172 | "root": { 173 | "inputs": { 174 | "flake-compat": "flake-compat", 175 | "flake-utils": "flake-utils", 176 | "nixpkgs": "nixpkgs", 177 | "zig": "zig", 178 | "zls": "zls" 179 | } 180 | }, 181 | "systems": { 182 | "locked": { 183 | "lastModified": 1681028828, 184 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 185 | "owner": "nix-systems", 186 | "repo": "default", 187 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 188 | "type": "github" 189 | }, 190 | "original": { 191 | "owner": "nix-systems", 192 | "repo": "default", 193 | "type": "github" 194 | } 195 | }, 196 | "systems_2": { 197 | "locked": { 198 | "lastModified": 1681028828, 199 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 200 | "owner": "nix-systems", 201 | "repo": "default", 202 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 203 | "type": "github" 204 | }, 205 | "original": { 206 | "owner": "nix-systems", 207 | "repo": "default", 208 | "type": "github" 209 | } 210 | }, 211 | "systems_3": { 212 | "locked": { 213 | "lastModified": 1681028828, 214 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 215 | "owner": "nix-systems", 216 | "repo": "default", 217 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 218 | "type": "github" 219 | }, 220 | "original": { 221 | "owner": "nix-systems", 222 | "repo": "default", 223 | "type": "github" 224 | } 225 | }, 226 | "systems_4": { 227 | "locked": { 228 | "lastModified": 1681028828, 229 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 230 | "owner": "nix-systems", 231 | "repo": "default", 232 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 233 | "type": "github" 234 | }, 235 | "original": { 236 | "owner": "nix-systems", 237 | "repo": "default", 238 | "type": "github" 239 | } 240 | }, 241 | "zig": { 242 | "inputs": { 243 | "flake-compat": "flake-compat_2", 244 | "flake-utils": "flake-utils_2", 245 | "nixpkgs": [ 246 | "nixpkgs" 247 | ] 248 | }, 249 | "locked": { 250 | "lastModified": 1718798994, 251 | "narHash": "sha256-aEZaj+rFFuLXIE9ohjYFo65t7xKbQ0asrhETNtDGF/0=", 252 | "owner": "mitchellh", 253 | "repo": "zig-overlay", 254 | "rev": "e1a9faa2f863ff1134685b4c0cfdf792ee24d762", 255 | "type": "github" 256 | }, 257 | "original": { 258 | "owner": "mitchellh", 259 | "repo": "zig-overlay", 260 | "type": "github" 261 | } 262 | }, 263 | "zig-overlay": { 264 | "inputs": { 265 | "flake-compat": "flake-compat_3", 266 | "flake-utils": "flake-utils_4", 267 | "nixpkgs": [ 268 | "zls", 269 | "nixpkgs" 270 | ] 271 | }, 272 | "locked": { 273 | "lastModified": 1718539737, 274 | "narHash": "sha256-hvQ900gSqzGnJWMRQwv65TixciIbC44iX0Nh5ENRwCU=", 275 | "owner": "mitchellh", 276 | "repo": "zig-overlay", 277 | "rev": "6eb42ce6f85d247b1aecf854c45d80902821d0ad", 278 | "type": "github" 279 | }, 280 | "original": { 281 | "owner": "mitchellh", 282 | "repo": "zig-overlay", 283 | "type": "github" 284 | } 285 | }, 286 | "zls": { 287 | "inputs": { 288 | "flake-utils": "flake-utils_3", 289 | "gitignore": "gitignore", 290 | "langref": "langref", 291 | "nixpkgs": [ 292 | "nixpkgs" 293 | ], 294 | "zig-overlay": "zig-overlay" 295 | }, 296 | "locked": { 297 | "lastModified": 1718724404, 298 | "narHash": "sha256-BnXu0u0H74cyVOEneESQoCqMCf9zgSrkSx2QVuYztVY=", 299 | "owner": "zigtools", 300 | "repo": "zls", 301 | "rev": "cfea2d55798418cccdf27b1b1bde0f70bff1b8f2", 302 | "type": "github" 303 | }, 304 | "original": { 305 | "owner": "zigtools", 306 | "repo": "zls", 307 | "type": "github" 308 | } 309 | } 310 | }, 311 | "root": "root", 312 | "version": 7 313 | } 314 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A TOML library for Zig"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | zls = { 8 | url = "github:zigtools/zls"; 9 | inputs.nixpkgs.follows = "nixpkgs"; 10 | }; 11 | flake-compat = { 12 | url = "github:edolstra/flake-compat"; 13 | flake = false; 14 | }; 15 | zig = { 16 | url = "github:mitchellh/zig-overlay"; 17 | inputs.nixpkgs.follows = "nixpkgs"; 18 | }; 19 | }; 20 | 21 | outputs = {self, nixpkgs, flake-utils, zls, flake-compat, zig}: 22 | let 23 | overlays = [ 24 | (final: prev: { 25 | zigpkgs = zig.packages.${prev.system}; 26 | }) 27 | (final: prev: { 28 | zlspkgs = zls.packages.${prev.system}; 29 | }) 30 | ]; 31 | systems = builtins.attrNames zig.packages; 32 | in 33 | flake-utils.lib.eachSystem systems (system: 34 | let 35 | pkgs = import nixpkgs { inherit overlays system; }; 36 | in 37 | { 38 | devShell = pkgs.mkShell { 39 | buildInputs = (with pkgs; [ 40 | zigpkgs.master-2024-06-18 41 | zlspkgs.default 42 | bashInteractive 43 | gdb 44 | lldb 45 | ]); 46 | }; 47 | } 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /gyro.zzz: -------------------------------------------------------------------------------- 1 | pkgs: 2 | tomlz: 3 | version: 0.2.0 4 | description: "A TOML parsing library for Zig" 5 | license: MIT 6 | source_url: "https://github.com/mattyhall/tomlz" 7 | tags: 8 | parsing 9 | toml 10 | 11 | root: src/main.zig 12 | files: 13 | README.md 14 | LICENSE 15 | src/*.zig 16 | build.zig 17 | -------------------------------------------------------------------------------- /src/fuzz.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | const lex = @import("lexer.zig"); 4 | const parser = @import("parser.zig"); 5 | 6 | export fn cmain() void { 7 | main() catch unreachable; 8 | } 9 | 10 | pub fn main() !void { 11 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 12 | defer std.debug.assert(gpa.deinit() == .ok); 13 | var allocator = gpa.allocator(); 14 | 15 | const stdin = std.io.getStdIn(); 16 | const data = try stdin.readToEndAlloc(allocator, std.math.maxInt(usize)); 17 | defer allocator.free(data); 18 | 19 | const lexer = parser.Lexer{ .real = try lex.Lexer.init(allocator, data) }; 20 | var p = try parser.Parser.init(allocator, lexer); 21 | defer p.deinit(); 22 | 23 | var table = p.parse() catch |err| { 24 | std.debug.print("error parsing {}\n", .{err}); 25 | std.debug.print("{?}\n", .{p.diag}); 26 | return; 27 | }; 28 | defer table.deinit(allocator); 29 | } 30 | -------------------------------------------------------------------------------- /src/integration_tests.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const parser = @import("parser.zig"); 3 | const testing = std.testing; 4 | 5 | const failing_invalid_tests = [_][]const u8{}; 6 | 7 | const failing_valid_tests = [_][]const u8{ 8 | "comment/everywhere.toml", 9 | "spec-example-1.toml", 10 | "array/array.toml", 11 | "example.toml", 12 | "spec-example-1-compact.toml", 13 | "datetime/milliseconds.toml", 14 | "datetime/local-date.toml", 15 | "datetime/timezone.toml", 16 | "datetime/local-time.toml", 17 | "datetime/local.toml", 18 | "datetime/datetime.toml", 19 | }; 20 | 21 | const dbg = false; 22 | 23 | fn jsonValueEquality(actual: *const std.json.Value, expected: *const std.json.Value) bool { 24 | if (dbg) { 25 | std.debug.print("====\n", .{}); 26 | actual.dump(); 27 | std.debug.print("\n", .{}); 28 | expected.dump(); 29 | std.debug.print("\n====\n", .{}); 30 | } 31 | 32 | switch (actual.*) { 33 | .string => |s| return std.mem.eql(u8, s, expected.string), 34 | .integer => |i| return i == expected.integer, 35 | .bool => |a| return a == expected.bool, 36 | .float => |f| return switch (expected.*) { 37 | .float => |f2| f == f2, 38 | .integer => |i| f == @as(f64, @floatFromInt(i)), 39 | else => false, 40 | }, 41 | .null, .number_string => return false, 42 | else => return false, 43 | } 44 | } 45 | 46 | pub fn jsonEquality(gpa: std.mem.Allocator, actual: *const std.json.Value, expected: *const std.json.Value) !bool { 47 | if (expected.* == .object and expected.object.contains("type")) { 48 | const t = expected.object.get("type") orelse unreachable; 49 | const s = expected.object.get("value") orelse unreachable; 50 | 51 | if (std.mem.eql(u8, t.string, "string")) { 52 | if (actual.* != .string) return false; 53 | 54 | return std.mem.eql(u8, actual.string, s.string); 55 | } 56 | 57 | if (std.mem.eql(u8, t.string, "float")) { 58 | if (actual.* != .float) return false; 59 | 60 | if (std.mem.eql(u8, s.string, "inf") or (std.mem.eql(u8, s.string, "+inf") or (std.mem.eql(u8, s.string, "-inf")))) 61 | return std.math.inf(f64) == actual.float; 62 | 63 | if (std.mem.eql(u8, s.string, "nan") or (std.mem.eql(u8, s.string, "+nan") or (std.mem.eql(u8, s.string, "-nan")))) 64 | return std.math.isNan(actual.float); 65 | } 66 | 67 | var parsed = std.json.parseFromSlice(std.json.Value, gpa, s.string, .{}) catch { 68 | if (dbg) std.debug.print("could not parse '{s}'", .{s.string}); 69 | return false; 70 | }; 71 | defer parsed.deinit(); 72 | 73 | return jsonValueEquality(actual, &parsed.value); 74 | } 75 | 76 | switch (actual.*) { 77 | .array => { 78 | const arr_actual = actual.array.items; 79 | const arr_expected = expected.array.items; 80 | if (arr_actual.len != arr_expected.len) return false; 81 | 82 | for (arr_actual, 0..) |value_a, i| { 83 | const value_e = arr_expected[i]; 84 | if (dbg) std.debug.print("index: {}\n", .{i}); 85 | if (!try jsonEquality(gpa, &value_a, &value_e)) return false; 86 | } 87 | 88 | return true; 89 | }, 90 | .object => { 91 | var tbl_a = actual.object; 92 | var tbl_e = expected.object; 93 | if (tbl_a.count() != tbl_e.count()) { 94 | if (dbg) std.debug.print("wrong count\n", .{}); 95 | return false; 96 | } 97 | 98 | var it = tbl_a.iterator(); 99 | while (it.next()) |entry_a| { 100 | if (dbg) std.debug.print("key: {s}\n", .{entry_a.key_ptr.*}); 101 | const value_e = tbl_e.get(entry_a.key_ptr.*) orelse return false; 102 | if (!try jsonEquality(gpa, entry_a.value_ptr, &value_e)) return false; 103 | } 104 | 105 | return true; 106 | }, 107 | else => { 108 | if (dbg) std.debug.print("some other type\n", .{}); 109 | return false; 110 | }, 111 | } 112 | } 113 | 114 | pub fn tomlValueToJson(allocator: std.mem.Allocator, v: *parser.Value) !std.json.Value { 115 | return switch (v.*) { 116 | .string => |s| std.json.Value{ .string = s }, 117 | .integer => |s| std.json.Value{ .integer = s }, 118 | .float => |f| std.json.Value{ .float = f }, 119 | .boolean => |b| std.json.Value{ .bool = b }, 120 | .array => |*a| b: { 121 | var al = try std.json.Array.initCapacity(allocator, a.array.items.len); 122 | for (a.array.items) |*value| { 123 | al.appendAssumeCapacity(try tomlValueToJson(allocator, value)); 124 | } 125 | break :b std.json.Value{ .array = al }; 126 | }, 127 | .table => |*t| try tableToJson(allocator, t), 128 | }; 129 | } 130 | 131 | pub fn tableToJson(allocator: std.mem.Allocator, table: *parser.Table) error{OutOfMemory}!std.json.Value { 132 | var obj = std.json.ObjectMap.init(allocator); 133 | errdefer obj.deinit(); 134 | 135 | var it = table.table.iterator(); 136 | while (it.next()) |entry| { 137 | const v = try tomlValueToJson(allocator, entry.value_ptr); 138 | try obj.put(entry.key_ptr.*, v); 139 | } 140 | 141 | return std.json.Value{ .object = obj }; 142 | } 143 | 144 | fn expectParseEqualToJson(src: []const u8, json: []const u8) !void { 145 | var table = try parser.parse(testing.allocator, src); 146 | defer table.deinit(testing.allocator); 147 | 148 | var actual_al = std.ArrayList(u8).init(testing.allocator); 149 | defer actual_al.deinit(); 150 | 151 | var json_writer = std.json.writeStreamArbitraryDepth( 152 | testing.allocator, 153 | actual_al.writer(), 154 | .{ .whitespace = .indent_4 }, 155 | ); 156 | defer json_writer.deinit(); 157 | 158 | var arena = std.heap.ArenaAllocator.init(testing.allocator); 159 | defer arena.deinit(); 160 | 161 | var actual_json = try tableToJson(arena.allocator(), &table); 162 | try actual_json.jsonStringify(&json_writer); 163 | 164 | try testing.expectEqualStrings(json, actual_al.items); 165 | } 166 | 167 | fn testFile(dir: *const std.fs.Dir, basename: []const u8) !parser.Table { 168 | var f = try dir.openFile(basename, .{}); 169 | defer f.close(); 170 | 171 | const contents = try f.reader().readAllAlloc(testing.allocator, 5 * 1024 * 1024); 172 | defer testing.allocator.free(contents); 173 | 174 | return try parser.parse(testing.allocator, contents); 175 | } 176 | 177 | fn testInvalid(dir: *const std.fs.Dir, path: []const u8, basename: []const u8) !bool { 178 | for (failing_invalid_tests) |skip_path| if (std.mem.eql(u8, path, skip_path)) return false; 179 | 180 | const full_path = try dir.realpathAlloc(testing.allocator, basename); 181 | defer testing.allocator.free(full_path); 182 | 183 | var tbl = testFile(dir, basename) catch return false; 184 | defer tbl.deinit(testing.allocator); 185 | 186 | std.debug.print("{s} successfully parsed\n", .{full_path}); 187 | return true; 188 | } 189 | 190 | fn testValid(dir: *const std.fs.Dir, path: []const u8, basename: []const u8) !bool { 191 | for (failing_valid_tests) |skip_path| if (std.mem.eql(u8, path, skip_path)) return false; 192 | 193 | const full_path = try dir.realpathAlloc(testing.allocator, basename); 194 | defer testing.allocator.free(full_path); 195 | 196 | var tbl = testFile(dir, basename) catch |err| { 197 | std.debug.print("{s} failed to parse {}\n", .{ full_path, err }); 198 | return true; 199 | }; 200 | defer tbl.deinit(testing.allocator); 201 | 202 | var value = .{ .table = tbl }; 203 | var arena = std.heap.ArenaAllocator.init(testing.allocator); 204 | defer arena.deinit(); 205 | var actual = try tomlValueToJson(arena.allocator(), &value); 206 | 207 | var json_path = try testing.allocator.dupe(u8, basename); 208 | defer testing.allocator.free(json_path); 209 | std.mem.copyForwards(u8, json_path[basename.len - 4 ..], "json"); 210 | 211 | var f = try dir.openFile(json_path, .{}); 212 | defer f.close(); 213 | 214 | const contents = try f.reader().readAllAlloc(testing.allocator, 5 * 1024 * 1024); 215 | defer testing.allocator.free(contents); 216 | 217 | var expected = try std.json.parseFromSlice(std.json.Value, testing.allocator, contents, .{}); 218 | defer expected.deinit(); 219 | 220 | if (!try jsonEquality(arena.allocator(), &actual, &expected.value)) { 221 | std.debug.print("{s}\n", .{full_path}); 222 | return true; 223 | } 224 | 225 | return false; 226 | } 227 | 228 | // standard tests 229 | 230 | test "invalid" { 231 | var dir = try std.fs.cwd().makeOpenPath("tests/invalid", .{.iterate = true}); 232 | defer dir.close(); 233 | 234 | var fail = false; 235 | 236 | var walker = try dir.walk(testing.allocator); 237 | defer walker.deinit(); 238 | while (try walker.next()) |entry| { 239 | if (entry.kind != .file) continue; 240 | 241 | fail = fail or try testInvalid(&entry.dir, entry.path, entry.basename); 242 | } 243 | 244 | if (fail) return error.InvalidDidNotFail; 245 | } 246 | 247 | test "valid" { 248 | var dir = try std.fs.cwd().makeOpenPath("tests/valid", .{.iterate = true}); 249 | defer dir.close(); 250 | 251 | var fail = false; 252 | 253 | var walker = try dir.walk(testing.allocator); 254 | defer walker.deinit(); 255 | while (try walker.next()) |entry| { 256 | if (entry.kind != .file) continue; 257 | if (std.mem.endsWith(u8, entry.basename, "json")) continue; 258 | 259 | fail = fail or try testValid(&entry.dir, entry.path, entry.basename); 260 | } 261 | 262 | if (fail) return error.ValidDidNotPass; 263 | } 264 | 265 | // fuzz error case tests 266 | 267 | test "fuzz" { 268 | var dir = try std.fs.cwd().makeOpenPath("tests/fuzzing", .{.iterate = true}); 269 | defer dir.close(); 270 | 271 | var walker = try dir.walk(testing.allocator); 272 | defer walker.deinit(); 273 | while (try walker.next()) |entry| { 274 | if (entry.kind != .file) continue; 275 | 276 | const full_path = try entry.dir.realpathAlloc(testing.allocator, entry.basename); 277 | defer testing.allocator.free(full_path); 278 | 279 | var f = try entry.dir.openFile(full_path, .{}); 280 | defer f.close(); 281 | 282 | const contents = try f.reader().readAllAlloc(testing.allocator, 5 * 1024 * 1024); 283 | defer testing.allocator.free(contents); 284 | 285 | // We just want to make sure we don't crash when parsing these 286 | var tbl = parser.parse(testing.allocator, contents) catch continue; 287 | tbl.deinit(testing.allocator); 288 | } 289 | } 290 | 291 | // decode tests 292 | 293 | test "decode simple" { 294 | const S = struct { 295 | b: bool, 296 | i1: i32, 297 | i2: u8, 298 | f1: f32, 299 | f2: f64, 300 | }; 301 | 302 | const s = try parser.decode(S, testing.allocator, 303 | \\b = false 304 | \\i1 = 147 305 | \\i2 = 14 306 | \\f1 = 14.7 307 | \\f2 = 14.7 308 | ); 309 | 310 | try testing.expectEqual(S{ .b = false, .i1 = 147, .i2 = 14, .f1 = 14.7, .f2 = 14.7 }, s); 311 | } 312 | 313 | test "decode optional" { 314 | const S = struct { a: i64, b: ?bool }; 315 | 316 | const s = try parser.decode(S, testing.allocator, "a = 147"); 317 | 318 | try testing.expectEqual(S{ .a = 147, .b = null }, s); 319 | } 320 | 321 | test "decode array of ints" { 322 | const S = struct { 323 | vals: []const i64, 324 | }; 325 | 326 | const s = try parser.decode(S, testing.allocator, "vals = [1, 2, 3, 4, 5]"); 327 | defer testing.allocator.free(s.vals); 328 | 329 | try testing.expectEqualSlices(i64, &.{ 1, 2, 3, 4, 5 }, s.vals); 330 | } 331 | 332 | test "decode array of strings" { 333 | const S = struct { 334 | vals: []const []const u8, 335 | }; 336 | 337 | const s = try parser.decode(S, testing.allocator, 338 | \\vals = ["hello", ", ", "world"] 339 | ); 340 | defer { 341 | for (s.vals) |str| testing.allocator.free(str); 342 | testing.allocator.free(s.vals); 343 | } 344 | 345 | try testing.expectEqual(@as(usize, 3), s.vals.len); 346 | try testing.expectEqualStrings("hello", s.vals[0]); 347 | try testing.expectEqualStrings(", ", s.vals[1]); 348 | try testing.expectEqualStrings("world", s.vals[2]); 349 | } 350 | 351 | test "decode array of tables" { 352 | const B = struct { a: i64 }; 353 | const F = struct { bar: []const B }; 354 | const S = struct { foo: F }; 355 | 356 | const s = try parser.decode(S, testing.allocator, 357 | \\[[foo.bar]] 358 | \\a = 147 359 | \\[[foo.bar]] 360 | \\a = 1 361 | ); 362 | defer { 363 | testing.allocator.free(s.foo.bar); 364 | } 365 | 366 | try testing.expectEqualSlices(B, &.{ .{ .a = 147 }, .{ .a = 1 } }, s.foo.bar); 367 | } 368 | 369 | test "decode default value" { 370 | const S = struct { 371 | a: []const u8 = "hello world", 372 | b: i32 = 147, 373 | c: bool = false, 374 | }; 375 | 376 | const s = try parser.decode(S, testing.allocator, 377 | \\c = true 378 | ); 379 | 380 | try testing.expectEqualStrings("hello world", s.a); 381 | try testing.expectEqual(@as(i32, 147), s.b); 382 | try testing.expect(s.c); 383 | } 384 | 385 | // toml2json tests 386 | 387 | test "snooker" { 388 | try expectParseEqualToJson( 389 | \\name = "snooker" 390 | \\ 391 | \\[goat] 392 | \\name = "Ronnie o' Sullivan" 393 | \\age = 46 # as of Nov 2022 394 | \\hobbies = ["running", "hustling at pool"] 395 | \\ 396 | \\[goat.triple-crowns] 397 | \\worlds = 7 398 | \\masters = 7 399 | \\uks = 7 400 | , 401 | \\{ 402 | \\ "name": "snooker", 403 | \\ "goat": { 404 | \\ "triple-crowns": { 405 | \\ "uks": 7, 406 | \\ "masters": 7, 407 | \\ "worlds": 7 408 | \\ }, 409 | \\ "name": "Ronnie o' Sullivan", 410 | \\ "age": 46, 411 | \\ "hobbies": [ 412 | \\ "running", 413 | \\ "hustling at pool" 414 | \\ ] 415 | \\ } 416 | \\} 417 | ); 418 | } 419 | 420 | test "decode snooker" { 421 | const TripleCrowns = struct { worlds: i64, masters: i64, uks: i64 }; 422 | 423 | const Player = struct { 424 | name: []const u8, 425 | age: i64, 426 | hobbies: []const []const u8, 427 | triplecrowns: TripleCrowns, 428 | 429 | const Self = @This(); 430 | 431 | pub fn deinit(self: *Self, gpa: std.mem.Allocator) void { 432 | gpa.free(self.name); 433 | 434 | for (self.hobbies) |hobby| { 435 | gpa.free(hobby); 436 | } 437 | gpa.free(self.hobbies); 438 | } 439 | }; 440 | 441 | const Game = struct { 442 | name: []const u8, 443 | goat: Player, 444 | 445 | const Self = @This(); 446 | 447 | pub fn deinit(self: *Self, gpa: std.mem.Allocator) void { 448 | gpa.free(self.name); 449 | self.goat.deinit(gpa); 450 | } 451 | }; 452 | 453 | var s = try parser.decode(Game, testing.allocator, 454 | \\name = "snooker" 455 | \\ 456 | \\[goat] 457 | \\name = "Ronnie o' Sullivan" 458 | \\age = 46 # as of Nov 2022 459 | \\hobbies = ["running", "hustling at pool"] 460 | \\ 461 | \\[goat.triplecrowns] 462 | \\worlds = 7 463 | \\masters = 7 464 | \\uks = 7 465 | ); 466 | defer s.deinit(testing.allocator); 467 | 468 | try testing.expectEqualStrings("snooker", s.name); 469 | 470 | try testing.expectEqualStrings("Ronnie o' Sullivan", s.goat.name); 471 | try testing.expectEqual(@as(i64, 46), s.goat.age); 472 | try testing.expectEqual(@as(usize, 2), s.goat.hobbies.len); 473 | try testing.expectEqualStrings("running", s.goat.hobbies[0]); 474 | try testing.expectEqualStrings("hustling at pool", s.goat.hobbies[1]); 475 | 476 | try testing.expectEqual(@as(i64, 7), s.goat.triplecrowns.worlds); 477 | try testing.expectEqual(@as(i64, 7), s.goat.triplecrowns.masters); 478 | try testing.expectEqual(@as(i64, 7), s.goat.triplecrowns.uks); 479 | } 480 | 481 | test "helix config" { 482 | try expectParseEqualToJson( 483 | \\theme = "ayu_dark" 484 | \\ 485 | \\[editor] 486 | \\line-number = "relative" 487 | \\rulers = [80, 120] 488 | \\scrolloff = 0 489 | \\true-color = true 490 | \\ 491 | \\[editor.cursor-shape] 492 | \\insert = "bar" 493 | \\normal = "block" 494 | \\select = "underline" 495 | \\ 496 | \\[editor.statusline] 497 | \\center = ["file-name"] 498 | \\left = ["mode", "spinner"] 499 | \\right = ["diagnostics", "selections", "position", "position-percentage", "file-encoding", "file-type"] 500 | \\separator = "│" 501 | \\ 502 | \\[keys.normal] 503 | \\"," = "collapse_selection" 504 | \\";" = "keep_primary_selection" 505 | \\A-J = "join_selections" 506 | \\A-K = "remove_selections" 507 | \\A-k = "keep_selections" 508 | \\B = "extend_prev_word_start" 509 | \\E = "extend_next_word_end" 510 | \\H = "extend_char_left" 511 | \\J = "extend_line_down" 512 | \\K = "extend_line_up" 513 | \\L = "extend_char_right" 514 | \\N = "extend_search_next" 515 | \\W = "extend_next_word_start" 516 | \\X = "extend_line_below" 517 | \\ 518 | \\[keys.normal.space] 519 | \\"," = "buffer_picker" 520 | \\space = "file_picker" 521 | \\ 522 | \\[keys.normal.space.c] 523 | \\D = "workspace_diagnostics_picker" 524 | \\R = "rename_symbol" 525 | \\S = "workspace_symbol_picker" 526 | \\a = "code_action" 527 | \\d = "diagnostics_picker" 528 | \\s = "symbol_picker" 529 | , 530 | \\{ 531 | \\ "keys": { 532 | \\ "normal": { 533 | \\ "A-K": "remove_selections", 534 | \\ "space": { 535 | \\ "c": { 536 | \\ "a": "code_action", 537 | \\ "R": "rename_symbol", 538 | \\ "S": "workspace_symbol_picker", 539 | \\ "s": "symbol_picker", 540 | \\ "D": "workspace_diagnostics_picker", 541 | \\ "d": "diagnostics_picker" 542 | \\ }, 543 | \\ "space": "file_picker", 544 | \\ ",": "buffer_picker" 545 | \\ }, 546 | \\ "K": "extend_line_up", 547 | \\ ";": "keep_primary_selection", 548 | \\ "H": "extend_char_left", 549 | \\ ",": "collapse_selection", 550 | \\ "A-k": "keep_selections", 551 | \\ "B": "extend_prev_word_start", 552 | \\ "W": "extend_next_word_start", 553 | \\ "X": "extend_line_below", 554 | \\ "L": "extend_char_right", 555 | \\ "J": "extend_line_down", 556 | \\ "N": "extend_search_next", 557 | \\ "E": "extend_next_word_end", 558 | \\ "A-J": "join_selections" 559 | \\ } 560 | \\ }, 561 | \\ "theme": "ayu_dark", 562 | \\ "editor": { 563 | \\ "line-number": "relative", 564 | \\ "true-color": true, 565 | \\ "statusline": { 566 | \\ "right": [ 567 | \\ "diagnostics", 568 | \\ "selections", 569 | \\ "position", 570 | \\ "position-percentage", 571 | \\ "file-encoding", 572 | \\ "file-type" 573 | \\ ], 574 | \\ "left": [ 575 | \\ "mode", 576 | \\ "spinner" 577 | \\ ], 578 | \\ "separator": "│", 579 | \\ "center": [ 580 | \\ "file-name" 581 | \\ ] 582 | \\ }, 583 | \\ "rulers": [ 584 | \\ 80, 585 | \\ 120 586 | \\ ], 587 | \\ "cursor-shape": { 588 | \\ "select": "underline", 589 | \\ "insert": "bar", 590 | \\ "normal": "block" 591 | \\ }, 592 | \\ "scrolloff": 0 593 | \\ } 594 | \\} 595 | ); 596 | } 597 | 598 | test "cargo" { 599 | try expectParseEqualToJson( 600 | \\[package] 601 | \\ 602 | \\name = "tiled" 603 | \\version = "0.9.3" 604 | \\description = "A rust crate for loading in maps created by the Tiled editor" 605 | \\repository = "https://github.com/mattyhall/rs-tiled.git" 606 | \\# documentation = "http://rust-ci.org/mattyhall/rs-tiled/doc/tiled/" 607 | \\readme = "README.md" 608 | \\license = "MIT" 609 | \\authors = ["Matthew Hall "] 610 | \\edition = "2018" 611 | \\ 612 | \\keywords = ["tiled", "tmx", "map"] 613 | \\ 614 | \\[features] 615 | \\default = ["zstd"] 616 | \\ 617 | \\[lib] 618 | \\name = "tiled" 619 | \\path = "src/lib.rs" 620 | \\ 621 | \\[[example]] 622 | \\name = "example" 623 | \\path = "examples/main1.rs" 624 | \\ 625 | \\[[example]] 626 | \\name = "example" 627 | \\path = "examples/main2.rs" 628 | \\ 629 | \\[dependencies] 630 | \\base64 = "0.10" 631 | \\xml-rs = "0.8" 632 | \\libflate = "0.1.18" 633 | \\zstd = { version = "0.5", optional = true } 634 | , 635 | \\{ 636 | \\ "example": [ 637 | \\ { 638 | \\ "path": "examples/main1.rs", 639 | \\ "name": "example" 640 | \\ }, 641 | \\ { 642 | \\ "path": "examples/main2.rs", 643 | \\ "name": "example" 644 | \\ } 645 | \\ ], 646 | \\ "dependencies": { 647 | \\ "libflate": "0.1.18", 648 | \\ "xml-rs": "0.8", 649 | \\ "zstd": { 650 | \\ "version": "0.5", 651 | \\ "optional": true 652 | \\ }, 653 | \\ "base64": "0.10" 654 | \\ }, 655 | \\ "package": { 656 | \\ "repository": "https://github.com/mattyhall/rs-tiled.git", 657 | \\ "version": "0.9.3", 658 | \\ "license": "MIT", 659 | \\ "keywords": [ 660 | \\ "tiled", 661 | \\ "tmx", 662 | \\ "map" 663 | \\ ], 664 | \\ "authors": [ 665 | \\ "Matthew Hall " 666 | \\ ], 667 | \\ "description": "A rust crate for loading in maps created by the Tiled editor", 668 | \\ "name": "tiled", 669 | \\ "edition": "2018", 670 | \\ "readme": "README.md" 671 | \\ }, 672 | \\ "lib": { 673 | \\ "path": "src/lib.rs", 674 | \\ "name": "tiled" 675 | \\ }, 676 | \\ "features": { 677 | \\ "default": [ 678 | \\ "zstd" 679 | \\ ] 680 | \\ } 681 | \\} 682 | ); 683 | } 684 | 685 | test "fruits" { 686 | try expectParseEqualToJson( 687 | \\[[fruits]] 688 | \\name = "apple" 689 | \\ 690 | \\[fruits.physical] # subtable 691 | \\color = "red" 692 | \\shape = "round" 693 | \\ 694 | \\[[fruits.varieties]] # nested array of tables 695 | \\name = "red delicious" 696 | \\ 697 | \\[fruits.varieties.rating] 698 | \\yumminess = 5 699 | \\appearance = 6 700 | \\ 701 | \\[[fruits.varieties]] 702 | \\name = "granny smith" 703 | \\ 704 | \\ 705 | \\[[fruits]] 706 | \\name = "banana" 707 | \\ 708 | \\[[fruits.varieties]] 709 | \\name = "plantain" 710 | , 711 | \\{ 712 | \\ "fruits": [ 713 | \\ { 714 | \\ "physical": { 715 | \\ "color": "red", 716 | \\ "shape": "round" 717 | \\ }, 718 | \\ "name": "apple", 719 | \\ "varieties": [ 720 | \\ { 721 | \\ "rating": { 722 | \\ "appearance": 6, 723 | \\ "yumminess": 5 724 | \\ }, 725 | \\ "name": "red delicious" 726 | \\ }, 727 | \\ { 728 | \\ "name": "granny smith" 729 | \\ } 730 | \\ ] 731 | \\ }, 732 | \\ { 733 | \\ "name": "banana", 734 | \\ "varieties": [ 735 | \\ { 736 | \\ "name": "plantain" 737 | \\ } 738 | \\ ] 739 | \\ } 740 | \\ ] 741 | \\} 742 | ); 743 | } 744 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | pub const lex = @import("lexer.zig"); 4 | pub const parser = @import("parser.zig"); 5 | pub const serializer = @import("serializer.zig"); 6 | 7 | pub const parse = parser.parse; 8 | pub const decode = parser.decode; 9 | pub const Value = parser.Value; 10 | pub const Array = parser.Array; 11 | pub const Table = parser.Table; 12 | 13 | /// Serialize a value to the given out_stream. 14 | /// 15 | /// Use this when you want to write a struct as the root table. When serializing 16 | /// e.g. a number use `serializeKeyValue` instead, because in that case a key is required. 17 | /// 18 | /// For a fixed-depth version that doesn't require an allocator, see `serializer.serializeFixedDepth`. 19 | /// 20 | /// # Example 21 | /// ``` 22 | /// const std = @import("std") 23 | /// const tomlz = @import("tomlz"); 24 | /// 25 | /// var gpa_instance = std.heap.GeneralPurposeAllocator(.{}){}; 26 | /// defer _ = gpa_instance.deinit(); 27 | /// 28 | /// const point = .{ 29 | /// .x=4, 30 | /// .y=2, 31 | /// }; 32 | /// 33 | /// try tomlz.serialize( 34 | /// gpa_instance.allocator(), 35 | /// std.io.getStdOut().writer(), 36 | /// point, 37 | /// ); 38 | /// 39 | /// // Output: 40 | /// // x = 4 41 | /// // y = 2 42 | /// ```` 43 | pub const serialize = serializer.serialize; 44 | 45 | /// Serialize a key-value pair to the given out_stream. 46 | /// 47 | /// If you want to write a struct as the root table, see `serialize`. 48 | /// 49 | /// For a fixed-depth version that doesn't require an allocator, see `serializer.serializeKeyValueFixedDepth`. 50 | /// # Example 51 | /// ``` 52 | /// const std = @import("std") 53 | /// const tomlz = @import("tomlz"); 54 | /// 55 | /// var gpa_instance = std.heap.GeneralPurposeAllocator(.{}){}; 56 | /// defer _ = gpa_instance.deinit(); 57 | /// 58 | /// const mynumber = 42; 59 | /// 60 | /// try tomlz.serializeKeyValue( 61 | /// gpa_instance.allocator(), 62 | /// std.io.getStdOut().writer(), 63 | /// "some_key", 64 | /// mynumber 65 | /// ); 66 | /// 67 | /// // Output: 68 | /// // mynumber = 42 69 | /// ```` 70 | pub const serializeKeyValue = serializer.serializeKeyValue; 71 | 72 | test "refAllDecls" { 73 | const integration_tests = @import("integration_tests.zig"); 74 | 75 | std.testing.refAllDecls(lex); 76 | std.testing.refAllDecls(parser); 77 | std.testing.refAllDecls(integration_tests); 78 | std.testing.refAllDecls(serializer); 79 | } 80 | -------------------------------------------------------------------------------- /src/print_failing_tests.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | const lexer = @import("lexer.zig"); 4 | const parser = @import("parser.zig"); 5 | const e2e = @import("end_to_end.zig"); 6 | const standard_tests = @import("standard_tests.zig"); 7 | 8 | fn testFile(gpa: std.mem.Allocator, dir: *const std.fs.Dir, basename: []const u8) !parser.Table { 9 | var f = try dir.openFile(basename, .{}); 10 | defer f.close(); 11 | 12 | var contents = try f.reader().readAllAlloc(gpa, 5 * 1024 * 1024); 13 | defer gpa.free(contents); 14 | 15 | return try parser.parse(gpa, contents); 16 | } 17 | 18 | fn parseInvalid(gpa: std.mem.Allocator, dir: *const std.fs.Dir, basename: []const u8) !bool { 19 | var full_path = try dir.realpathAlloc(gpa, basename); 20 | defer gpa.free(full_path); 21 | 22 | var tbl = testFile(gpa, dir, basename) catch return false; 23 | defer tbl.deinit(gpa); 24 | 25 | std.debug.print("{s}\n", .{full_path}); 26 | return true; 27 | } 28 | 29 | fn parseValid(gpa: std.mem.Allocator, dir: *const std.fs.Dir, basename: []const u8) !bool { 30 | var full_path = try dir.realpathAlloc(gpa, basename); 31 | defer gpa.free(full_path); 32 | 33 | var tbl = testFile(gpa, dir, basename) catch { 34 | std.debug.print("{s}\n", .{full_path}); 35 | return true; 36 | }; 37 | defer tbl.deinit(gpa); 38 | 39 | var value = .{ .table = tbl }; 40 | var actual = try e2e.tomlValueToJson(gpa, &value); 41 | 42 | var json_path = try gpa.dupe(u8, basename); 43 | defer gpa.free(json_path); 44 | std.mem.copy(u8, json_path[basename.len - 4 ..], "json"); 45 | 46 | var f = try dir.openFile(json_path, .{}); 47 | defer f.close(); 48 | 49 | var contents = try f.reader().readAllAlloc(gpa, 5 * 1024 * 1024); 50 | defer gpa.free(contents); 51 | 52 | var json_parser = std.json.Parser.init(gpa, false); 53 | defer json_parser.deinit(); 54 | 55 | var expected = try json_parser.parse(contents); 56 | defer expected.deinit(); 57 | 58 | if (!try standard_tests.jsonEquality(gpa, &actual, &expected.root)) { 59 | std.debug.print("{s}\n", .{full_path}); 60 | return true; 61 | } 62 | 63 | return false; 64 | } 65 | 66 | pub fn main() !void { 67 | var gpa = std.heap.page_allocator; 68 | 69 | { 70 | std.debug.print("Invalid\n", .{}); 71 | var dir = try std.fs.cwd().makeOpenPathIterable("tests/invalid", .{}); 72 | defer dir.close(); 73 | 74 | var walker = try dir.walk(gpa); 75 | defer walker.deinit(); 76 | while (try walker.next()) |entry| { 77 | if (entry.kind != .File) continue; 78 | 79 | _ = try parseInvalid(gpa, &entry.dir, entry.basename); 80 | } 81 | } 82 | 83 | { 84 | std.debug.print("Valid\n", .{}); 85 | var dir = try std.fs.cwd().makeOpenPathIterable("tests/valid", .{}); 86 | defer dir.close(); 87 | 88 | var walker = try dir.walk(gpa); 89 | defer walker.deinit(); 90 | while (try walker.next()) |entry| { 91 | if (entry.kind != .File) continue; 92 | if (!std.mem.endsWith(u8, entry.basename, "toml")) continue; 93 | 94 | _ = try parseValid(gpa, &entry.dir, entry.basename); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/toml2json.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | const lex = @import("lexer.zig"); 4 | const parser = @import("parser.zig"); 5 | 6 | pub fn main() !void { 7 | if (std.os.argv.len != 2) { 8 | std.debug.print("Please pass a TOML file as the second argument", .{}); 9 | } 10 | 11 | var gpa = std.heap.page_allocator; 12 | 13 | var f = try std.fs.openFileAbsoluteZ(std.os.argv[1], .{}); 14 | defer f.close(); 15 | 16 | var contents = try f.reader().readAllAlloc(gpa, 5 * 1024 * 1024); 17 | defer gpa.free(contents); 18 | 19 | var lexer = parser.Lexer{ .real = try lex.Lexer.init(gpa, contents) }; 20 | var p = try parser.Parser.init(gpa, lexer); 21 | defer p.deinit(); 22 | 23 | var table = p.parse() catch |err| { 24 | std.debug.print("error parsing {s}: {}\n", .{ std.os.argv[1], err }); 25 | std.debug.print("{?}\n", .{p.diag}); 26 | return err; 27 | }; 28 | defer table.deinit(gpa); 29 | 30 | const integration = @import("integration_tests.zig"); 31 | var json = try integration.tableToJson(gpa, &table); 32 | 33 | var al = std.ArrayList(u8).init(gpa); 34 | defer al.deinit(); 35 | 36 | try json.jsonStringify(.{ .whitespace = .{} }, al.writer()); 37 | std.debug.print("{s}", .{al.items}); 38 | } 39 | -------------------------------------------------------------------------------- /tests/.gitattributes: -------------------------------------------------------------------------------- 1 | *.toml -text 2 | -------------------------------------------------------------------------------- /tests/COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 TOML authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/fuzzing/id-000000,sig-06,src-000024,time-10060,execs-1850,op-havoc,rep-4: -------------------------------------------------------------------------------- 1 | # Si ' should be allowedD 2 | oneline = '''This string has a ' quote character.''' 3 | 4 | # A newline owing the opening delimiter will be trimmed. 5 | firstnl = ''' 6 | This string has a ' quote character.''' 7 | 8 | # All othefalser whitespace and newline characters remain intact. 9 | multiline = ''' 10 | This string 11 | has ' a quote character 12 | and more than 13 | on0 newline 14 | in it.g'' 15 | -------------------------------------------------------------------------------- /tests/fuzzing/id-000000,sig-06,src-000035,time-345,execs-551,op-havoc,rep-2: -------------------------------------------------------------------------------- 1 | a = [ { = {} } ] 2 | -------------------------------------------------------------------------------- /tests/fuzzing/id-000000,sig-06,src-000052+000007,time-701543,execs-28399,op-splice,rep-2: -------------------------------------------------------------------------------- 1 | answej4 = """"\u03B4" 2 | answer8 = "\U000003B4" 3 | -------------------------------------------------------------------------------- /tests/invalid/array/double-comma-1.toml: -------------------------------------------------------------------------------- 1 | array = [1,,2] 2 | -------------------------------------------------------------------------------- /tests/invalid/array/double-comma-2.toml: -------------------------------------------------------------------------------- 1 | array = [1,2,,] 2 | 3 | -------------------------------------------------------------------------------- /tests/invalid/array/extending-table.toml: -------------------------------------------------------------------------------- 1 | a = [{ b = 1 }] 2 | 3 | # Cannot extend tables within static arrays 4 | # https://github.com/toml-lang/toml/issues/908 5 | [a.c] 6 | foo = 1 7 | -------------------------------------------------------------------------------- /tests/invalid/array/missing-separator.toml: -------------------------------------------------------------------------------- 1 | wrong = [ 1 2 3 ] 2 | -------------------------------------------------------------------------------- /tests/invalid/array/no-close-2.toml: -------------------------------------------------------------------------------- 1 | x = [42 # 2 | -------------------------------------------------------------------------------- /tests/invalid/array/no-close-table-2.toml: -------------------------------------------------------------------------------- 1 | x = [{ key = 42 # 2 | -------------------------------------------------------------------------------- /tests/invalid/array/no-close-table.toml: -------------------------------------------------------------------------------- 1 | x = [{ key = 42 2 | -------------------------------------------------------------------------------- /tests/invalid/array/no-close.toml: -------------------------------------------------------------------------------- 1 | long_array = [ 1, 2, 3 2 | -------------------------------------------------------------------------------- /tests/invalid/array/tables-1.toml: -------------------------------------------------------------------------------- 1 | # INVALID TOML DOC 2 | fruit = [] 3 | 4 | [[fruit]] # Not allowed 5 | -------------------------------------------------------------------------------- /tests/invalid/array/tables-2.toml: -------------------------------------------------------------------------------- 1 | # INVALID TOML DOC 2 | [[fruit]] 3 | name = "apple" 4 | 5 | [[fruit.variety]] 6 | name = "red delicious" 7 | 8 | # This table conflicts with the previous table 9 | [fruit.variety] 10 | name = "granny smith" 11 | -------------------------------------------------------------------------------- /tests/invalid/array/text-after-array-entries.toml: -------------------------------------------------------------------------------- 1 | array = [ 2 | "Is there life after an array separator?", No 3 | "Entry" 4 | ] 5 | -------------------------------------------------------------------------------- /tests/invalid/array/text-before-array-separator.toml: -------------------------------------------------------------------------------- 1 | array = [ 2 | "Is there life before an array separator?" No, 3 | "Entry" 4 | ] 5 | -------------------------------------------------------------------------------- /tests/invalid/array/text-in-array.toml: -------------------------------------------------------------------------------- 1 | array = [ 2 | "Entry 1", 3 | I don't belong, 4 | "Entry 2", 5 | ] 6 | -------------------------------------------------------------------------------- /tests/invalid/bool/almost-false-with-extra.toml: -------------------------------------------------------------------------------- 1 | a = falsify 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/almost-false.toml: -------------------------------------------------------------------------------- 1 | a = fals 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/almost-true-with-extra.toml: -------------------------------------------------------------------------------- 1 | a = truthy 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/almost-true.toml: -------------------------------------------------------------------------------- 1 | a = tru 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/just-f.toml: -------------------------------------------------------------------------------- 1 | a = f 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/just-t.toml: -------------------------------------------------------------------------------- 1 | a = t 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/mixed-case.toml: -------------------------------------------------------------------------------- 1 | valid = False 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/starting-same-false.toml: -------------------------------------------------------------------------------- 1 | a = falsey 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/starting-same-true.toml: -------------------------------------------------------------------------------- 1 | a = truer 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/wrong-case-false.toml: -------------------------------------------------------------------------------- 1 | b = FALSE 2 | -------------------------------------------------------------------------------- /tests/invalid/bool/wrong-case-true.toml: -------------------------------------------------------------------------------- 1 | a = TRUE 2 | -------------------------------------------------------------------------------- /tests/invalid/control/bare-cr.toml: -------------------------------------------------------------------------------- 1 | # The following line contains a single carriage return control character 2 | -------------------------------------------------------------------------------- /tests/invalid/control/bare-formfeed.toml: -------------------------------------------------------------------------------- 1 | bare-formfeed = 2 | -------------------------------------------------------------------------------- /tests/invalid/control/bare-null.toml: -------------------------------------------------------------------------------- 1 | bare-null = "some value" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/bare-vertical-tab.toml: -------------------------------------------------------------------------------- 1 | bare-vertical-tab = 2 | -------------------------------------------------------------------------------- /tests/invalid/control/comment-cr.toml: -------------------------------------------------------------------------------- 1 | comment-cr = "Carriage return in comment" # a=1 2 | -------------------------------------------------------------------------------- /tests/invalid/control/comment-del.toml: -------------------------------------------------------------------------------- 1 | comment-del = "0x7f" #  2 | -------------------------------------------------------------------------------- /tests/invalid/control/comment-lf.toml: -------------------------------------------------------------------------------- 1 | comment-lf = "ctrl-P" #  2 | -------------------------------------------------------------------------------- /tests/invalid/control/comment-null.toml: -------------------------------------------------------------------------------- 1 | comment-null = "null" # 2 | -------------------------------------------------------------------------------- /tests/invalid/control/comment-us.toml: -------------------------------------------------------------------------------- 1 | comment-us = "ctrl-_" #  2 | -------------------------------------------------------------------------------- /tests/invalid/control/control.multi: -------------------------------------------------------------------------------- 1 | # "\x.." sequences are replaced with literal control characters. 2 | 3 | comment-null = "null" # \x00 4 | comment-lf = "ctrl-P" # \x10 5 | comment-us = "ctrl-_" # \x1f 6 | comment-del = "0x7f" # \x7f 7 | comment-cr = "Carriage return in comment" # \x0da=1 8 | 9 | string-null = "null\x00" 10 | string-lf = "null\x10" 11 | string-us = "null\x1f" 12 | string-del = "null\x7f" 13 | 14 | rawstring-null = 'null\x00' 15 | rawstring-lf = 'null\x10' 16 | rawstring-us = 'null\x1f' 17 | rawstring-del = 'null\x7f' 18 | 19 | multi-null = """null\x00""" 20 | multi-lf = """null\x10""" 21 | multi-us = """null\x1f""" 22 | multi-del = """null\x7f""" 23 | 24 | rawmulti-null = '''null\x00''' 25 | rawmulti-lf = '''null\x10''' 26 | rawmulti-us = '''null\x1f''' 27 | rawmulti-del = '''null\x7f''' 28 | 29 | string-bs = "backspace\x08" 30 | 31 | bare-null = "some value" \x00 32 | bare-formfeed = \x0c 33 | bare-vertical-tab = \x0b 34 | -------------------------------------------------------------------------------- /tests/invalid/control/multi-del.toml: -------------------------------------------------------------------------------- 1 | multi-del = """null""" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/multi-lf.toml: -------------------------------------------------------------------------------- 1 | multi-lf = """null""" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/multi-null.toml: -------------------------------------------------------------------------------- 1 | multi-null = """null""" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/multi-us.toml: -------------------------------------------------------------------------------- 1 | multi-us = """null""" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawmulti-del.toml: -------------------------------------------------------------------------------- 1 | rawmulti-del = '''null''' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawmulti-lf.toml: -------------------------------------------------------------------------------- 1 | rawmulti-lf = '''null''' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawmulti-null.toml: -------------------------------------------------------------------------------- 1 | rawmulti-null = '''null''' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawmulti-us.toml: -------------------------------------------------------------------------------- 1 | rawmulti-us = '''null''' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawstring-del.toml: -------------------------------------------------------------------------------- 1 | rawstring-del = 'null' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawstring-lf.toml: -------------------------------------------------------------------------------- 1 | rawstring-lf = 'null' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawstring-null.toml: -------------------------------------------------------------------------------- 1 | rawstring-null = 'null' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/rawstring-us.toml: -------------------------------------------------------------------------------- 1 | rawstring-us = 'null' 2 | -------------------------------------------------------------------------------- /tests/invalid/control/string-bs.toml: -------------------------------------------------------------------------------- 1 | string-bs = "backspace" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/string-del.toml: -------------------------------------------------------------------------------- 1 | string-del = "null" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/string-lf.toml: -------------------------------------------------------------------------------- 1 | string-lf = "null" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/string-null.toml: -------------------------------------------------------------------------------- 1 | string-null = "null" 2 | -------------------------------------------------------------------------------- /tests/invalid/control/string-us.toml: -------------------------------------------------------------------------------- 1 | string-us = "null" 2 | -------------------------------------------------------------------------------- /tests/invalid/datetime/hour-over.toml: -------------------------------------------------------------------------------- 1 | # time-hour = 2DIGIT ; 00-23 2 | d = 2006-01-01T24:00:00-00:00 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/mday-over.toml: -------------------------------------------------------------------------------- 1 | # date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on 2 | # ; month/year 3 | d = 2006-01-32T00:00:00-00:00 4 | -------------------------------------------------------------------------------- /tests/invalid/datetime/mday-under.toml: -------------------------------------------------------------------------------- 1 | # date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on 2 | # ; month/year 3 | d = 2006-01-00T00:00:00-00:00 4 | -------------------------------------------------------------------------------- /tests/invalid/datetime/minute-over.toml: -------------------------------------------------------------------------------- 1 | # time-minute = 2DIGIT ; 00-59 2 | d = 2006-01-01T00:60:00-00:00 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/month-over.toml: -------------------------------------------------------------------------------- 1 | # date-month = 2DIGIT ; 01-12 2 | d = 2006-13-01T00:00:00-00:00 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/month-under.toml: -------------------------------------------------------------------------------- 1 | # date-month = 2DIGIT ; 01-12 2 | d = 2007-00-01T00:00:00-00:00 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/no-leads-with-milli.toml: -------------------------------------------------------------------------------- 1 | # Day "5" instead of "05"; the leading zero is required. 2 | with-milli = 1987-07-5T17:45:00.12Z 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/no-leads.toml: -------------------------------------------------------------------------------- 1 | # Month "7" instead of "07"; the leading zero is required. 2 | no-leads = 1987-7-05T17:45:00Z 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/no-secs.toml: -------------------------------------------------------------------------------- 1 | # No seconds in time. 2 | no-secs = 1987-07-05T17:45Z 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/no-t.toml: -------------------------------------------------------------------------------- 1 | # No "t" or "T" between the date and time. 2 | no-t = 1987-07-0517:45:00Z 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/second-over.toml: -------------------------------------------------------------------------------- 1 | # time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second 2 | # ; rules 3 | d = 2006-01-01T00:00:61-00:00 4 | -------------------------------------------------------------------------------- /tests/invalid/datetime/time-no-leads-2.toml: -------------------------------------------------------------------------------- 1 | # Leading 0 is always required. 2 | d = 01:32:0 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/time-no-leads.toml: -------------------------------------------------------------------------------- 1 | # Leading 0 is always required. 2 | d = 1:32:00 3 | -------------------------------------------------------------------------------- /tests/invalid/datetime/trailing-t.toml: -------------------------------------------------------------------------------- 1 | # Date cannot end with trailing T 2 | d = 2006-01-30T 3 | -------------------------------------------------------------------------------- /tests/invalid/encoding/bad-utf8-at-end.toml: -------------------------------------------------------------------------------- 1 | # There is a 0xda at after the quotes, and no EOL at the end of the file. 2 | # 3 | # This is a bit of an edge case: This indicates there should be two bytes 4 | # (0b1101_1010) but there is no byte to follow because it's the end of the file. 5 | x = """"""� -------------------------------------------------------------------------------- /tests/invalid/encoding/bad-utf8-in-comment.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/invalid/encoding/bad-utf8-in-comment.toml -------------------------------------------------------------------------------- /tests/invalid/encoding/bad-utf8-in-string.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/invalid/encoding/bad-utf8-in-string.toml -------------------------------------------------------------------------------- /tests/invalid/encoding/bom-not-at-start-1.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/invalid/encoding/bom-not-at-start-1.toml -------------------------------------------------------------------------------- /tests/invalid/encoding/bom-not-at-start-2.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/invalid/encoding/bom-not-at-start-2.toml -------------------------------------------------------------------------------- /tests/invalid/encoding/utf16-bom.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/invalid/encoding/utf16-bom.toml -------------------------------------------------------------------------------- /tests/invalid/encoding/utf16.toml: -------------------------------------------------------------------------------- 1 | # UTF-16 without BOM 2 | -------------------------------------------------------------------------------- /tests/invalid/float/double-point-1.toml: -------------------------------------------------------------------------------- 1 | double-point-1 = 0..1 2 | -------------------------------------------------------------------------------- /tests/invalid/float/double-point-2.toml: -------------------------------------------------------------------------------- 1 | double-point-2 = 0.1.2 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-double-e-1.toml: -------------------------------------------------------------------------------- 1 | exp-double-e-1 = 1ee2 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-double-e-2.toml: -------------------------------------------------------------------------------- 1 | exp-double-e-2 = 1e2e3 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-double-us.toml: -------------------------------------------------------------------------------- 1 | exp-double-us = 1e__23 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-leading-us.toml: -------------------------------------------------------------------------------- 1 | exp-leading-us = 1e_23 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-point-1.toml: -------------------------------------------------------------------------------- 1 | exp-point-1 = 1e2.3 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-point-2.toml: -------------------------------------------------------------------------------- 1 | exp-point-2 = 1.e2 2 | -------------------------------------------------------------------------------- /tests/invalid/float/exp-trailing-us.toml: -------------------------------------------------------------------------------- 1 | exp-trailing-us = 1e_23_ 2 | -------------------------------------------------------------------------------- /tests/invalid/float/float.multi: -------------------------------------------------------------------------------- 1 | leading-zero = 03.14 2 | leading-zero-neg = -03.14 3 | leading-zero-plus = +03.14 4 | 5 | leading-point = .12345 6 | leading-point-neg = -.12345 7 | leading-point-plus = +.12345 8 | 9 | trailing-point = 1. 10 | trailing-point-min = -1. 11 | trailing-point-plus = +1. 12 | 13 | trailing-us = 1.2_ 14 | leading-us = _1.2 15 | us-before-point = 1_.2 16 | us-after-point = 1._2 17 | 18 | double-point-1 = 0..1 19 | double-point-2 = 0.1.2 20 | 21 | exp-point-1 = 1e2.3 22 | exp-point-2 = 1.e2 23 | 24 | exp-double-e-1 = 1ee2 25 | exp-double-e-2 = 1e2e3 26 | 27 | exp-leading-us = 1e_23 28 | exp-trailing-us = 1e_23_ 29 | exp-double-us = 1e__23 30 | 31 | inf-incomplete-1 = in 32 | inf-incomplete-2 = +in 33 | inf-incomplete-3 = -in 34 | 35 | nan-incomplete-1 = na 36 | nan-incomplete-2 = +na 37 | nan-incomplete-3 = -na 38 | 39 | nan_underscore = na_n 40 | inf_underscore = in_f 41 | -------------------------------------------------------------------------------- /tests/invalid/float/inf-incomplete-1.toml: -------------------------------------------------------------------------------- 1 | inf-incomplete-1 = in 2 | -------------------------------------------------------------------------------- /tests/invalid/float/inf-incomplete-2.toml: -------------------------------------------------------------------------------- 1 | inf-incomplete-2 = +in 2 | -------------------------------------------------------------------------------- /tests/invalid/float/inf-incomplete-3.toml: -------------------------------------------------------------------------------- 1 | inf-incomplete-3 = -in 2 | -------------------------------------------------------------------------------- /tests/invalid/float/inf_underscore.toml: -------------------------------------------------------------------------------- 1 | inf_underscore = in_f 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-point-neg.toml: -------------------------------------------------------------------------------- 1 | leading-point-neg = -.12345 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-point-plus.toml: -------------------------------------------------------------------------------- 1 | leading-point-plus = +.12345 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-point.toml: -------------------------------------------------------------------------------- 1 | leading-point = .12345 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-us.toml: -------------------------------------------------------------------------------- 1 | leading-us = _1.2 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-zero-neg.toml: -------------------------------------------------------------------------------- 1 | leading-zero-neg = -03.14 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-zero-plus.toml: -------------------------------------------------------------------------------- 1 | leading-zero-plus = +03.14 2 | -------------------------------------------------------------------------------- /tests/invalid/float/leading-zero.toml: -------------------------------------------------------------------------------- 1 | leading-zero = 03.14 2 | -------------------------------------------------------------------------------- /tests/invalid/float/nan-incomplete-1.toml: -------------------------------------------------------------------------------- 1 | nan-incomplete-1 = na 2 | -------------------------------------------------------------------------------- /tests/invalid/float/nan-incomplete-2.toml: -------------------------------------------------------------------------------- 1 | nan-incomplete-2 = +na 2 | -------------------------------------------------------------------------------- /tests/invalid/float/nan-incomplete-3.toml: -------------------------------------------------------------------------------- 1 | nan-incomplete-3 = -na 2 | -------------------------------------------------------------------------------- /tests/invalid/float/nan_underscore.toml: -------------------------------------------------------------------------------- 1 | nan_underscore = na_n 2 | -------------------------------------------------------------------------------- /tests/invalid/float/trailing-point-min.toml: -------------------------------------------------------------------------------- 1 | trailing-point-min = -1. 2 | -------------------------------------------------------------------------------- /tests/invalid/float/trailing-point-plus.toml: -------------------------------------------------------------------------------- 1 | trailing-point-plus = +1. 2 | -------------------------------------------------------------------------------- /tests/invalid/float/trailing-point.toml: -------------------------------------------------------------------------------- 1 | trailing-point = 1. 2 | -------------------------------------------------------------------------------- /tests/invalid/float/trailing-us-exp.toml: -------------------------------------------------------------------------------- 1 | # trailing underscore in integer part is not allowed 2 | trailing-us-exp = 1_e2 3 | # trailing underscore in float part is not allowed 4 | trailing-us-exp2 = 1.2_e2 5 | -------------------------------------------------------------------------------- /tests/invalid/float/trailing-us.toml: -------------------------------------------------------------------------------- 1 | trailing-us = 1.2_ 2 | -------------------------------------------------------------------------------- /tests/invalid/float/us-after-point.toml: -------------------------------------------------------------------------------- 1 | us-after-point = 1._2 2 | -------------------------------------------------------------------------------- /tests/invalid/float/us-before-point.toml: -------------------------------------------------------------------------------- 1 | us-before-point = 1_.2 2 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/add.toml: -------------------------------------------------------------------------------- 1 | a={} 2 | # Inline tables are immutable and can't be extended 3 | [a.b] 4 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/double-comma.toml: -------------------------------------------------------------------------------- 1 | t = {x=3,,y=4} 2 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/duplicate-key.toml: -------------------------------------------------------------------------------- 1 | # Duplicate keys within an inline table are invalid 2 | a={b=1, b=2} 3 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/empty.toml: -------------------------------------------------------------------------------- 1 | t = {,} 2 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/linebreak-1.toml: -------------------------------------------------------------------------------- 1 | # No newlines are allowed between the curly braces unless they are valid within 2 | # a value. 3 | simple = { a = 1 4 | } 5 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/linebreak-2.toml: -------------------------------------------------------------------------------- 1 | t = {a=1, 2 | b=2} 3 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/linebreak-3.toml: -------------------------------------------------------------------------------- 1 | t = {a=1 2 | ,b=2} 3 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/linebreak-4.toml: -------------------------------------------------------------------------------- 1 | json_like = { 2 | first = "Tom", 3 | last = "Preston-Werner" 4 | } 5 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/no-comma.toml: -------------------------------------------------------------------------------- 1 | t = {x = 3 y = 4} 2 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/overwrite.toml: -------------------------------------------------------------------------------- 1 | a.b=0 2 | # Since table "a" is already defined, it can't be replaced by an inline table. 3 | a={} 4 | -------------------------------------------------------------------------------- /tests/invalid/inline-table/trailing-comma.toml: -------------------------------------------------------------------------------- 1 | # A terminating comma (also called trailing comma) is not permitted after the 2 | # last key/value pair in an inline table 3 | abc = { abc = 123, } 4 | -------------------------------------------------------------------------------- /tests/invalid/integer/capital-bin.toml: -------------------------------------------------------------------------------- 1 | capital-bin = 0B0 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/capital-hex.toml: -------------------------------------------------------------------------------- 1 | capital-hex = 0X1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/capital-oct.toml: -------------------------------------------------------------------------------- 1 | capital-oct = 0O0 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/double-sign-nex.toml: -------------------------------------------------------------------------------- 1 | double-sign-nex = --99 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/double-sign-plus.toml: -------------------------------------------------------------------------------- 1 | double-sign-plus = ++99 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/double-us.toml: -------------------------------------------------------------------------------- 1 | double-us = 1__23 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/incomplete-bin.toml: -------------------------------------------------------------------------------- 1 | incomplete-bin = 0b 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/incomplete-hex.toml: -------------------------------------------------------------------------------- 1 | incomplete-hex = 0x 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/incomplete-oct.toml: -------------------------------------------------------------------------------- 1 | incomplete-oct = 0o 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/integer.multi: -------------------------------------------------------------------------------- 1 | leading-zero-1 = 01 2 | leading-zero-2 = 00 3 | leading-zero-3 = 0_0 4 | leading-zero-sign-1 = -01 5 | leading-zero-sign-2 = +01 6 | leading-zero-sign-3 = +0_1 7 | 8 | double-sign-plus = ++99 9 | double-sign-nex = --99 10 | 11 | negative-hex = -0xff 12 | negative-bin = -0b11010110 13 | negative-oct = -0o99 14 | 15 | positive-hex = +0xff 16 | positive-bin = +0b11010110 17 | positive-oct = +0o99 18 | 19 | trailing-us = 123_ 20 | leading-us = _123 21 | double-us = 1__23 22 | 23 | us-after-hex = 0x_1 24 | us-after-oct = 0o_1 25 | us-after-bin = 0b_1 26 | 27 | trailing-us-hex = 0x1_ 28 | trailing-us-oct = 0o1_ 29 | trailing-us-bin = 0b1_ 30 | 31 | leading-us-hex = _0o1 32 | leading-us-oct = _0o1 33 | leading-us-bin = _0o1 34 | 35 | invalid-hex = 0xaafz 36 | invalid-oct = 0o778 37 | invalid-bin = 0b0012 38 | 39 | capital-hex = 0X1 40 | capital-oct = 0O0 41 | capital-bin = 0B0 42 | -------------------------------------------------------------------------------- /tests/invalid/integer/invalid-bin.toml: -------------------------------------------------------------------------------- 1 | invalid-bin = 0b0012 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/invalid-hex.toml: -------------------------------------------------------------------------------- 1 | invalid-hex = 0xaafz 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/invalid-oct.toml: -------------------------------------------------------------------------------- 1 | invalid-oct = 0o778 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-us-bin.toml: -------------------------------------------------------------------------------- 1 | leading-us-bin = _0o1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-us-hex.toml: -------------------------------------------------------------------------------- 1 | leading-us-hex = _0o1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-us-oct.toml: -------------------------------------------------------------------------------- 1 | leading-us-oct = _0o1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-us.toml: -------------------------------------------------------------------------------- 1 | leading-us = _123 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-1.toml: -------------------------------------------------------------------------------- 1 | leading-zero-1 = 01 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-2.toml: -------------------------------------------------------------------------------- 1 | leading-zero-2 = 00 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-3.toml: -------------------------------------------------------------------------------- 1 | leading-zero-3 = 0_0 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-sign-1.toml: -------------------------------------------------------------------------------- 1 | leading-zero-sign-1 = -01 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-sign-2.toml: -------------------------------------------------------------------------------- 1 | leading-zero-sign-2 = +01 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/leading-zero-sign-3.toml: -------------------------------------------------------------------------------- 1 | leading-zero-sign-3 = +0_1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/negative-bin.toml: -------------------------------------------------------------------------------- 1 | negative-bin = -0b11010110 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/negative-hex.toml: -------------------------------------------------------------------------------- 1 | negative-hex = -0xff 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/negative-oct.toml: -------------------------------------------------------------------------------- 1 | negative-oct = -0o99 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/positive-bin.toml: -------------------------------------------------------------------------------- 1 | positive-bin = +0b11010110 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/positive-hex.toml: -------------------------------------------------------------------------------- 1 | positive-hex = +0xff 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/positive-oct.toml: -------------------------------------------------------------------------------- 1 | positive-oct = +0o99 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/text-after-integer.toml: -------------------------------------------------------------------------------- 1 | answer = 42 the ultimate answer? 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/trailing-us-bin.toml: -------------------------------------------------------------------------------- 1 | trailing-us-bin = 0b1_ 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/trailing-us-hex.toml: -------------------------------------------------------------------------------- 1 | trailing-us-hex = 0x1_ 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/trailing-us-oct.toml: -------------------------------------------------------------------------------- 1 | trailing-us-oct = 0o1_ 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/trailing-us.toml: -------------------------------------------------------------------------------- 1 | trailing-us = 123_ 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/us-after-bin.toml: -------------------------------------------------------------------------------- 1 | us-after-bin = 0b_1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/us-after-hex.toml: -------------------------------------------------------------------------------- 1 | us-after-hex = 0x_1 2 | -------------------------------------------------------------------------------- /tests/invalid/integer/us-after-oct.toml: -------------------------------------------------------------------------------- 1 | us-after-oct = 0o_1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/after-array.toml: -------------------------------------------------------------------------------- 1 | [[agencies]] owner = "S Cjelli" 2 | -------------------------------------------------------------------------------- /tests/invalid/key/after-table.toml: -------------------------------------------------------------------------------- 1 | [error] this = "should not be here" 2 | -------------------------------------------------------------------------------- /tests/invalid/key/after-value.toml: -------------------------------------------------------------------------------- 1 | first = "Tom" last = "Preston-Werner" # INVALID 2 | -------------------------------------------------------------------------------- /tests/invalid/key/bare-invalid-character.toml: -------------------------------------------------------------------------------- 1 | bare!key = 123 2 | -------------------------------------------------------------------------------- /tests/invalid/key/dotted-redefine-table.toml: -------------------------------------------------------------------------------- 1 | # Defined a.b as int 2 | a.b = 1 3 | # Tries to access it as table: error 4 | a.b.c = 2 5 | -------------------------------------------------------------------------------- /tests/invalid/key/duplicate-keys.toml: -------------------------------------------------------------------------------- 1 | dupe = false 2 | dupe = true 3 | -------------------------------------------------------------------------------- /tests/invalid/key/duplicate.toml: -------------------------------------------------------------------------------- 1 | # DO NOT DO THIS 2 | name = "Tom" 3 | name = "Pradyun" 4 | -------------------------------------------------------------------------------- /tests/invalid/key/empty.toml: -------------------------------------------------------------------------------- 1 | = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/escape.toml: -------------------------------------------------------------------------------- 1 | \u00c0 = "latin capital letter A with grave" 2 | -------------------------------------------------------------------------------- /tests/invalid/key/hash.toml: -------------------------------------------------------------------------------- 1 | a# = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/multiline.toml: -------------------------------------------------------------------------------- 1 | """long 2 | key""" = 1 3 | -------------------------------------------------------------------------------- /tests/invalid/key/newline.toml: -------------------------------------------------------------------------------- 1 | barekey 2 | = 123 3 | -------------------------------------------------------------------------------- /tests/invalid/key/no-eol.toml: -------------------------------------------------------------------------------- 1 | a = 1 b = 2 2 | -------------------------------------------------------------------------------- /tests/invalid/key/open-bracket.toml: -------------------------------------------------------------------------------- 1 | [abc = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/partial-quoted.toml: -------------------------------------------------------------------------------- 1 | partial"quoted" = 5 2 | -------------------------------------------------------------------------------- /tests/invalid/key/quoted-unclosed-1.toml: -------------------------------------------------------------------------------- 1 | "key = x 2 | -------------------------------------------------------------------------------- /tests/invalid/key/quoted-unclosed-2.toml: -------------------------------------------------------------------------------- 1 | "key 2 | -------------------------------------------------------------------------------- /tests/invalid/key/single-open-bracket.toml: -------------------------------------------------------------------------------- 1 | [ 2 | -------------------------------------------------------------------------------- /tests/invalid/key/space.toml: -------------------------------------------------------------------------------- 1 | a b = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/special-character.toml: -------------------------------------------------------------------------------- 1 | μ = "greek small letter mu" 2 | -------------------------------------------------------------------------------- /tests/invalid/key/start-bracket.toml: -------------------------------------------------------------------------------- 1 | [a] 2 | [xyz = 5 3 | [b] 4 | -------------------------------------------------------------------------------- /tests/invalid/key/start-dot.toml: -------------------------------------------------------------------------------- 1 | .key = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/two-equals.toml: -------------------------------------------------------------------------------- 1 | key= = 1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/two-equals2.toml: -------------------------------------------------------------------------------- 1 | a==1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/two-equals3.toml: -------------------------------------------------------------------------------- 1 | a=b=1 2 | -------------------------------------------------------------------------------- /tests/invalid/key/without-value-1.toml: -------------------------------------------------------------------------------- 1 | key 2 | -------------------------------------------------------------------------------- /tests/invalid/key/without-value-2.toml: -------------------------------------------------------------------------------- 1 | key = 2 | -------------------------------------------------------------------------------- /tests/invalid/key/without-value-3.toml: -------------------------------------------------------------------------------- 1 | "key" 2 | -------------------------------------------------------------------------------- /tests/invalid/key/without-value-4.toml: -------------------------------------------------------------------------------- 1 | "key" = 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-byte-escape.toml: -------------------------------------------------------------------------------- 1 | naughty = "\xAg" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-codepoint.toml: -------------------------------------------------------------------------------- 1 | invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-concat.toml: -------------------------------------------------------------------------------- 1 | no_concat = "first" "second" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-escape-1.toml: -------------------------------------------------------------------------------- 1 | invalid-escape = "This string has a bad \a escape character." 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-escape-2.toml: -------------------------------------------------------------------------------- 1 | invalid-escape = "This string has a bad \ escape character." 2 | 3 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-multiline.toml: -------------------------------------------------------------------------------- 1 | multi = "first line 2 | second line" 3 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-slash-escape.toml: -------------------------------------------------------------------------------- 1 | invalid-escape = "This string has a bad \/ escape character." 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-uni-esc-1.toml: -------------------------------------------------------------------------------- 1 | str = "val\ue" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-uni-esc-2.toml: -------------------------------------------------------------------------------- 1 | str = "val\Ux" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-uni-esc-3.toml: -------------------------------------------------------------------------------- 1 | str = "val\U0000000" 2 | 3 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-uni-esc-4.toml: -------------------------------------------------------------------------------- 1 | str = "val\U0000" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/bad-uni-esc-5.toml: -------------------------------------------------------------------------------- 1 | str = "val\Ugggggggg" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-byte-escapes.toml: -------------------------------------------------------------------------------- 1 | answer = "\x33" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-multiline-out-of-range-unicode-escape-1.toml: -------------------------------------------------------------------------------- 1 | a = """\UFFFFFFFF""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-multiline-out-of-range-unicode-escape-2.toml: -------------------------------------------------------------------------------- 1 | a = """\U00D80000""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-multiline-quotes.toml: -------------------------------------------------------------------------------- 1 | str5 = """Here are three quotation marks: """.""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-multiline-unknown-escape.toml: -------------------------------------------------------------------------------- 1 | a = """\@""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-out-of-range-unicode-escape-1.toml: -------------------------------------------------------------------------------- 1 | a = "\UFFFFFFFF" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-out-of-range-unicode-escape-2.toml: -------------------------------------------------------------------------------- 1 | a = "\U00D80000" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/basic-unknown-escape.toml: -------------------------------------------------------------------------------- 1 | a = "\@" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/literal-multiline-quotes-1.toml: -------------------------------------------------------------------------------- 1 | a = '''6 apostrophes: '''''' 2 | 3 | -------------------------------------------------------------------------------- /tests/invalid/string/literal-multiline-quotes-2.toml: -------------------------------------------------------------------------------- 1 | a = '''15 apostrophes: '''''''''''''''''' 2 | -------------------------------------------------------------------------------- /tests/invalid/string/missing-quotes.toml: -------------------------------------------------------------------------------- 1 | name = value 2 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-bad-escape-1.toml: -------------------------------------------------------------------------------- 1 | k = """t\a""" 2 | 3 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-bad-escape-2.toml: -------------------------------------------------------------------------------- 1 | # \ is not a valid escape. 2 | k = """t\ t""" 3 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-bad-escape-3.toml: -------------------------------------------------------------------------------- 1 | # \ is not a valid escape. 2 | k = """t\ """ 3 | 4 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-escape-space.toml: -------------------------------------------------------------------------------- 1 | a = """ 2 | foo \ \n 3 | bar""" 4 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-no-close-2.toml: -------------------------------------------------------------------------------- 1 | x=""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-no-close.toml: -------------------------------------------------------------------------------- 1 | invalid = """ 2 | this will fail 3 | -------------------------------------------------------------------------------- /tests/invalid/string/multiline-quotes-1.toml: -------------------------------------------------------------------------------- 1 | a = """6 quotes: """""" 2 | -------------------------------------------------------------------------------- /tests/invalid/string/no-close.toml: -------------------------------------------------------------------------------- 1 | no-ending-quote = "One time, at band camp 2 | -------------------------------------------------------------------------------- /tests/invalid/string/text-after-string.toml: -------------------------------------------------------------------------------- 1 | string = "Is there life after strings?" No. 2 | -------------------------------------------------------------------------------- /tests/invalid/string/wrong-close.toml: -------------------------------------------------------------------------------- 1 | bad-ending-quote = "double and single' 2 | -------------------------------------------------------------------------------- /tests/invalid/table/append-with-dotted-keys-1.toml: -------------------------------------------------------------------------------- 1 | # First a.b.c defines a table: a.b.c = {z=9} 2 | # 3 | # Then we define a.b.c.t = "str" to add a str to the above table, making it: 4 | # 5 | # a.b.c = {z=9, t="..."} 6 | # 7 | # While this makes sense, logically, it was decided this is not valid TOML as 8 | # it's too confusing/convoluted. 9 | # 10 | # See: https://github.com/toml-lang/toml/issues/846 11 | # https://github.com/toml-lang/toml/pull/859 12 | 13 | [a.b.c] 14 | z = 9 15 | 16 | [a] 17 | b.c.t = "Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed" 18 | -------------------------------------------------------------------------------- /tests/invalid/table/append-with-dotted-keys-2.toml: -------------------------------------------------------------------------------- 1 | # This is the same issue as in injection-1.toml, except that nests one level 2 | # deeper. See that file for a more complete description. 3 | 4 | [a.b.c.d] 5 | z = 9 6 | 7 | [a] 8 | b.c.d.k.t = "Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed" 9 | -------------------------------------------------------------------------------- /tests/invalid/table/array-empty.toml: -------------------------------------------------------------------------------- 1 | [[]] 2 | name = "Born to Run" 3 | -------------------------------------------------------------------------------- /tests/invalid/table/array-implicit.toml: -------------------------------------------------------------------------------- 1 | # This test is a bit tricky. It should fail because the first use of 2 | # `[[albums.songs]]` without first declaring `albums` implies that `albums` 3 | # must be a table. The alternative would be quite weird. Namely, it wouldn't 4 | # comply with the TOML spec: "Each double-bracketed sub-table will belong to 5 | # the most *recently* defined table element *above* it." 6 | # 7 | # This is in contrast to the *valid* test, table-array-implicit where 8 | # `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared 9 | # later. (Although, `[albums]` could be.) 10 | [[albums.songs]] 11 | name = "Glory Days" 12 | 13 | [[albums]] 14 | name = "Born in the USA" 15 | -------------------------------------------------------------------------------- /tests/invalid/table/array-missing-bracket.toml: -------------------------------------------------------------------------------- 1 | [[albums] 2 | name = "Born to Run" 3 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate-key-dotted-table.toml: -------------------------------------------------------------------------------- 1 | [fruit] 2 | apple.color = "red" 3 | 4 | [fruit.apple] # INVALID 5 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate-key-dotted-table2.toml: -------------------------------------------------------------------------------- 1 | [fruit] 2 | apple.taste.sweet = true 3 | 4 | [fruit.apple.taste] # INVALID 5 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate-key-table.toml: -------------------------------------------------------------------------------- 1 | [fruit] 2 | type = "apple" 3 | 4 | [fruit.type] 5 | apple = "yes" 6 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate-table-array.toml: -------------------------------------------------------------------------------- 1 | [tbl] 2 | [[tbl]] 3 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate-table-array2.toml: -------------------------------------------------------------------------------- 1 | [[tbl]] 2 | [tbl] 3 | -------------------------------------------------------------------------------- /tests/invalid/table/duplicate.toml: -------------------------------------------------------------------------------- 1 | [a] 2 | b = 1 3 | 4 | [a] 5 | c = 2 6 | -------------------------------------------------------------------------------- /tests/invalid/table/empty-implicit-table.toml: -------------------------------------------------------------------------------- 1 | [naughty..naughty] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/empty.toml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/equals-sign.toml: -------------------------------------------------------------------------------- 1 | [name=bad] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/llbrace.toml: -------------------------------------------------------------------------------- 1 | [ [table]] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/nested-brackets-close.toml: -------------------------------------------------------------------------------- 1 | [a]b] 2 | zyx = 42 3 | -------------------------------------------------------------------------------- /tests/invalid/table/nested-brackets-open.toml: -------------------------------------------------------------------------------- 1 | [a[b] 2 | zyx = 42 3 | -------------------------------------------------------------------------------- /tests/invalid/table/quoted-no-close.toml: -------------------------------------------------------------------------------- 1 | ["where will it end] 2 | name = value 3 | -------------------------------------------------------------------------------- /tests/invalid/table/redefine.toml: -------------------------------------------------------------------------------- 1 | # Define b as int, and try to use it as a table: error 2 | [a] 3 | b = 1 4 | 5 | [a.b] 6 | c = 2 7 | -------------------------------------------------------------------------------- /tests/invalid/table/rrbrace.toml: -------------------------------------------------------------------------------- 1 | [[table] ] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/text-after-table.toml: -------------------------------------------------------------------------------- 1 | [error] this shouldn't be here 2 | -------------------------------------------------------------------------------- /tests/invalid/table/whitespace.toml: -------------------------------------------------------------------------------- 1 | [invalid key] 2 | -------------------------------------------------------------------------------- /tests/invalid/table/with-pound.toml: -------------------------------------------------------------------------------- 1 | [key#group] 2 | answer = 42 3 | -------------------------------------------------------------------------------- /tests/valid/array/array.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": [ 3 | { 4 | "type": "integer", 5 | "value": "1" 6 | }, 7 | { 8 | "type": "integer", 9 | "value": "2" 10 | } 11 | ], 12 | "dates": [ 13 | { 14 | "type": "datetime", 15 | "value": "1987-07-05T17:45:00Z" 16 | }, 17 | { 18 | "type": "datetime", 19 | "value": "1979-05-27T07:32:00Z" 20 | }, 21 | { 22 | "type": "datetime", 23 | "value": "2006-06-01T11:00:00Z" 24 | } 25 | ], 26 | "floats": [ 27 | { 28 | "type": "float", 29 | "value": "1.1" 30 | }, 31 | { 32 | "type": "float", 33 | "value": "2.1" 34 | }, 35 | { 36 | "type": "float", 37 | "value": "3.1" 38 | } 39 | ], 40 | "ints": [ 41 | { 42 | "type": "integer", 43 | "value": "1" 44 | }, 45 | { 46 | "type": "integer", 47 | "value": "2" 48 | }, 49 | { 50 | "type": "integer", 51 | "value": "3" 52 | } 53 | ], 54 | "strings": [ 55 | { 56 | "type": "string", 57 | "value": "a" 58 | }, 59 | { 60 | "type": "string", 61 | "value": "b" 62 | }, 63 | { 64 | "type": "string", 65 | "value": "c" 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /tests/valid/array/array.toml: -------------------------------------------------------------------------------- 1 | ints = [1, 2, 3, ] 2 | floats = [1.1, 2.1, 3.1] 3 | strings = ["a", "b", "c"] 4 | dates = [ 5 | 1987-07-05T17:45:00Z, 6 | 1979-05-27T07:32:00Z, 7 | 2006-06-01T11:00:00Z, 8 | ] 9 | comments = [ 10 | 1, 11 | 2, #this is ok 12 | ] 13 | -------------------------------------------------------------------------------- /tests/valid/array/bool.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": [ 3 | { 4 | "type": "bool", 5 | "value": "true" 6 | }, 7 | { 8 | "type": "bool", 9 | "value": "false" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/array/bool.toml: -------------------------------------------------------------------------------- 1 | a = [true, false] 2 | -------------------------------------------------------------------------------- /tests/valid/array/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "thevoid": [ 3 | [ 4 | [ 5 | [ 6 | [] 7 | ] 8 | ] 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tests/valid/array/empty.toml: -------------------------------------------------------------------------------- 1 | thevoid = [[[[[]]]]] 2 | -------------------------------------------------------------------------------- /tests/valid/array/hetergeneous.json: -------------------------------------------------------------------------------- 1 | { 2 | "mixed": [ 3 | [ 4 | { 5 | "type": "integer", 6 | "value": "1" 7 | }, 8 | { 9 | "type": "integer", 10 | "value": "2" 11 | } 12 | ], 13 | [ 14 | { 15 | "type": "string", 16 | "value": "a" 17 | }, 18 | { 19 | "type": "string", 20 | "value": "b" 21 | } 22 | ], 23 | [ 24 | { 25 | "type": "float", 26 | "value": "1.1" 27 | }, 28 | { 29 | "type": "float", 30 | "value": "2.1" 31 | } 32 | ] 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /tests/valid/array/hetergeneous.toml: -------------------------------------------------------------------------------- 1 | mixed = [[1, 2], ["a", "b"], [1.1, 2.1]] 2 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-array.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrays-and-ints": [ 3 | { 4 | "type": "integer", 5 | "value": "1" 6 | }, 7 | [ 8 | { 9 | "type": "string", 10 | "value": "Arrays are not integers." 11 | } 12 | ] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-array.toml: -------------------------------------------------------------------------------- 1 | arrays-and-ints = [1, ["Arrays are not integers."]] 2 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-float.json: -------------------------------------------------------------------------------- 1 | { 2 | "ints-and-floats": [ 3 | { 4 | "type": "integer", 5 | "value": "1" 6 | }, 7 | { 8 | "type": "float", 9 | "value": "1.1" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-float.toml: -------------------------------------------------------------------------------- 1 | ints-and-floats = [1, 1.1] 2 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-string.json: -------------------------------------------------------------------------------- 1 | { 2 | "strings-and-ints": [ 3 | { 4 | "type": "string", 5 | "value": "hi" 6 | }, 7 | { 8 | "type": "integer", 9 | "value": "42" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-int-string.toml: -------------------------------------------------------------------------------- 1 | strings-and-ints = ["hi", 42] 2 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-string-table.json: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": [ 3 | { 4 | "type": "string", 5 | "value": "Foo Bar \u003cfoo@example.com\u003e" 6 | }, 7 | { 8 | "email": { 9 | "type": "string", 10 | "value": "bazqux@example.com" 11 | }, 12 | "name": { 13 | "type": "string", 14 | "value": "Baz Qux" 15 | }, 16 | "url": { 17 | "type": "string", 18 | "value": "https://example.com/bazqux" 19 | } 20 | } 21 | ], 22 | "mixed": [ 23 | { 24 | "k": { 25 | "type": "string", 26 | "value": "a" 27 | } 28 | }, 29 | { 30 | "type": "string", 31 | "value": "b" 32 | }, 33 | { 34 | "type": "integer", 35 | "value": "1" 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /tests/valid/array/mixed-string-table.toml: -------------------------------------------------------------------------------- 1 | contributors = [ 2 | "Foo Bar ", 3 | { name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" } 4 | ] 5 | 6 | # Start with a table as the first element. This tests a case that some libraries 7 | # might have where they will check if the first entry is a table/map/hash/assoc 8 | # array and then encode it as a table array. This was a reasonable thing to do 9 | # before TOML 1.0 since arrays could only contain one type, but now it's no 10 | # longer. 11 | mixed = [{k="a"}, "b", 1] 12 | -------------------------------------------------------------------------------- /tests/valid/array/nested-double.json: -------------------------------------------------------------------------------- 1 | { 2 | "nest": [ 3 | [ 4 | [ 5 | { 6 | "type": "string", 7 | "value": "a" 8 | } 9 | ], 10 | [ 11 | { 12 | "type": "integer", 13 | "value": "1" 14 | }, 15 | { 16 | "type": "integer", 17 | "value": "2" 18 | }, 19 | [ 20 | { 21 | "type": "integer", 22 | "value": "3" 23 | } 24 | ] 25 | ] 26 | ] 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/valid/array/nested-double.toml: -------------------------------------------------------------------------------- 1 | nest = [ 2 | [ 3 | ["a"], 4 | [1, 2, [3]] 5 | ] 6 | ] 7 | -------------------------------------------------------------------------------- /tests/valid/array/nested-inline-table.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": [ 3 | { 4 | "b": {} 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tests/valid/array/nested-inline-table.toml: -------------------------------------------------------------------------------- 1 | a = [ { b = {} } ] 2 | -------------------------------------------------------------------------------- /tests/valid/array/nested.json: -------------------------------------------------------------------------------- 1 | { 2 | "nest": [ 3 | [ 4 | { 5 | "type": "string", 6 | "value": "a" 7 | } 8 | ], 9 | [ 10 | { 11 | "type": "string", 12 | "value": "b" 13 | } 14 | ] 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/array/nested.toml: -------------------------------------------------------------------------------- 1 | nest = [["a"], ["b"]] 2 | -------------------------------------------------------------------------------- /tests/valid/array/nospaces.json: -------------------------------------------------------------------------------- 1 | { 2 | "ints": [ 3 | { 4 | "type": "integer", 5 | "value": "1" 6 | }, 7 | { 8 | "type": "integer", 9 | "value": "2" 10 | }, 11 | { 12 | "type": "integer", 13 | "value": "3" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/array/nospaces.toml: -------------------------------------------------------------------------------- 1 | ints = [1,2,3] 2 | -------------------------------------------------------------------------------- /tests/valid/array/string-quote-comma-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": [ 3 | { 4 | "type": "string", 5 | "value": " \", " 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /tests/valid/array/string-quote-comma-2.toml: -------------------------------------------------------------------------------- 1 | title = [ " \", ",] 2 | -------------------------------------------------------------------------------- /tests/valid/array/string-quote-comma.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": [ 3 | { 4 | "type": "string", 5 | "value": "Client: \"XXXX\", Job: XXXX" 6 | }, 7 | { 8 | "type": "string", 9 | "value": "Code: XXXX" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/array/string-quote-comma.toml: -------------------------------------------------------------------------------- 1 | title = [ 2 | "Client: \"XXXX\", Job: XXXX", 3 | "Code: XXXX" 4 | ] 5 | -------------------------------------------------------------------------------- /tests/valid/array/string-with-comma.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": [ 3 | { 4 | "type": "string", 5 | "value": "Client: XXXX, Job: XXXX" 6 | }, 7 | { 8 | "type": "string", 9 | "value": "Code: XXXX" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/array/string-with-comma.toml: -------------------------------------------------------------------------------- 1 | title = [ 2 | "Client: XXXX, Job: XXXX", 3 | "Code: XXXX" 4 | ] 5 | -------------------------------------------------------------------------------- /tests/valid/array/strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "string_array": [ 3 | { 4 | "type": "string", 5 | "value": "all" 6 | }, 7 | { 8 | "type": "string", 9 | "value": "strings" 10 | }, 11 | { 12 | "type": "string", 13 | "value": "are the same" 14 | }, 15 | { 16 | "type": "string", 17 | "value": "type" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tests/valid/array/strings.toml: -------------------------------------------------------------------------------- 1 | string_array = [ "all", 'strings', """are the same""", '''type'''] 2 | -------------------------------------------------------------------------------- /tests/valid/array/table-array-string-backslash.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": [ 3 | { 4 | "bar": { 5 | "type": "string", 6 | "value": "\"{{baz}}\"" 7 | } 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/array/table-array-string-backslash.toml: -------------------------------------------------------------------------------- 1 | foo = [ { bar="\"{{baz}}\""} ] 2 | -------------------------------------------------------------------------------- /tests/valid/bool/bool.json: -------------------------------------------------------------------------------- 1 | { 2 | "f": { 3 | "type": "bool", 4 | "value": "false" 5 | }, 6 | "t": { 7 | "type": "bool", 8 | "value": "true" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/bool/bool.toml: -------------------------------------------------------------------------------- 1 | t = true 2 | f = false 3 | -------------------------------------------------------------------------------- /tests/valid/comment/at-eof.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": { 3 | "type": "string", 4 | "value": "value" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/comment/at-eof.toml: -------------------------------------------------------------------------------- 1 | # This is a full-line comment 2 | key = "value" # This is a comment at the end of a line 3 | -------------------------------------------------------------------------------- /tests/valid/comment/at-eof2.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": { 3 | "type": "string", 4 | "value": "value" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/comment/at-eof2.toml: -------------------------------------------------------------------------------- 1 | # This is a full-line comment 2 | key = "value" # This is a comment at the end of a line 3 | -------------------------------------------------------------------------------- /tests/valid/comment/everywhere.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": { 3 | "answer": { 4 | "type": "integer", 5 | "value": "42" 6 | }, 7 | "dt": { 8 | "type": "datetime", 9 | "value": "1979-05-27T07:32:12-07:00" 10 | }, 11 | "d": { 12 | "type": "date-local", 13 | "value": "1979-05-27" 14 | }, 15 | "more": [ 16 | { 17 | "type": "integer", 18 | "value": "42" 19 | }, 20 | { 21 | "type": "integer", 22 | "value": "42" 23 | } 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/valid/comment/everywhere.toml: -------------------------------------------------------------------------------- 1 | # Top comment. 2 | # Top comment. 3 | # Top comment. 4 | 5 | # [no-extraneous-groups-please] 6 | 7 | [group] # Comment 8 | answer = 42 # Comment 9 | # no-extraneous-keys-please = 999 10 | # Inbetween comment. 11 | more = [ # Comment 12 | # What about multiple # comments? 13 | # Can you handle it? 14 | # 15 | # Evil. 16 | # Evil. 17 | 42, 42, # Comments within arrays are fun. 18 | # What about multiple # comments? 19 | # Can you handle it? 20 | # 21 | # Evil. 22 | # Evil. 23 | # ] Did I fool you? 24 | ] # Hopefully not. 25 | 26 | # Make sure the space between the datetime and "#" isn't lexed. 27 | dt = 1979-05-27T07:32:12-07:00 # c 28 | d = 1979-05-27 # Comment 29 | -------------------------------------------------------------------------------- /tests/valid/comment/noeol.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/valid/comment/noeol.toml: -------------------------------------------------------------------------------- 1 | # single comment without any eol characters -------------------------------------------------------------------------------- /tests/valid/comment/tricky.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash#tag": { 3 | "#!": { 4 | "type": "string", 5 | "value": "hash bang" 6 | }, 7 | "arr3": [ 8 | { 9 | "type": "string", 10 | "value": "#" 11 | }, 12 | { 13 | "type": "string", 14 | "value": "#" 15 | }, 16 | { 17 | "type": "string", 18 | "value": "###" 19 | } 20 | ], 21 | "arr4": [ 22 | { 23 | "type": "integer", 24 | "value": "1" 25 | }, 26 | { 27 | "type": "integer", 28 | "value": "2" 29 | }, 30 | { 31 | "type": "integer", 32 | "value": "3" 33 | }, 34 | { 35 | "type": "integer", 36 | "value": "4" 37 | } 38 | ], 39 | "arr5": [ 40 | [ 41 | [ 42 | [ 43 | [ 44 | { 45 | "type": "string", 46 | "value": "#" 47 | } 48 | ] 49 | ] 50 | ] 51 | ] 52 | ], 53 | "tbl1": { 54 | "#": { 55 | "type": "string", 56 | "value": "}#" 57 | } 58 | } 59 | }, 60 | "section": { 61 | "8": { 62 | "type": "string", 63 | "value": "eight" 64 | }, 65 | "eleven": { 66 | "type": "float", 67 | "value": "11.1" 68 | }, 69 | "five": { 70 | "type": "float", 71 | "value": "5.5" 72 | }, 73 | "four": { 74 | "type": "string", 75 | "value": "# no comment\n# nor this\n#also not comment" 76 | }, 77 | "one": { 78 | "type": "string", 79 | "value": "11" 80 | }, 81 | "six": { 82 | "type": "integer", 83 | "value": "6" 84 | }, 85 | "ten": { 86 | "type": "float", 87 | "value": "1000.0" 88 | }, 89 | "three": { 90 | "type": "string", 91 | "value": "#" 92 | }, 93 | "two": { 94 | "type": "string", 95 | "value": "22#" 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /tests/valid/comment/tricky.toml: -------------------------------------------------------------------------------- 1 | [section]#attached comment 2 | #[notsection] 3 | one = "11"#cmt 4 | two = "22#" 5 | three = '#' 6 | 7 | four = """# no comment 8 | # nor this 9 | #also not comment"""#is_comment 10 | 11 | five = 5.5#66 12 | six = 6#7 13 | 8 = "eight" 14 | #nine = 99 15 | ten = 10e2#1 16 | eleven = 1.11e1#23 17 | 18 | ["hash#tag"] 19 | "#!" = "hash bang" 20 | arr3 = [ "#", '#', """###""" ] 21 | arr4 = [ 1,# 9, 9, 22 | 2#,9 23 | ,#9 24 | 3#] 25 | ,4] 26 | arr5 = [[[[#["#"], 27 | ["#"]]]]#] 28 | ] 29 | tbl1 = { "#" = '}#'}#}} 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/valid/datetime/datetime.json: -------------------------------------------------------------------------------- 1 | { 2 | "lower": { 3 | "type": "datetime", 4 | "value": "1987-07-05T17:45:00Z" 5 | }, 6 | "space": { 7 | "type": "datetime", 8 | "value": "1987-07-05T17:45:00Z" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/datetime/datetime.toml: -------------------------------------------------------------------------------- 1 | space = 1987-07-05 17:45:00Z 2 | lower = 1987-07-05t17:45:00z 3 | -------------------------------------------------------------------------------- /tests/valid/datetime/local-date.json: -------------------------------------------------------------------------------- 1 | { 2 | "bestdayever": { 3 | "type": "date-local", 4 | "value": "1987-07-05" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/datetime/local-date.toml: -------------------------------------------------------------------------------- 1 | bestdayever = 1987-07-05 2 | -------------------------------------------------------------------------------- /tests/valid/datetime/local-time.json: -------------------------------------------------------------------------------- 1 | { 2 | "besttimeever": { 3 | "type": "time-local", 4 | "value": "17:45:00" 5 | }, 6 | "milliseconds": { 7 | "type": "time-local", 8 | "value": "10:32:00.555" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/datetime/local-time.toml: -------------------------------------------------------------------------------- 1 | besttimeever = 17:45:00 2 | milliseconds = 10:32:00.555 3 | -------------------------------------------------------------------------------- /tests/valid/datetime/local.json: -------------------------------------------------------------------------------- 1 | { 2 | "local": { 3 | "type": "datetime-local", 4 | "value": "1987-07-05T17:45:00" 5 | }, 6 | "milli": { 7 | "type": "datetime-local", 8 | "value": "1977-12-21T10:32:00.555" 9 | }, 10 | "space": { 11 | "type": "datetime-local", 12 | "value": "1987-07-05T17:45:00" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/valid/datetime/local.toml: -------------------------------------------------------------------------------- 1 | local = 1987-07-05T17:45:00 2 | milli = 1977-12-21T10:32:00.555 3 | space = 1987-07-05 17:45:00 4 | -------------------------------------------------------------------------------- /tests/valid/datetime/milliseconds.json: -------------------------------------------------------------------------------- 1 | { 2 | "utc1": { 3 | "type": "datetime", 4 | "value": "1987-07-05T17:45:56.1234Z" 5 | }, 6 | "utc2": { 7 | "type": "datetime", 8 | "value": "1987-07-05T17:45:56.6000Z" 9 | }, 10 | "wita1": { 11 | "type": "datetime", 12 | "value": "1987-07-05T17:45:56.1234+08:00" 13 | }, 14 | "wita2": { 15 | "type": "datetime", 16 | "value": "1987-07-05T17:45:56.6000+08:00" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/valid/datetime/milliseconds.toml: -------------------------------------------------------------------------------- 1 | utc1 = 1987-07-05T17:45:56.1234Z 2 | utc2 = 1987-07-05T17:45:56.6Z 3 | wita1 = 1987-07-05T17:45:56.1234+08:00 4 | wita2 = 1987-07-05T17:45:56.6+08:00 5 | -------------------------------------------------------------------------------- /tests/valid/datetime/timezone.json: -------------------------------------------------------------------------------- 1 | { 2 | "nzdt": { 3 | "type": "datetime", 4 | "value": "1987-07-05T17:45:56+13:00" 5 | }, 6 | "nzst": { 7 | "type": "datetime", 8 | "value": "1987-07-05T17:45:56+12:00" 9 | }, 10 | "pdt": { 11 | "type": "datetime", 12 | "value": "1987-07-05T17:45:56-05:00" 13 | }, 14 | "utc": { 15 | "type": "datetime", 16 | "value": "1987-07-05T17:45:56Z" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/valid/datetime/timezone.toml: -------------------------------------------------------------------------------- 1 | utc = 1987-07-05T17:45:56Z 2 | pdt = 1987-07-05T17:45:56-05:00 3 | nzst = 1987-07-05T17:45:56+12:00 4 | nzdt = 1987-07-05T17:45:56+13:00 # DST 5 | -------------------------------------------------------------------------------- /tests/valid/empty-file.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/valid/empty-file.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattyhall/tomlz/bb7706fb5a752526f74ce544fc15125be8e58495/tests/valid/empty-file.toml -------------------------------------------------------------------------------- /tests/valid/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "best-day-ever": { 3 | "type": "datetime", 4 | "value": "1987-07-05T17:45:00Z" 5 | }, 6 | "numtheory": { 7 | "boring": { 8 | "type": "bool", 9 | "value": "false" 10 | }, 11 | "perfection": [ 12 | { 13 | "type": "integer", 14 | "value": "6" 15 | }, 16 | { 17 | "type": "integer", 18 | "value": "28" 19 | }, 20 | { 21 | "type": "integer", 22 | "value": "496" 23 | } 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/valid/example.toml: -------------------------------------------------------------------------------- 1 | best-day-ever = 1987-07-05T17:45:00Z 2 | 3 | [numtheory] 4 | boring = false 5 | perfection = [6, 28, 496] 6 | -------------------------------------------------------------------------------- /tests/valid/float/exponent.json: -------------------------------------------------------------------------------- 1 | { 2 | "lower": { 3 | "type": "float", 4 | "value": "300.0" 5 | }, 6 | "minustenth": { 7 | "type": "float", 8 | "value": "-0.1" 9 | }, 10 | "neg": { 11 | "type": "float", 12 | "value": "0.03" 13 | }, 14 | "pointlower": { 15 | "type": "float", 16 | "value": "310.0" 17 | }, 18 | "pointupper": { 19 | "type": "float", 20 | "value": "310.0" 21 | }, 22 | "pos": { 23 | "type": "float", 24 | "value": "300.0" 25 | }, 26 | "upper": { 27 | "type": "float", 28 | "value": "300.0" 29 | }, 30 | "zero": { 31 | "type": "float", 32 | "value": "3.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/valid/float/exponent.toml: -------------------------------------------------------------------------------- 1 | lower = 3e2 2 | upper = 3E2 3 | neg = 3e-2 4 | pos = 3E+2 5 | zero = 3e0 6 | pointlower = 3.1e2 7 | pointupper = 3.1E2 8 | minustenth = -1E-1 9 | -------------------------------------------------------------------------------- /tests/valid/float/float.json: -------------------------------------------------------------------------------- 1 | { 2 | "negpi": { 3 | "type": "float", 4 | "value": "-3.14" 5 | }, 6 | "pi": { 7 | "type": "float", 8 | "value": "3.14" 9 | }, 10 | "pospi": { 11 | "type": "float", 12 | "value": "3.14" 13 | }, 14 | "zero-intpart": { 15 | "type": "float", 16 | "value": "0.123" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/valid/float/float.toml: -------------------------------------------------------------------------------- 1 | pi = 3.14 2 | pospi = +3.14 3 | negpi = -3.14 4 | zero-intpart = 0.123 5 | -------------------------------------------------------------------------------- /tests/valid/float/inf-and-nan.json: -------------------------------------------------------------------------------- 1 | { 2 | "infinity": { 3 | "type": "float", 4 | "value": "inf" 5 | }, 6 | "infinity_neg": { 7 | "type": "float", 8 | "value": "-inf" 9 | }, 10 | "infinity_plus": { 11 | "type": "float", 12 | "value": "+inf" 13 | }, 14 | "nan": { 15 | "type": "float", 16 | "value": "nan" 17 | }, 18 | "nan_neg": { 19 | "type": "float", 20 | "value": "nan" 21 | }, 22 | "nan_plus": { 23 | "type": "float", 24 | "value": "nan" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/valid/float/inf-and-nan.toml: -------------------------------------------------------------------------------- 1 | # We don't encode +nan and -nan back with the signs; many languages don't 2 | # support a sign on NaN (it doesn't really make much sense). 3 | nan = nan 4 | nan_neg = -nan 5 | nan_plus = +nan 6 | infinity = inf 7 | infinity_neg = -inf 8 | infinity_plus = +inf 9 | -------------------------------------------------------------------------------- /tests/valid/float/long.json: -------------------------------------------------------------------------------- 1 | { 2 | "longpi": { 3 | "type": "float", 4 | "value": "3.141592653589793" 5 | }, 6 | "neglongpi": { 7 | "type": "float", 8 | "value": "-3.141592653589793" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/float/long.toml: -------------------------------------------------------------------------------- 1 | longpi = 3.141592653589793 2 | neglongpi = -3.141592653589793 3 | -------------------------------------------------------------------------------- /tests/valid/float/underscore.json: -------------------------------------------------------------------------------- 1 | { 2 | "after": { 3 | "type": "float", 4 | "value": "3141.5927" 5 | }, 6 | "before": { 7 | "type": "float", 8 | "value": "3141.5927" 9 | }, 10 | "exponent": { 11 | "type": "float", 12 | "value": "3.0e14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/valid/float/underscore.toml: -------------------------------------------------------------------------------- 1 | before = 3_141.5927 2 | after = 3141.592_7 3 | exponent = 3e1_4 4 | -------------------------------------------------------------------------------- /tests/valid/float/zero.json: -------------------------------------------------------------------------------- 1 | { 2 | "zero": { 3 | "type": "float", 4 | "value": "0" 5 | }, 6 | "signed-pos": { 7 | "type": "float", 8 | "value": "0" 9 | }, 10 | "signed-neg": { 11 | "type": "float", 12 | "value": "0" 13 | }, 14 | "exponent": { 15 | "type": "float", 16 | "value": "0" 17 | }, 18 | "exponent-two-0": { 19 | "type": "float", 20 | "value": "0" 21 | }, 22 | "exponent-signed-pos": { 23 | "type": "float", 24 | "value": "0" 25 | }, 26 | "exponent-signed-neg": { 27 | "type": "float", 28 | "value": "0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/valid/float/zero.toml: -------------------------------------------------------------------------------- 1 | zero = 0.0 2 | signed-pos = +0.0 3 | signed-neg = -0.0 4 | exponent = 0e0 5 | exponent-two-0 = 0e00 6 | exponent-signed-pos = +0e0 7 | exponent-signed-neg = -0e0 8 | -------------------------------------------------------------------------------- /tests/valid/implicit-and-explicit-after.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "b": { 4 | "c": { 5 | "answer": { 6 | "type": "integer", 7 | "value": "42" 8 | } 9 | } 10 | }, 11 | "better": { 12 | "type": "integer", 13 | "value": "43" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/implicit-and-explicit-after.toml: -------------------------------------------------------------------------------- 1 | [a.b.c] 2 | answer = 42 3 | 4 | [a] 5 | better = 43 6 | -------------------------------------------------------------------------------- /tests/valid/implicit-and-explicit-before.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "b": { 4 | "c": { 5 | "answer": { 6 | "type": "integer", 7 | "value": "42" 8 | } 9 | } 10 | }, 11 | "better": { 12 | "type": "integer", 13 | "value": "43" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/implicit-and-explicit-before.toml: -------------------------------------------------------------------------------- 1 | [a] 2 | better = 43 3 | 4 | [a.b.c] 5 | answer = 42 6 | -------------------------------------------------------------------------------- /tests/valid/implicit-groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "b": { 4 | "c": { 5 | "answer": { 6 | "type": "integer", 7 | "value": "42" 8 | } 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/implicit-groups.toml: -------------------------------------------------------------------------------- 1 | [a.b.c] 2 | answer = 42 3 | -------------------------------------------------------------------------------- /tests/valid/inline-table/array.json: -------------------------------------------------------------------------------- 1 | { 2 | "people": [ 3 | { 4 | "first_name": { 5 | "type": "string", 6 | "value": "Bruce" 7 | }, 8 | "last_name": { 9 | "type": "string", 10 | "value": "Springsteen" 11 | } 12 | }, 13 | { 14 | "first_name": { 15 | "type": "string", 16 | "value": "Eric" 17 | }, 18 | "last_name": { 19 | "type": "string", 20 | "value": "Clapton" 21 | } 22 | }, 23 | { 24 | "first_name": { 25 | "type": "string", 26 | "value": "Bob" 27 | }, 28 | "last_name": { 29 | "type": "string", 30 | "value": "Seger" 31 | } 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /tests/valid/inline-table/array.toml: -------------------------------------------------------------------------------- 1 | people = [{first_name = "Bruce", last_name = "Springsteen"}, 2 | {first_name = "Eric", last_name = "Clapton"}, 3 | {first_name = "Bob", last_name = "Seger"}] 4 | -------------------------------------------------------------------------------- /tests/valid/inline-table/bool.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "a": { 4 | "type": "bool", 5 | "value": "true" 6 | }, 7 | "b": { 8 | "type": "bool", 9 | "value": "false" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/inline-table/bool.toml: -------------------------------------------------------------------------------- 1 | a = {a = true, b = false} 2 | -------------------------------------------------------------------------------- /tests/valid/inline-table/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "empty1": {}, 3 | "empty2": {}, 4 | "empty_in_array": [ 5 | { 6 | "not_empty": { 7 | "type": "integer", 8 | "value": "1" 9 | } 10 | }, 11 | {} 12 | ], 13 | "empty_in_array2": [ 14 | {}, 15 | { 16 | "not_empty": { 17 | "type": "integer", 18 | "value": "1" 19 | } 20 | } 21 | ], 22 | "many_empty": [ 23 | {}, 24 | {}, 25 | {} 26 | ], 27 | "nested_empty": { 28 | "empty": {} 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/valid/inline-table/empty.toml: -------------------------------------------------------------------------------- 1 | empty1 = {} 2 | empty2 = { } 3 | empty_in_array = [ { not_empty = 1 }, {} ] 4 | empty_in_array2 = [{},{not_empty=1}] 5 | many_empty = [{},{},{}] 6 | nested_empty = {"empty"={}} 7 | -------------------------------------------------------------------------------- /tests/valid/inline-table/end-in-bool.json: -------------------------------------------------------------------------------- 1 | { 2 | "black": { 3 | "allow_prereleases": { 4 | "type": "bool", 5 | "value": "true" 6 | }, 7 | "python": { 8 | "type": "string", 9 | "value": "\u003e3.6" 10 | }, 11 | "version": { 12 | "type": "string", 13 | "value": "\u003e=18.9b0" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/inline-table/end-in-bool.toml: -------------------------------------------------------------------------------- 1 | black = { python=">3.6", version=">=18.9b0", allow_prereleases=true } 2 | -------------------------------------------------------------------------------- /tests/valid/inline-table/inline-table.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": { 3 | "first": { 4 | "type": "string", 5 | "value": "Tom" 6 | }, 7 | "last": { 8 | "type": "string", 9 | "value": "Preston-Werner" 10 | } 11 | }, 12 | "point": { 13 | "x": { 14 | "type": "integer", 15 | "value": "1" 16 | }, 17 | "y": { 18 | "type": "integer", 19 | "value": "2" 20 | } 21 | }, 22 | "simple": { 23 | "a": { 24 | "type": "integer", 25 | "value": "1" 26 | } 27 | }, 28 | "str-key": { 29 | "a": { 30 | "type": "integer", 31 | "value": "1" 32 | } 33 | }, 34 | "table-array": [ 35 | { 36 | "a": { 37 | "type": "integer", 38 | "value": "1" 39 | } 40 | }, 41 | { 42 | "b": { 43 | "type": "integer", 44 | "value": "2" 45 | } 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /tests/valid/inline-table/inline-table.toml: -------------------------------------------------------------------------------- 1 | name = { first = "Tom", last = "Preston-Werner" } 2 | point = { x = 1, y = 2 } 3 | simple = { a = 1 } 4 | str-key = { "a" = 1 } 5 | table-array = [{ "a" = 1 }, { "b" = 2 }] 6 | -------------------------------------------------------------------------------- /tests/valid/inline-table/key-dotted.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "a": { 4 | "b": { 5 | "type": "integer", 6 | "value": "1" 7 | } 8 | } 9 | }, 10 | "arr": [ 11 | { 12 | "T": { 13 | "a": { 14 | "b": { 15 | "type": "integer", 16 | "value": "1" 17 | } 18 | } 19 | }, 20 | "t": { 21 | "a": { 22 | "b": { 23 | "type": "integer", 24 | "value": "1" 25 | } 26 | } 27 | } 28 | }, 29 | { 30 | "T": { 31 | "a": { 32 | "b": { 33 | "type": "integer", 34 | "value": "2" 35 | } 36 | } 37 | }, 38 | "t": { 39 | "a": { 40 | "b": { 41 | "type": "integer", 42 | "value": "2" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "b": { 49 | "a": { 50 | "b": { 51 | "type": "integer", 52 | "value": "1" 53 | } 54 | } 55 | }, 56 | "c": { 57 | "a": { 58 | "b": { 59 | "type": "integer", 60 | "value": "1" 61 | } 62 | } 63 | }, 64 | "d": { 65 | "a": { 66 | "b": { 67 | "type": "integer", 68 | "value": "1" 69 | } 70 | } 71 | }, 72 | "e": { 73 | "a": { 74 | "b": { 75 | "type": "integer", 76 | "value": "1" 77 | } 78 | } 79 | }, 80 | "inline": { 81 | "a": { 82 | "b": { 83 | "type": "integer", 84 | "value": "42" 85 | } 86 | } 87 | }, 88 | "many": { 89 | "dots": { 90 | "here": { 91 | "dot": { 92 | "dot": { 93 | "dot": { 94 | "a": { 95 | "b": { 96 | "c": { 97 | "type": "integer", 98 | "value": "1" 99 | }, 100 | "d": { 101 | "type": "integer", 102 | "value": "2" 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | } 111 | }, 112 | "tbl": { 113 | "a": { 114 | "b": { 115 | "c": { 116 | "d": { 117 | "e": { 118 | "type": "integer", 119 | "value": "1" 120 | } 121 | } 122 | } 123 | } 124 | }, 125 | "x": { 126 | "a": { 127 | "b": { 128 | "c": { 129 | "d": { 130 | "e": { 131 | "type": "integer", 132 | "value": "1" 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /tests/valid/inline-table/key-dotted.toml: -------------------------------------------------------------------------------- 1 | inline = {a.b = 42} 2 | 3 | many.dots.here.dot.dot.dot = {a.b.c = 1, a.b.d = 2} 4 | 5 | a = { a.b = 1 } 6 | b = { "a"."b" = 1 } 7 | c = { a . b = 1 } 8 | d = { 'a' . "b" = 1 } 9 | e = {a.b=1} 10 | 11 | [tbl] 12 | a.b.c = {d.e=1} 13 | 14 | [tbl.x] 15 | a.b.c = {d.e=1} 16 | 17 | [[arr]] 18 | t = {a.b=1} 19 | T = {a.b=1} 20 | 21 | [[arr]] 22 | t = {a.b=2} 23 | T = {a.b=2} 24 | -------------------------------------------------------------------------------- /tests/valid/inline-table/multiline.json: -------------------------------------------------------------------------------- 1 | { 2 | "tbl_multiline": { 3 | "a": { 4 | "type": "integer", 5 | "value": "1" 6 | }, 7 | "b": { 8 | "type": "string", 9 | "value": "multiline\n" 10 | }, 11 | "c": { 12 | "type": "string", 13 | "value": "and yet\nanother line" 14 | }, 15 | "d": { 16 | "type": "integer", 17 | "value": "4" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/valid/inline-table/multiline.toml: -------------------------------------------------------------------------------- 1 | tbl_multiline = { a = 1, b = """ 2 | multiline 3 | """, c = """and yet 4 | another line""", d = 4 } 5 | -------------------------------------------------------------------------------- /tests/valid/inline-table/nest.json: -------------------------------------------------------------------------------- 1 | { 2 | "arr_arr_tbl_empty": [ 3 | [ 4 | {} 5 | ] 6 | ], 7 | "arr_arr_tbl_val": [ 8 | [ 9 | { 10 | "one": { 11 | "type": "integer", 12 | "value": "1" 13 | } 14 | } 15 | ] 16 | ], 17 | "arr_arr_tbls": [ 18 | [ 19 | { 20 | "one": { 21 | "type": "integer", 22 | "value": "1" 23 | } 24 | }, 25 | { 26 | "two": { 27 | "type": "integer", 28 | "value": "2" 29 | } 30 | } 31 | ] 32 | ], 33 | "arr_tbl_tbl": [ 34 | { 35 | "tbl": { 36 | "one": { 37 | "type": "integer", 38 | "value": "1" 39 | } 40 | } 41 | } 42 | ], 43 | "tbl_arr_tbl": { 44 | "arr_tbl": [ 45 | { 46 | "one": { 47 | "type": "integer", 48 | "value": "1" 49 | } 50 | } 51 | ] 52 | }, 53 | "tbl_tbl_empty": { 54 | "tbl_0": {} 55 | }, 56 | "tbl_tbl_val": { 57 | "tbl_1": { 58 | "one": { 59 | "type": "integer", 60 | "value": "1" 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/valid/inline-table/nest.toml: -------------------------------------------------------------------------------- 1 | tbl_tbl_empty = { tbl_0 = {} } 2 | tbl_tbl_val = { tbl_1 = { one = 1 } } 3 | tbl_arr_tbl = { arr_tbl = [ { one = 1 } ] } 4 | arr_tbl_tbl = [ { tbl = { one = 1 } } ] 5 | 6 | # Array-of-array-of-table is interesting because it can only 7 | # be represented in inline form. 8 | arr_arr_tbl_empty = [ [ {} ] ] 9 | arr_arr_tbl_val = [ [ { one = 1 } ] ] 10 | arr_arr_tbls = [ [ { one = 1 }, { two = 2 } ] ] 11 | -------------------------------------------------------------------------------- /tests/valid/integer/integer.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "integer", 4 | "value": "42" 5 | }, 6 | "neganswer": { 7 | "type": "integer", 8 | "value": "-42" 9 | }, 10 | "posanswer": { 11 | "type": "integer", 12 | "value": "42" 13 | }, 14 | "zero": { 15 | "type": "integer", 16 | "value": "0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/valid/integer/integer.toml: -------------------------------------------------------------------------------- 1 | answer = 42 2 | posanswer = +42 3 | neganswer = -42 4 | zero = 0 5 | -------------------------------------------------------------------------------- /tests/valid/integer/literals.json: -------------------------------------------------------------------------------- 1 | { 2 | "bin1": { 3 | "type": "integer", 4 | "value": "214" 5 | }, 6 | "bin2": { 7 | "type": "integer", 8 | "value": "5" 9 | }, 10 | "hex1": { 11 | "type": "integer", 12 | "value": "3735928559" 13 | }, 14 | "hex2": { 15 | "type": "integer", 16 | "value": "3735928559" 17 | }, 18 | "hex3": { 19 | "type": "integer", 20 | "value": "3735928559" 21 | }, 22 | "hex4": { 23 | "type": "integer", 24 | "value": "2439" 25 | }, 26 | "oct1": { 27 | "type": "integer", 28 | "value": "342391" 29 | }, 30 | "oct2": { 31 | "type": "integer", 32 | "value": "493" 33 | }, 34 | "oct3": { 35 | "type": "integer", 36 | "value": "501" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/valid/integer/literals.toml: -------------------------------------------------------------------------------- 1 | bin1 = 0b11010110 2 | bin2 = 0b1_0_1 3 | 4 | oct1 = 0o01234567 5 | oct2 = 0o755 6 | oct3 = 0o7_6_5 7 | 8 | hex1 = 0xDEADBEEF 9 | hex2 = 0xdeadbeef 10 | hex3 = 0xdead_beef 11 | hex4 = 0x00987 12 | -------------------------------------------------------------------------------- /tests/valid/integer/long.json: -------------------------------------------------------------------------------- 1 | { 2 | "int64-max": { 3 | "type": "integer", 4 | "value": "9223372036854775807" 5 | }, 6 | "int64-max-neg": { 7 | "type": "integer", 8 | "value": "-9223372036854775808" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/integer/long.toml: -------------------------------------------------------------------------------- 1 | int64-max = 9223372036854775807 2 | int64-max-neg = -9223372036854775808 3 | -------------------------------------------------------------------------------- /tests/valid/integer/underscore.json: -------------------------------------------------------------------------------- 1 | { 2 | "kilo": { 3 | "type": "integer", 4 | "value": "1000" 5 | }, 6 | "x": { 7 | "type": "integer", 8 | "value": "1111" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/integer/underscore.toml: -------------------------------------------------------------------------------- 1 | kilo = 1_000 2 | x = 1_1_1_1 3 | -------------------------------------------------------------------------------- /tests/valid/integer/zero.json: -------------------------------------------------------------------------------- 1 | { 2 | "a2": { 3 | "type": "integer", 4 | "value": "0" 5 | }, 6 | "a3": { 7 | "type": "integer", 8 | "value": "0" 9 | }, 10 | "b1": { 11 | "type": "integer", 12 | "value": "0" 13 | }, 14 | "b2": { 15 | "type": "integer", 16 | "value": "0" 17 | }, 18 | "b3": { 19 | "type": "integer", 20 | "value": "0" 21 | }, 22 | "d1": { 23 | "type": "integer", 24 | "value": "0" 25 | }, 26 | "d2": { 27 | "type": "integer", 28 | "value": "0" 29 | }, 30 | "d3": { 31 | "type": "integer", 32 | "value": "0" 33 | }, 34 | "h1": { 35 | "type": "integer", 36 | "value": "0" 37 | }, 38 | "h2": { 39 | "type": "integer", 40 | "value": "0" 41 | }, 42 | "h3": { 43 | "type": "integer", 44 | "value": "0" 45 | }, 46 | "o1": { 47 | "type": "integer", 48 | "value": "0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/valid/integer/zero.toml: -------------------------------------------------------------------------------- 1 | d1 = 0 2 | d2 = +0 3 | d3 = -0 4 | 5 | h1 = 0x0 6 | h2 = 0x00 7 | h3 = 0x00000 8 | 9 | o1 = 0o0 10 | a2 = 0o00 11 | a3 = 0o00000 12 | 13 | b1 = 0b0 14 | b2 = 0b00 15 | b3 = 0b00000 16 | -------------------------------------------------------------------------------- /tests/valid/key/alphanum.json: -------------------------------------------------------------------------------- 1 | { 2 | "000111": { 3 | "type": "string", 4 | "value": "leading" 5 | }, 6 | "10e3": { 7 | "type": "string", 8 | "value": "false float" 9 | }, 10 | "123": { 11 | "type": "string", 12 | "value": "num" 13 | }, 14 | "2018_10": { 15 | "001": { 16 | "type": "integer", 17 | "value": "1" 18 | } 19 | }, 20 | "34-11": { 21 | "type": "integer", 22 | "value": "23" 23 | }, 24 | "a-a-a": { 25 | "_": { 26 | "type": "bool", 27 | "value": "false" 28 | } 29 | }, 30 | "alpha": { 31 | "type": "string", 32 | "value": "a" 33 | }, 34 | "one1two2": { 35 | "type": "string", 36 | "value": "mixed" 37 | }, 38 | "under_score": { 39 | "type": "string", 40 | "value": "___" 41 | }, 42 | "with-dash": { 43 | "type": "string", 44 | "value": "dashed" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/valid/key/alphanum.toml: -------------------------------------------------------------------------------- 1 | alpha = "a" 2 | 123 = "num" 3 | 000111 = "leading" 4 | 10e3 = "false float" 5 | one1two2 = "mixed" 6 | with-dash = "dashed" 7 | under_score = "___" 8 | 34-11 = 23 9 | 10 | [2018_10] 11 | 001 = 1 12 | 13 | [a-a-a] 14 | _ = false 15 | -------------------------------------------------------------------------------- /tests/valid/key/case-sensitive.json: -------------------------------------------------------------------------------- 1 | { 2 | "Section": { 3 | "M": { 4 | "type": "string", 5 | "value": "latin letter M" 6 | }, 7 | "name": { 8 | "type": "string", 9 | "value": "different section!!" 10 | }, 11 | "Μ": { 12 | "type": "string", 13 | "value": "greek capital letter MU" 14 | }, 15 | "μ": { 16 | "type": "string", 17 | "value": "greek small letter mu" 18 | } 19 | }, 20 | "sectioN": { 21 | "type": "string", 22 | "value": "NN" 23 | }, 24 | "section": { 25 | "NAME": { 26 | "type": "string", 27 | "value": "upper" 28 | }, 29 | "Name": { 30 | "type": "string", 31 | "value": "capitalized" 32 | }, 33 | "name": { 34 | "type": "string", 35 | "value": "lower" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/valid/key/case-sensitive.toml: -------------------------------------------------------------------------------- 1 | sectioN = "NN" 2 | 3 | [section] 4 | name = "lower" 5 | NAME = "upper" 6 | Name = "capitalized" 7 | 8 | [Section] 9 | name = "different section!!" 10 | "μ" = "greek small letter mu" 11 | "Μ" = "greek capital letter MU" 12 | M = "latin letter M" 13 | 14 | -------------------------------------------------------------------------------- /tests/valid/key/dotted.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "few": { 4 | "dots": { 5 | "polka": { 6 | "dance-with": { 7 | "type": "string", 8 | "value": "Dot" 9 | }, 10 | "dot": { 11 | "type": "string", 12 | "value": "again?" 13 | } 14 | } 15 | } 16 | } 17 | }, 18 | "arr": [ 19 | { 20 | "a": { 21 | "b": { 22 | "c": { 23 | "type": "integer", 24 | "value": "1" 25 | }, 26 | "d": { 27 | "type": "integer", 28 | "value": "2" 29 | } 30 | } 31 | } 32 | }, 33 | { 34 | "a": { 35 | "b": { 36 | "c": { 37 | "type": "integer", 38 | "value": "3" 39 | }, 40 | "d": { 41 | "type": "integer", 42 | "value": "4" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "count": { 49 | "a": { 50 | "type": "integer", 51 | "value": "1" 52 | }, 53 | "b": { 54 | "type": "integer", 55 | "value": "2" 56 | }, 57 | "c": { 58 | "type": "integer", 59 | "value": "3" 60 | }, 61 | "d": { 62 | "type": "integer", 63 | "value": "4" 64 | }, 65 | "e": { 66 | "type": "integer", 67 | "value": "5" 68 | }, 69 | "f": { 70 | "type": "integer", 71 | "value": "6" 72 | }, 73 | "g": { 74 | "type": "integer", 75 | "value": "7" 76 | }, 77 | "h": { 78 | "type": "integer", 79 | "value": "8" 80 | }, 81 | "i": { 82 | "type": "integer", 83 | "value": "9" 84 | }, 85 | "j": { 86 | "type": "integer", 87 | "value": "10" 88 | }, 89 | "k": { 90 | "type": "integer", 91 | "value": "11" 92 | }, 93 | "l": { 94 | "type": "integer", 95 | "value": "12" 96 | } 97 | }, 98 | "many": { 99 | "dots": { 100 | "here": { 101 | "dot": { 102 | "dot": { 103 | "dot": { 104 | "type": "integer", 105 | "value": "42" 106 | } 107 | } 108 | } 109 | } 110 | } 111 | }, 112 | "name": { 113 | "first": { 114 | "type": "string", 115 | "value": "Arthur" 116 | }, 117 | "last": { 118 | "type": "string", 119 | "value": "Dent" 120 | } 121 | }, 122 | "tbl": { 123 | "a": { 124 | "b": { 125 | "c": { 126 | "type": "float", 127 | "value": "42.666" 128 | } 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /tests/valid/key/dotted.toml: -------------------------------------------------------------------------------- 1 | # Note: this file contains literal tab characters. 2 | 3 | name.first = "Arthur" 4 | "name".'last' = "Dent" 5 | 6 | many.dots.here.dot.dot.dot = 42 7 | 8 | # Space are ignored, and key parts can be quoted. 9 | count.a = 1 10 | count . b = 2 11 | "count"."c" = 3 12 | "count" . "d" = 4 13 | 'count'.'e' = 5 14 | 'count' . 'f' = 6 15 | "count".'g' = 7 16 | "count" . 'h' = 8 17 | count.'i' = 9 18 | count . 'j' = 10 19 | "count".k = 11 20 | "count" . l = 12 21 | 22 | [tbl] 23 | a.b.c = 42.666 24 | 25 | [a.few.dots] 26 | polka.dot = "again?" 27 | polka.dance-with = "Dot" 28 | 29 | [[arr]] 30 | a.b.c=1 31 | a.b.d=2 32 | 33 | [[arr]] 34 | a.b.c=3 35 | a.b.d=4 36 | -------------------------------------------------------------------------------- /tests/valid/key/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "": { 3 | "type": "string", 4 | "value": "blank" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/key/empty.toml: -------------------------------------------------------------------------------- 1 | "" = "blank" 2 | -------------------------------------------------------------------------------- /tests/valid/key/equals-nospace.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "integer", 4 | "value": "42" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/key/equals-nospace.toml: -------------------------------------------------------------------------------- 1 | answer=42 2 | -------------------------------------------------------------------------------- /tests/valid/key/escapes.json: -------------------------------------------------------------------------------- 1 | { 2 | "\n": { 3 | "type": "string", 4 | "value": "newline" 5 | }, 6 | "\"": { 7 | "type": "string", 8 | "value": "just a quote" 9 | }, 10 | "\"quoted\"": { 11 | "quote": { 12 | "type": "bool", 13 | "value": "true" 14 | } 15 | }, 16 | "a.b": { 17 | "À": {} 18 | }, 19 | "backsp\u0008\u0008": {}, 20 | "À": { 21 | "type": "string", 22 | "value": "latin capital letter A with grave" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/valid/key/escapes.toml: -------------------------------------------------------------------------------- 1 | "\n" = "newline" 2 | "\u00c0" = "latin capital letter A with grave" 3 | "\"" = "just a quote" 4 | 5 | ["backsp\b\b"] 6 | 7 | ["\"quoted\""] 8 | quote = true 9 | 10 | ["a.b"."\u00c0"] 11 | -------------------------------------------------------------------------------- /tests/valid/key/numeric-dotted.json: -------------------------------------------------------------------------------- 1 | { 2 | "1": { 3 | "2": { 4 | "type": "integer", 5 | "value": "3" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/valid/key/numeric-dotted.toml: -------------------------------------------------------------------------------- 1 | 1.2 = 3 2 | -------------------------------------------------------------------------------- /tests/valid/key/numeric.json: -------------------------------------------------------------------------------- 1 | { 2 | "1": { 3 | "type": "integer", 4 | "value": "1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/key/numeric.toml: -------------------------------------------------------------------------------- 1 | 1 = 1 2 | -------------------------------------------------------------------------------- /tests/valid/key/quoted-dots.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": { 3 | "type": "integer", 4 | "value": "1" 5 | }, 6 | "plain_table": { 7 | "plain": { 8 | "type": "integer", 9 | "value": "3" 10 | }, 11 | "with.dot": { 12 | "type": "integer", 13 | "value": "4" 14 | } 15 | }, 16 | "table": { 17 | "withdot": { 18 | "key.with.dots": { 19 | "type": "integer", 20 | "value": "6" 21 | }, 22 | "plain": { 23 | "type": "integer", 24 | "value": "5" 25 | } 26 | } 27 | }, 28 | "with.dot": { 29 | "type": "integer", 30 | "value": "2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/valid/key/quoted-dots.toml: -------------------------------------------------------------------------------- 1 | plain = 1 2 | "with.dot" = 2 3 | 4 | [plain_table] 5 | plain = 3 6 | "with.dot" = 4 7 | 8 | [table.withdot] 9 | plain = 5 10 | "key.with.dots" = 6 11 | -------------------------------------------------------------------------------- /tests/valid/key/space.json: -------------------------------------------------------------------------------- 1 | { 2 | " c d ": { 3 | "type": "integer", 4 | "value": "2" 5 | }, 6 | " tbl ": { 7 | "\ttab\ttab\t": { 8 | "type": "string", 9 | "value": "tab" 10 | } 11 | }, 12 | "a b": { 13 | "type": "integer", 14 | "value": "1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/valid/key/space.toml: -------------------------------------------------------------------------------- 1 | # Keep whitespace inside quotes keys at all positions. 2 | "a b" = 1 3 | " c d " = 2 4 | 5 | [ " tbl " ] 6 | "\ttab\ttab\t" = "tab" 7 | -------------------------------------------------------------------------------- /tests/valid/key/special-chars.json: -------------------------------------------------------------------------------- 1 | { 2 | "=~!@$^\u0026*()_+-`1234567890[]|/?\u003e\u003c.,;:'=": { 3 | "type": "integer", 4 | "value": "1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/key/special-chars.toml: -------------------------------------------------------------------------------- 1 | "=~!@$^&*()_+-`1234567890[]|/?><.,;:'=" = 1 2 | -------------------------------------------------------------------------------- /tests/valid/key/special-word.json: -------------------------------------------------------------------------------- 1 | { 2 | "false": { 3 | "type": "bool", 4 | "value": "false" 5 | }, 6 | "inf": { 7 | "type": "integer", 8 | "value": "100000000" 9 | }, 10 | "nan": { 11 | "type": "string", 12 | "value": "ceci n'est pas un nombre" 13 | }, 14 | "true": { 15 | "type": "integer", 16 | "value": "1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/valid/key/special-word.toml: -------------------------------------------------------------------------------- 1 | false = false 2 | true = 1 3 | inf = 100000000 4 | nan = "ceci n'est pas un nombre" 5 | 6 | -------------------------------------------------------------------------------- /tests/valid/newline-crlf.json: -------------------------------------------------------------------------------- 1 | { 2 | "newline": { 3 | "type": "string", 4 | "value": "crlf" 5 | }, 6 | "os": { 7 | "type": "string", 8 | "value": "DOS" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/newline-crlf.toml: -------------------------------------------------------------------------------- 1 | os = "DOS" 2 | newline = "crlf" 3 | -------------------------------------------------------------------------------- /tests/valid/newline-lf.json: -------------------------------------------------------------------------------- 1 | { 2 | "newline": { 3 | "type": "string", 4 | "value": "lf" 5 | }, 6 | "os": { 7 | "type": "string", 8 | "value": "unix" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/newline-lf.toml: -------------------------------------------------------------------------------- 1 | os = "unix" 2 | newline = "lf" 3 | -------------------------------------------------------------------------------- /tests/valid/spec-example-1-compact.json: -------------------------------------------------------------------------------- 1 | { 2 | "clients": { 3 | "data": [ 4 | [ 5 | { 6 | "type": "string", 7 | "value": "gamma" 8 | }, 9 | { 10 | "type": "string", 11 | "value": "delta" 12 | } 13 | ], 14 | [ 15 | { 16 | "type": "integer", 17 | "value": "1" 18 | }, 19 | { 20 | "type": "integer", 21 | "value": "2" 22 | } 23 | ] 24 | ], 25 | "hosts": [ 26 | { 27 | "type": "string", 28 | "value": "alpha" 29 | }, 30 | { 31 | "type": "string", 32 | "value": "omega" 33 | } 34 | ] 35 | }, 36 | "database": { 37 | "connection_max": { 38 | "type": "integer", 39 | "value": "5000" 40 | }, 41 | "enabled": { 42 | "type": "bool", 43 | "value": "true" 44 | }, 45 | "ports": [ 46 | { 47 | "type": "integer", 48 | "value": "8001" 49 | }, 50 | { 51 | "type": "integer", 52 | "value": "8001" 53 | }, 54 | { 55 | "type": "integer", 56 | "value": "8002" 57 | } 58 | ], 59 | "server": { 60 | "type": "string", 61 | "value": "192.168.1.1" 62 | } 63 | }, 64 | "owner": { 65 | "dob": { 66 | "type": "datetime", 67 | "value": "1979-05-27T07:32:00-08:00" 68 | }, 69 | "name": { 70 | "type": "string", 71 | "value": "Lance Uppercut" 72 | } 73 | }, 74 | "servers": { 75 | "alpha": { 76 | "dc": { 77 | "type": "string", 78 | "value": "eqdc10" 79 | }, 80 | "ip": { 81 | "type": "string", 82 | "value": "10.0.0.1" 83 | } 84 | }, 85 | "beta": { 86 | "dc": { 87 | "type": "string", 88 | "value": "eqdc10" 89 | }, 90 | "ip": { 91 | "type": "string", 92 | "value": "10.0.0.2" 93 | } 94 | } 95 | }, 96 | "title": { 97 | "type": "string", 98 | "value": "TOML Example" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /tests/valid/spec-example-1-compact.toml: -------------------------------------------------------------------------------- 1 | #Useless spaces eliminated. 2 | title="TOML Example" 3 | [owner] 4 | name="Lance Uppercut" 5 | dob=1979-05-27T07:32:00-08:00#First class dates 6 | [database] 7 | server="192.168.1.1" 8 | ports=[8001,8001,8002] 9 | connection_max=5000 10 | enabled=true 11 | [servers] 12 | [servers.alpha] 13 | ip="10.0.0.1" 14 | dc="eqdc10" 15 | [servers.beta] 16 | ip="10.0.0.2" 17 | dc="eqdc10" 18 | [clients] 19 | data=[["gamma","delta"],[1,2]] 20 | hosts=[ 21 | "alpha", 22 | "omega" 23 | ] 24 | -------------------------------------------------------------------------------- /tests/valid/spec-example-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "clients": { 3 | "data": [ 4 | [ 5 | { 6 | "type": "string", 7 | "value": "gamma" 8 | }, 9 | { 10 | "type": "string", 11 | "value": "delta" 12 | } 13 | ], 14 | [ 15 | { 16 | "type": "integer", 17 | "value": "1" 18 | }, 19 | { 20 | "type": "integer", 21 | "value": "2" 22 | } 23 | ] 24 | ], 25 | "hosts": [ 26 | { 27 | "type": "string", 28 | "value": "alpha" 29 | }, 30 | { 31 | "type": "string", 32 | "value": "omega" 33 | } 34 | ] 35 | }, 36 | "database": { 37 | "connection_max": { 38 | "type": "integer", 39 | "value": "5000" 40 | }, 41 | "enabled": { 42 | "type": "bool", 43 | "value": "true" 44 | }, 45 | "ports": [ 46 | { 47 | "type": "integer", 48 | "value": "8001" 49 | }, 50 | { 51 | "type": "integer", 52 | "value": "8001" 53 | }, 54 | { 55 | "type": "integer", 56 | "value": "8002" 57 | } 58 | ], 59 | "server": { 60 | "type": "string", 61 | "value": "192.168.1.1" 62 | } 63 | }, 64 | "owner": { 65 | "dob": { 66 | "type": "datetime", 67 | "value": "1979-05-27T07:32:00-08:00" 68 | }, 69 | "name": { 70 | "type": "string", 71 | "value": "Lance Uppercut" 72 | } 73 | }, 74 | "servers": { 75 | "alpha": { 76 | "dc": { 77 | "type": "string", 78 | "value": "eqdc10" 79 | }, 80 | "ip": { 81 | "type": "string", 82 | "value": "10.0.0.1" 83 | } 84 | }, 85 | "beta": { 86 | "dc": { 87 | "type": "string", 88 | "value": "eqdc10" 89 | }, 90 | "ip": { 91 | "type": "string", 92 | "value": "10.0.0.2" 93 | } 94 | } 95 | }, 96 | "title": { 97 | "type": "string", 98 | "value": "TOML Example" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /tests/valid/spec-example-1.toml: -------------------------------------------------------------------------------- 1 | # This is a TOML document. Boom. 2 | 3 | title = "TOML Example" 4 | 5 | [owner] 6 | name = "Lance Uppercut" 7 | dob = 1979-05-27T07:32:00-08:00 # First class dates? Why not? 8 | 9 | [database] 10 | server = "192.168.1.1" 11 | ports = [ 8001, 8001, 8002 ] 12 | connection_max = 5000 13 | enabled = true 14 | 15 | [servers] 16 | 17 | # You can indent as you please. Tabs or spaces. TOML don't care. 18 | [servers.alpha] 19 | ip = "10.0.0.1" 20 | dc = "eqdc10" 21 | 22 | [servers.beta] 23 | ip = "10.0.0.2" 24 | dc = "eqdc10" 25 | 26 | [clients] 27 | data = [ ["gamma", "delta"], [1, 2] ] 28 | 29 | # Line breaks are OK when inside arrays 30 | hosts = [ 31 | "alpha", 32 | "omega" 33 | ] 34 | -------------------------------------------------------------------------------- /tests/valid/string/double-quote-escape.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "type": "string", 4 | "value": "\"one\"" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/double-quote-escape.toml: -------------------------------------------------------------------------------- 1 | test = "\"one\"" 2 | -------------------------------------------------------------------------------- /tests/valid/string/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "string", 4 | "value": "" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/empty.toml: -------------------------------------------------------------------------------- 1 | answer = "" 2 | -------------------------------------------------------------------------------- /tests/valid/string/escape-esc.json: -------------------------------------------------------------------------------- 1 | { 2 | "esc": { 3 | "type": "string", 4 | "value": "\u001b There is no escape! \u001b" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/escape-esc.toml: -------------------------------------------------------------------------------- 1 | esc = "\e There is no escape! \e" 2 | -------------------------------------------------------------------------------- /tests/valid/string/escape-tricky.json: -------------------------------------------------------------------------------- 1 | { 2 | "end_esc": { 3 | "type": "string", 4 | "value": "String does not end here\" but ends here\\" 5 | }, 6 | "lit_end_esc": { 7 | "type": "string", 8 | "value": "String ends here\\" 9 | }, 10 | "lit_multiline_end": { 11 | "type": "string", 12 | "value": "There is no escape\\" 13 | }, 14 | "lit_multiline_not_unicode": { 15 | "type": "string", 16 | "value": "\\u007f" 17 | }, 18 | "multiline_end_esc": { 19 | "type": "string", 20 | "value": "When will it end? \"\"\"...\"\"\" should be here\"" 21 | }, 22 | "multiline_not_unicode": { 23 | "type": "string", 24 | "value": "\\u0041" 25 | }, 26 | "multiline_unicode": { 27 | "type": "string", 28 | "value": " " 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/valid/string/escape-tricky.toml: -------------------------------------------------------------------------------- 1 | end_esc = "String does not end here\" but ends here\\" 2 | lit_end_esc = 'String ends here\' 3 | 4 | multiline_unicode = """ 5 | \u00a0""" 6 | 7 | multiline_not_unicode = """ 8 | \\u0041""" 9 | 10 | multiline_end_esc = """When will it end? \"""...""\" should be here\"""" 11 | 12 | lit_multiline_not_unicode = ''' 13 | \u007f''' 14 | 15 | lit_multiline_end = '''There is no escape\''' 16 | -------------------------------------------------------------------------------- /tests/valid/string/escaped-escape.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "string", 4 | "value": "\\x64" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/escaped-escape.toml: -------------------------------------------------------------------------------- 1 | answer = "\\x64" 2 | -------------------------------------------------------------------------------- /tests/valid/string/escapes.json: -------------------------------------------------------------------------------- 1 | { 2 | "backslash": { 3 | "type": "string", 4 | "value": "This string has a \\ backslash character." 5 | }, 6 | "backspace": { 7 | "type": "string", 8 | "value": "This string has a \u0008 backspace character." 9 | }, 10 | "carriage": { 11 | "type": "string", 12 | "value": "This string has a \r carriage return character." 13 | }, 14 | "delete": { 15 | "type": "string", 16 | "value": "This string has a  delete control code." 17 | }, 18 | "formfeed": { 19 | "type": "string", 20 | "value": "This string has a \u000c form feed character." 21 | }, 22 | "newline": { 23 | "type": "string", 24 | "value": "This string has a \n new line character." 25 | }, 26 | "notunicode1": { 27 | "type": "string", 28 | "value": "This string does not have a unicode \\u escape." 29 | }, 30 | "notunicode2": { 31 | "type": "string", 32 | "value": "This string does not have a unicode \\u escape." 33 | }, 34 | "notunicode3": { 35 | "type": "string", 36 | "value": "This string does not have a unicode \\u0075 escape." 37 | }, 38 | "notunicode4": { 39 | "type": "string", 40 | "value": "This string does not have a unicode \\u escape." 41 | }, 42 | "quote": { 43 | "type": "string", 44 | "value": "This string has a \" quote character." 45 | }, 46 | "tab": { 47 | "type": "string", 48 | "value": "This string has a \t tab character." 49 | }, 50 | "unitseparator": { 51 | "type": "string", 52 | "value": "This string has a \u001f unit separator control code." 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/valid/string/escapes.toml: -------------------------------------------------------------------------------- 1 | backspace = "This string has a \b backspace character." 2 | tab = "This string has a \t tab character." 3 | newline = "This string has a \n new line character." 4 | formfeed = "This string has a \f form feed character." 5 | carriage = "This string has a \r carriage return character." 6 | quote = "This string has a \" quote character." 7 | backslash = "This string has a \\ backslash character." 8 | notunicode1 = "This string does not have a unicode \\u escape." 9 | notunicode2 = "This string does not have a unicode \u005Cu escape." 10 | notunicode3 = "This string does not have a unicode \\u0075 escape." 11 | notunicode4 = "This string does not have a unicode \\\u0075 escape." 12 | delete = "This string has a \u007F delete control code." 13 | unitseparator = "This string has a \u001F unit separator control code." 14 | -------------------------------------------------------------------------------- /tests/valid/string/multiline-escaped-crlf.json: -------------------------------------------------------------------------------- 1 | { 2 | "0": { 3 | "type": "string", 4 | "value": "" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/multiline-escaped-crlf.toml: -------------------------------------------------------------------------------- 1 | # The following line should be an unescaped backslash followed by a Windows 2 | # newline sequence ("\r\n") 3 | 0="""\ 4 | """ 5 | -------------------------------------------------------------------------------- /tests/valid/string/multiline-quotes.json: -------------------------------------------------------------------------------- 1 | { 2 | "escaped": { 3 | "type": "string", 4 | "value": "lol\"\"\"" 5 | }, 6 | "lit_one": { 7 | "type": "string", 8 | "value": "'one quote'" 9 | }, 10 | "lit_one_space": { 11 | "type": "string", 12 | "value": " 'one quote' " 13 | }, 14 | "lit_two": { 15 | "type": "string", 16 | "value": "''two quotes''" 17 | }, 18 | "lit_two_space": { 19 | "type": "string", 20 | "value": " ''two quotes'' " 21 | }, 22 | "mismatch1": { 23 | "type": "string", 24 | "value": "aaa'''bbb" 25 | }, 26 | "mismatch2": { 27 | "type": "string", 28 | "value": "aaa\"\"\"bbb" 29 | }, 30 | "one": { 31 | "type": "string", 32 | "value": "\"one quote\"" 33 | }, 34 | "one_space": { 35 | "type": "string", 36 | "value": " \"one quote\" " 37 | }, 38 | "two": { 39 | "type": "string", 40 | "value": "\"\"two quotes\"\"" 41 | }, 42 | "two_space": { 43 | "type": "string", 44 | "value": " \"\"two quotes\"\" " 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/valid/string/multiline-quotes.toml: -------------------------------------------------------------------------------- 1 | # Make sure that quotes inside multiline strings are allowed, including right 2 | # after the opening '''/""" and before the closing '''/""" 3 | 4 | lit_one = ''''one quote'''' 5 | lit_two = '''''two quotes''''' 6 | lit_one_space = ''' 'one quote' ''' 7 | lit_two_space = ''' ''two quotes'' ''' 8 | 9 | one = """"one quote"""" 10 | two = """""two quotes""""" 11 | one_space = """ "one quote" """ 12 | two_space = """ ""two quotes"" """ 13 | 14 | mismatch1 = """aaa'''bbb""" 15 | mismatch2 = '''aaa"""bbb''' 16 | 17 | # Three opening """, then one escaped ", then two "" (allowed), and then three 18 | # closing """ 19 | escaped = """lol\"""""" 20 | -------------------------------------------------------------------------------- /tests/valid/string/multiline.json: -------------------------------------------------------------------------------- 1 | { 2 | "equivalent_one": { 3 | "type": "string", 4 | "value": "The quick brown fox jumps over the lazy dog." 5 | }, 6 | "equivalent_three": { 7 | "type": "string", 8 | "value": "The quick brown fox jumps over the lazy dog." 9 | }, 10 | "equivalent_two": { 11 | "type": "string", 12 | "value": "The quick brown fox jumps over the lazy dog." 13 | }, 14 | "escape-bs-1": { 15 | "type": "string", 16 | "value": "a \\\nb" 17 | }, 18 | "escape-bs-2": { 19 | "type": "string", 20 | "value": "a \\b" 21 | }, 22 | "escape-bs-3": { 23 | "type": "string", 24 | "value": "a \\\\\n b" 25 | }, 26 | "keep-ws-before": { 27 | "type": "string", 28 | "value": "a \tb" 29 | }, 30 | "multiline_empty_four": { 31 | "type": "string", 32 | "value": "" 33 | }, 34 | "multiline_empty_one": { 35 | "type": "string", 36 | "value": "" 37 | }, 38 | "multiline_empty_three": { 39 | "type": "string", 40 | "value": "" 41 | }, 42 | "multiline_empty_two": { 43 | "type": "string", 44 | "value": "" 45 | }, 46 | "no-space": { 47 | "type": "string", 48 | "value": "ab" 49 | }, 50 | "whitespace-after-bs": { 51 | "type": "string", 52 | "value": "The quick brown fox jumps over the lazy dog." 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/valid/string/multiline.toml: -------------------------------------------------------------------------------- 1 | # NOTE: this file includes some literal tab characters. 2 | 3 | multiline_empty_one = """""" 4 | 5 | # A newline immediately following the opening delimiter will be trimmed. 6 | multiline_empty_two = """ 7 | """ 8 | 9 | # \ at the end of line trims newlines as well; note that last \ is followed by 10 | # two spaces, which are ignored. 11 | multiline_empty_three = """\ 12 | """ 13 | multiline_empty_four = """\ 14 | \ 15 | \ 16 | """ 17 | 18 | equivalent_one = "The quick brown fox jumps over the lazy dog." 19 | equivalent_two = """ 20 | The quick brown \ 21 | 22 | 23 | fox jumps over \ 24 | the lazy dog.""" 25 | 26 | equivalent_three = """\ 27 | The quick brown \ 28 | fox jumps over \ 29 | the lazy dog.\ 30 | """ 31 | 32 | whitespace-after-bs = """\ 33 | The quick brown \ 34 | fox jumps over \ 35 | the lazy dog.\ 36 | """ 37 | 38 | no-space = """a\ 39 | b""" 40 | 41 | # Has tab character. 42 | keep-ws-before = """a \ 43 | b""" 44 | 45 | escape-bs-1 = """a \\ 46 | b""" 47 | 48 | escape-bs-2 = """a \\\ 49 | b""" 50 | 51 | escape-bs-3 = """a \\\\ 52 | b""" 53 | -------------------------------------------------------------------------------- /tests/valid/string/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "lit_nl_end": { 3 | "type": "string", 4 | "value": "value\\n" 5 | }, 6 | "lit_nl_mid": { 7 | "type": "string", 8 | "value": "val\\nue" 9 | }, 10 | "lit_nl_uni": { 11 | "type": "string", 12 | "value": "val\\ue" 13 | }, 14 | "nl_end": { 15 | "type": "string", 16 | "value": "value\n" 17 | }, 18 | "nl_mid": { 19 | "type": "string", 20 | "value": "val\nue" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/valid/string/nl.toml: -------------------------------------------------------------------------------- 1 | nl_mid = "val\nue" 2 | nl_end = """value\n""" 3 | 4 | lit_nl_end = '''value\n''' 5 | lit_nl_mid = 'val\nue' 6 | lit_nl_uni = 'val\ue' 7 | -------------------------------------------------------------------------------- /tests/valid/string/raw-multiline.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstnl": { 3 | "type": "string", 4 | "value": "This string has a ' quote character." 5 | }, 6 | "multiline": { 7 | "type": "string", 8 | "value": "This string\nhas ' a quote character\nand more than\none newline\nin it." 9 | }, 10 | "oneline": { 11 | "type": "string", 12 | "value": "This string has a ' quote character." 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/valid/string/raw-multiline.toml: -------------------------------------------------------------------------------- 1 | # Single ' should be allowed. 2 | oneline = '''This string has a ' quote character.''' 3 | 4 | # A newline immediately following the opening delimiter will be trimmed. 5 | firstnl = ''' 6 | This string has a ' quote character.''' 7 | 8 | # All other whitespace and newline characters remain intact. 9 | multiline = ''' 10 | This string 11 | has ' a quote character 12 | and more than 13 | one newline 14 | in it.''' 15 | -------------------------------------------------------------------------------- /tests/valid/string/raw.json: -------------------------------------------------------------------------------- 1 | { 2 | "backslash": { 3 | "type": "string", 4 | "value": "This string has a \\\\ backslash character." 5 | }, 6 | "backspace": { 7 | "type": "string", 8 | "value": "This string has a \\b backspace character." 9 | }, 10 | "carriage": { 11 | "type": "string", 12 | "value": "This string has a \\r carriage return character." 13 | }, 14 | "formfeed": { 15 | "type": "string", 16 | "value": "This string has a \\f form feed character." 17 | }, 18 | "newline": { 19 | "type": "string", 20 | "value": "This string has a \\n new line character." 21 | }, 22 | "slash": { 23 | "type": "string", 24 | "value": "This string has a \\/ slash character." 25 | }, 26 | "tab": { 27 | "type": "string", 28 | "value": "This string has a \\t tab character." 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/valid/string/raw.toml: -------------------------------------------------------------------------------- 1 | backspace = 'This string has a \b backspace character.' 2 | tab = 'This string has a \t tab character.' 3 | newline = 'This string has a \n new line character.' 4 | formfeed = 'This string has a \f form feed character.' 5 | carriage = 'This string has a \r carriage return character.' 6 | slash = 'This string has a \/ slash character.' 7 | backslash = 'This string has a \\ backslash character.' 8 | -------------------------------------------------------------------------------- /tests/valid/string/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "string", 4 | "value": "You are not drinking enough whisky." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/simple.toml: -------------------------------------------------------------------------------- 1 | answer = "You are not drinking enough whisky." 2 | -------------------------------------------------------------------------------- /tests/valid/string/unicode-escape.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer4": { 3 | "type": "string", 4 | "value": "δ" 5 | }, 6 | "answer8": { 7 | "type": "string", 8 | "value": "δ" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/string/unicode-escape.toml: -------------------------------------------------------------------------------- 1 | answer4 = "\u03B4" 2 | answer8 = "\U000003B4" 3 | -------------------------------------------------------------------------------- /tests/valid/string/unicode-literal.json: -------------------------------------------------------------------------------- 1 | { 2 | "answer": { 3 | "type": "string", 4 | "value": "δ" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/string/unicode-literal.toml: -------------------------------------------------------------------------------- 1 | answer = "δ" 2 | -------------------------------------------------------------------------------- /tests/valid/string/with-pound.json: -------------------------------------------------------------------------------- 1 | { 2 | "pound": { 3 | "type": "string", 4 | "value": "We see no # comments here." 5 | }, 6 | "poundcomment": { 7 | "type": "string", 8 | "value": "But there are # some comments here." 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/valid/string/with-pound.toml: -------------------------------------------------------------------------------- 1 | pound = "We see no # comments here." 2 | poundcomment = "But there are # some comments here." # Did I # mess you up? 3 | -------------------------------------------------------------------------------- /tests/valid/table/array-implicit.json: -------------------------------------------------------------------------------- 1 | { 2 | "albums": { 3 | "songs": [ 4 | { 5 | "name": { 6 | "type": "string", 7 | "value": "Glory Days" 8 | } 9 | } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/table/array-implicit.toml: -------------------------------------------------------------------------------- 1 | [[albums.songs]] 2 | name = "Glory Days" 3 | -------------------------------------------------------------------------------- /tests/valid/table/array-many.json: -------------------------------------------------------------------------------- 1 | { 2 | "people": [ 3 | { 4 | "first_name": { 5 | "type": "string", 6 | "value": "Bruce" 7 | }, 8 | "last_name": { 9 | "type": "string", 10 | "value": "Springsteen" 11 | } 12 | }, 13 | { 14 | "first_name": { 15 | "type": "string", 16 | "value": "Eric" 17 | }, 18 | "last_name": { 19 | "type": "string", 20 | "value": "Clapton" 21 | } 22 | }, 23 | { 24 | "first_name": { 25 | "type": "string", 26 | "value": "Bob" 27 | }, 28 | "last_name": { 29 | "type": "string", 30 | "value": "Seger" 31 | } 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /tests/valid/table/array-many.toml: -------------------------------------------------------------------------------- 1 | [[people]] 2 | first_name = "Bruce" 3 | last_name = "Springsteen" 4 | 5 | [[people]] 6 | first_name = "Eric" 7 | last_name = "Clapton" 8 | 9 | [[people]] 10 | first_name = "Bob" 11 | last_name = "Seger" 12 | -------------------------------------------------------------------------------- /tests/valid/table/array-nest.json: -------------------------------------------------------------------------------- 1 | { 2 | "albums": [ 3 | { 4 | "name": { 5 | "type": "string", 6 | "value": "Born to Run" 7 | }, 8 | "songs": [ 9 | { 10 | "name": { 11 | "type": "string", 12 | "value": "Jungleland" 13 | } 14 | }, 15 | { 16 | "name": { 17 | "type": "string", 18 | "value": "Meeting Across the River" 19 | } 20 | } 21 | ] 22 | }, 23 | { 24 | "name": { 25 | "type": "string", 26 | "value": "Born in the USA" 27 | }, 28 | "songs": [ 29 | { 30 | "name": { 31 | "type": "string", 32 | "value": "Glory Days" 33 | } 34 | }, 35 | { 36 | "name": { 37 | "type": "string", 38 | "value": "Dancing in the Dark" 39 | } 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /tests/valid/table/array-nest.toml: -------------------------------------------------------------------------------- 1 | [[albums]] 2 | name = "Born to Run" 3 | 4 | [[albums.songs]] 5 | name = "Jungleland" 6 | 7 | [[albums.songs]] 8 | name = "Meeting Across the River" 9 | 10 | [[albums]] 11 | name = "Born in the USA" 12 | 13 | [[albums.songs]] 14 | name = "Glory Days" 15 | 16 | [[albums.songs]] 17 | name = "Dancing in the Dark" 18 | -------------------------------------------------------------------------------- /tests/valid/table/array-one.json: -------------------------------------------------------------------------------- 1 | { 2 | "people": [ 3 | { 4 | "first_name": { 5 | "type": "string", 6 | "value": "Bruce" 7 | }, 8 | "last_name": { 9 | "type": "string", 10 | "value": "Springsteen" 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tests/valid/table/array-one.toml: -------------------------------------------------------------------------------- 1 | [[people]] 2 | first_name = "Bruce" 3 | last_name = "Springsteen" 4 | -------------------------------------------------------------------------------- /tests/valid/table/array-table-array.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": [ 3 | { 4 | "b": [ 5 | { 6 | "c": { 7 | "d": { 8 | "type": "string", 9 | "value": "val0" 10 | } 11 | } 12 | }, 13 | { 14 | "c": { 15 | "d": { 16 | "type": "string", 17 | "value": "val1" 18 | } 19 | } 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tests/valid/table/array-table-array.toml: -------------------------------------------------------------------------------- 1 | [[a]] 2 | [[a.b]] 3 | [a.b.c] 4 | d = "val0" 5 | [[a.b]] 6 | [a.b.c] 7 | d = "val1" 8 | -------------------------------------------------------------------------------- /tests/valid/table/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": {} 3 | } 4 | -------------------------------------------------------------------------------- /tests/valid/table/empty.toml: -------------------------------------------------------------------------------- 1 | [a] 2 | -------------------------------------------------------------------------------- /tests/valid/table/keyword.json: -------------------------------------------------------------------------------- 1 | { 2 | "true": {}, 3 | "false": {}, 4 | "inf": {}, 5 | "nan": {} 6 | } 7 | -------------------------------------------------------------------------------- /tests/valid/table/keyword.toml: -------------------------------------------------------------------------------- 1 | [true] 2 | 3 | [false] 4 | 5 | [inf] 6 | 7 | [nan] 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/valid/table/names.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | " x ": {}, 4 | "b": { 5 | "c": {} 6 | }, 7 | "b.c": {}, 8 | "d.e": {} 9 | }, 10 | "d": { 11 | "e": { 12 | "f": {} 13 | } 14 | }, 15 | "g": { 16 | "h": { 17 | "i": {} 18 | } 19 | }, 20 | "j": { 21 | "ʞ": { 22 | "l": {} 23 | } 24 | }, 25 | "x": { 26 | "1": { 27 | "2": {} 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/valid/table/names.toml: -------------------------------------------------------------------------------- 1 | [a.b.c] 2 | [a."b.c"] 3 | [a.'d.e'] 4 | [a.' x '] 5 | [ d.e.f ] 6 | [ g . h . i ] 7 | [ j . "ʞ" . 'l' ] 8 | 9 | [x.1.2] 10 | -------------------------------------------------------------------------------- /tests/valid/table/no-eol.json: -------------------------------------------------------------------------------- 1 | { 2 | "table": {} 3 | } 4 | -------------------------------------------------------------------------------- /tests/valid/table/no-eol.toml: -------------------------------------------------------------------------------- 1 | [table] 2 | -------------------------------------------------------------------------------- /tests/valid/table/sub-empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "b": {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/valid/table/sub-empty.toml: -------------------------------------------------------------------------------- 1 | [a] 2 | [a.b] 3 | -------------------------------------------------------------------------------- /tests/valid/table/whitespace.json: -------------------------------------------------------------------------------- 1 | { 2 | "valid key": {} 3 | } 4 | -------------------------------------------------------------------------------- /tests/valid/table/whitespace.toml: -------------------------------------------------------------------------------- 1 | ["valid key"] 2 | -------------------------------------------------------------------------------- /tests/valid/table/with-literal-string.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "\"b\"": { 4 | "c": { 5 | "answer": { 6 | "type": "integer", 7 | "value": "42" 8 | } 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/table/with-literal-string.toml: -------------------------------------------------------------------------------- 1 | ['a'] 2 | [a.'"b"'] 3 | [a.'"b"'.c] 4 | answer = 42 5 | -------------------------------------------------------------------------------- /tests/valid/table/with-pound.json: -------------------------------------------------------------------------------- 1 | { 2 | "key#group": { 3 | "answer": { 4 | "type": "integer", 5 | "value": "42" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/valid/table/with-pound.toml: -------------------------------------------------------------------------------- 1 | ["key#group"] 2 | answer = 42 3 | -------------------------------------------------------------------------------- /tests/valid/table/with-single-quotes.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "b": { 4 | "c": { 5 | "answer": { 6 | "type": "integer", 7 | "value": "42" 8 | } 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/valid/table/with-single-quotes.toml: -------------------------------------------------------------------------------- 1 | ['a'] 2 | [a.'b'] 3 | [a.'b'.c] 4 | answer = 42 5 | -------------------------------------------------------------------------------- /tests/valid/table/without-super.json: -------------------------------------------------------------------------------- 1 | { 2 | "x": { 3 | "y": { 4 | "z": { 5 | "w": {} 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/valid/table/without-super.toml: -------------------------------------------------------------------------------- 1 | # [x] you 2 | # [x.y] don't 3 | # [x.y.z] need these 4 | [x.y.z.w] # for this to work 5 | [x] # defining a super-table afterwards is ok 6 | -------------------------------------------------------------------------------- /toml.dict: -------------------------------------------------------------------------------- 1 | key_value="a.b=\"c\"" 2 | unicode="\\u1234" 3 | unicode_long="\\u12345678" 4 | true="true" 5 | false="false" 6 | multiline_literal="'''" 7 | multiline="\"\"\"" 8 | integer="+1_2_3_4" 9 | negative_integer="-1" 10 | hex="0xde_ad" 11 | oct="0o6" 12 | bin="0b1" 13 | float="-6_3.6e-05" 14 | nan="nan" 15 | inf="inf" 16 | time="1979-05-27T07:32:00Z" 17 | array="[1,2]" 18 | table="[a]" 19 | inline_table="a={1=2,3=4}" 20 | array_table="[[a]]" 21 | -------------------------------------------------------------------------------- /zigmod.yml: -------------------------------------------------------------------------------- 1 | id: qbh3mfo5ck9p835t13fbskhxo2izt9saho18u4lx0dczafln 2 | name: tomlz 3 | main: src/main.zig 4 | license: MIT 5 | description: A toml parser for Zig 6 | dependencies: 7 | --------------------------------------------------------------------------------