A Rust KSON parser.
-
Incremental: its
Parseroperates on chunks of data using a state machine, so all sorts of inputs are supported: strings,Read,AsyncRead, vectored buffers, ... -
No backtracking, with one token of lookahead.
-
no-std, with support for custom allocators (using thenightlyorallocator-api2feature). -
Requires no allocation, except in the following cases:
-
When strings have escape sequences.
-
When embed blocks have escape sequences or a non-zero minimum indentation.
-
When individual values are split across chunks.
-
When a string is the last non-comment token in its chunk (as we must store it until we know if it is a string or a key).
-
-
No dependencies (except
allocator-api2, which is optional). -
Little unsafe code:
-
In
src/alloc.rs, to construct aBox<str, A>, which is required asBox::from(&str)does not have an allocator-aware equivalent. -
In
src/lexer.rs, to interpret&[u8]as&str, which is required asStringdoes not have an allocator-aware equivalent. -
In
src/event.rs, to extend a lifetime (only on stable, nightly accepts the code).
-
Both a low-level event-based API and a higher-level tree API are provided. The former is harder to use, but does not require any recursion, and reuses its internal buffer for all required allocations. The latter is easier to use, but must construct the whole tree in memory, which can be more expensive.
use kson_parser::{event::{parse, Event}, Str};
let events = parse("one: 1").collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(&events, &[
Event::StartObject,
Event::Key(Str::Input("one")),
Event::Int(1),
Event::End,
]);use kson_parser::{Str, Value};
#[cfg(all(feature = "allocator-api2", not(feature = "nightly")))]
use allocator_api2::vec;
let value = Value::parse("one: 1").unwrap();
assert_eq!(value, Value::Object(vec![(Str::Input("one"), Value::Int(1))]));-
allocator-api2: useallocator-api2to support custom allocators. -
nightly: assumes thatallocator_apiis stable to support custom allocators. Takes precedence overallocator-api2.
kson-rs is the official KSON crate, and
has far more features than this crate, such as misleading indentation warnings,
error recovery, formatting, higher-level APIs, and conversion to other formats.
However, it requires linking with the underlying KSON Kotlin library, which it
downloads dynamically in its build.rs file. Because it is implemented in
Kotlin, it does not expose non-copying or non-allocating APIs, and is fairly
heavy.
Warning
kson-sys is a development dependency, so running tests will fetch and run
the Kotlin library.
Use ./test.sh to run tests, do some fuzzing, check the code, etc.
I don't actually use this; I just thought KSON was a neat configuration language and noticed that it didn't have a native Rust parser, so I made this one.
I also wanted it to be sans-IO (driven by a state machine, supporting
streaming), #[no_std], and to use an optimal amount of memory. That is, this
will not allocate until absolutely necessary: strings are borrowed from the
input unless they need to be spilled to a buffer (if they have escapes or are
split across chunks), and buffers are stored inline, without allocation, for
small inputs and reasonably deep trees.