Skip to content

About

Pure-Rust KSON parser; incremental, no-std, low-allocation custom allocators.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

kson-parser

A Rust KSON parser.

  • Incremental: its Parser operates 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 the nightly or allocator-api2 feature).

  • 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:

    1. In src/alloc.rs, to construct a Box<str, A>, which is required as Box::from(&str) does not have an allocator-aware equivalent.

    2. In src/lexer.rs, to interpret &[u8] as &str, which is required as String does not have an allocator-aware equivalent.

    3. In src/event.rs, to extend a lifetime (only on stable, nightly accepts the code).

Usage

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.

Event-based

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,
]);

Value-based

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))]));

Features

  • allocator-api2: use allocator-api2 to support custom allocators.

  • nightly: assumes that allocator_api is stable to support custom allocators. Takes precedence over allocator-api2.

Comparison with kson-rs

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.

Development

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.

Disclaimer

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.

About

Pure-Rust KSON parser; incremental, no-std, low-allocation custom allocators.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages