Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mattyhall/tomlz
A well-tested TOML parsing library for Zig
https://github.com/mattyhall/tomlz
parsing toml zig
Last synced: 29 days ago
JSON representation
A well-tested TOML parsing library for Zig
- Host: GitHub
- URL: https://github.com/mattyhall/tomlz
- Owner: mattyhall
- License: mit
- Created: 2022-11-05T21:53:44.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-19T17:20:48.000Z (6 months ago)
- Last Synced: 2024-08-03T23:17:58.434Z (4 months ago)
- Topics: parsing, toml, zig
- Language: Zig
- Homepage:
- Size: 172 KB
- Stars: 21
- Watchers: 2
- Forks: 4
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-zig - mattyhall/tomlz - tested TOML parsing library for Zig. (File format processing / Utility)
README
# tomlz
A TOML parser for Zig targeting TOML v1.0.0, an easy API and safety.
Also supports encoding/serializing values(implemented by @0x5a4)!```zig
const std = @import("std")
const tomlz = @import("tomlz")var gpa = std.heap.page_allocator;
var table = try tomlz.parse(gpa,
\\foo = 1
\\bar = 2
);
defer table.deinit(gpa);table.getInteger("foo").?; // 1
// --- or ---
const S = struct { foo: i64, bar: i64 };
const s = try tomlz.decode(S, gpa,
\\foo = 1
\\bar = 2
);// serialize a value like this (also see the examples)
try tomlz.serialize(
gpa,
std.io.getStdout.writer()
s,
);
// foo = 1
// bar = 2
```## Current status
All types other than datetimes are supported. We pass 321/334 of the
[toml tests](https://github.com/BurntSushi/toml-test) 11 of those are due to not
having datetime support and the other two are minor lexing issues (allowing
whitespace between the square brackets of an array header).We allow both parsing into a special TOML type, a `Table`, but also support
decoding into a struct directly - including types that must be allocated like
arrays and strings.The Serializer allows encoding every kind of zig type, overwriting it's default behaviour
by implementing a function called `tomlzSerialize`, has the option to work
without an allocator and can therefore even work at `comptime`!
Note that for some types like `std.HashMap` its not possible to just encode
all their fields, so custom logic is needed. We can't provide this, but it's not
too difficult to implement it yourself(See examples).## Installation
tomlz supports being included as a module.
Create a file called `build.zig.zon` if you do not already have one, and add `tomlz` as a dependency
```
.{
.name = "myproject",
.version = "0.1.0",
.dependencies = .{
.tomlz = .{
.url = "https://github.com/mattyhall/tomlz/archive/.tar.gz",
.hash = "12206cf9e90462ee6e14f593ea6e0802b9fe434429ba10992a1451e32900f741005c",
},
}
}
```You'll have to replace the `` part with an actual, recent commit-hash.
The hash also needs changing, but `zig build` will complain and give you the correct one.In your `build.zig` file create and use the dependency
```
pub fn build(b: *std.Build) void {
// ... setup ...const tomlz = b.dependency("tomlz", .{
.target = target,
.optimize = optimize,
});// add the tomlz module
exe.root_module.addImport("tomlz", tomlz.module("tomlz"));// .. continue ...
}
```## Usage
### Table
We currently provide a single entry point for parsing which returns a toml
`Table` type. This type has helper methods for getting values out:```zig
const std = @import("std");
const tomlz = @import("tomlz");var gpa = std.heap.page_allocator;
var table = try tomlz.parse(gpa,
\\int = 1
\\float = 2.0
\\boolean = true
\\string = "hello, world"
\\array = [1, 2, 3]
\\table = { subvalue = 1, we.can.nest.keys = 2 }
);
defer table.deinit(gpa);table.getInteger("int");
table.getFloat("float");
table.getBool("boolean");
table.getString("string");
table.getArray("array");
table.getTable("table");
```A simple example is
[provided](https://github.com/mattyhall/tomlz/tree/main/examples/simple/).### Decode
```zig
const std = @import("std");
const tomlz = @import("tomlz");var gpa = std.heap.page_allocator;
const TripleCrowns = struct { worlds: i64, masters: i64, uks: i64 };const Player = struct {
name: []const u8,
age: i64,
hobbies: []const []const u8,
triplecrowns: TripleCrowns,const Self = @This();
pub fn deinit(self: *Self, gpa: std.mem.Allocator) void {
gpa.free(self.name);for (self.hobbies) |hobby| {
gpa.free(hobby);
}
gpa.free(self.hobbies);
}
};const Game = struct {
name: []const u8,
goat: Player,const Self = @This();
pub fn deinit(self: *Self, gpa: std.mem.Allocator) void {
gpa.free(self.name);
self.goat.deinit(gpa);
}
};var s = try tomlz.decode(Game, gpa,
\\name = "snooker"
\\
\\[goat]
\\name = "Ronnie o' Sullivan"
\\age = 46 # as of Nov 2022
\\hobbies = ["running", "hustling at pool"]
\\
\\[goat.triplecrowns]
\\worlds = 7
\\masters = 7
\\uks = 7
);
defer s.deinit(gpa);
```### Encode
Have a look at [the example](examples/serialize/src/main.zig).
## Goals and non-goals
Goals and non-goals are subject to change based on how the project is used and
my own time constraints. If you feel a goal or non-goal isn't quite right please
open an issue and we can discuss it.### Goals
- TOML v1.0.0. The datetime portion of this is probably going to be
unachievable until Zig gets a good standard library type for it or a library
gets dominance. Other than that however we should pass all the
[tests](https://github.com/BurntSushi/toml-test)
- A nice API. Getting values from the `Value` type should be painless as
possible and we should also provide deserialising a `Table` into a struct,
similarly to how `std.json` does it
- Easy installation. We should try to make using the library as a vendored
dependency and as a package - on e.g. [gyro](https://github.com/mattnite/gyro)
\- as easy as possible
- Safety. The parser should never crash no matter the input. To achieve this we
should run fuzzing against it
- Support Zig master and the latest tagged release until Zig v1.0. This will be
done by having the main branch track Zig master and a branch for each Zig
release. Any improvements should be backported to the most recent release
branch
- Good error messages### Non-goals
- Super duper performance. We want to be as performant as possible without
making the code harder to read. It is unlikely that parsing a TOML file is
going to be the bottleneck in your application so "good" performance should be
sufficient
- Previous versions of TOML