scapegoat

crates.io GitHub Actions

Ordered set and map data structures via an arena-based scapegoat tree (memory-efficient, self-balancing binary search tree).

This library is #![no_std] compatible by default, strictly #![forbid(unsafe_code)], and verified using differential fuzzing.

About

Three APIs:

Strives for two properties:

Other features:

Usage

SGMap non-exhaustive API example (would work identically for std::collections::BTreeMap):

```rust use scapegoat::SGMap;

let mut example = SGMap::new();

example.insert(3, String::from("the")); example.insert(2, String::from("don't blame")); example.insert(1, String::from("Please")); example.insert(4, String::from("borrow checker"));

asserteq!( example.iter().map(|(, v)| v).collect::>(), vec!["Please","don't blame","the","borrow checker"] );

assert_eq!(example[&3], "the");

let pleasetuple = example.popfirst().unwrap(); asserteq!(pleasetuple, (1, String::from("Please")));

example.insert(5, String::from("! :P"));

let dontblame = example.getmut(&2).unwrap(); dontblame.remove(0); dontblame.insert(0, 'D');

asserteq!( example.intoiter().map(|(_, v)| v).collect::>(), vec!["Don't blame","the","borrow checker","! :P"] ); ```

Configuring a Stack Storage Limit

The maximum number of stack-stored elements (set) or key-value pairs (map/tree) is determined at compile-time, via the environment variable SG_MAX_STACK_ELEMS. Valid values are in the range [0, 32] and powers of 2 up to 1,048,576. For example, to store up to 2048 items on the stack:

bash export SG_MAX_STACK_ELEMS=2048 cargo build --release

Please note:

Trusted Dependencies

This library has two dependencies, each of which have no dependencies of their own (e.g. exactly two total dependencies). Both dependencies were carefully chosen.

Considerations

This project is an exercise in safe data structure design. It's not as mature, fast, or memory efficient as the standard library's BTreeMap/BTreeSet. It does, however, offer: * Best-effort Compatibility: APIs are a subset of BTreeMap's/BTreeSet's, making it a somewhat "drop-in" replacement for !#[no_std] systems. Please open an issue if an API you need isn't yet supported! * Dynamic Verification: Coverage-guided differential fuzzing is used to verify that this implementation is logically equivalent and equally reliable.