scapegoat


scapegoat

crates.io MSRV 1.55+ docs.rs GitHub Actions License: MIT Unsafe-Zero-Percent

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

About

Two APIs:

Strives for three properties:

Other features:

Usage

SgMap non-exhaustive, !#[no_std] API example (would work almost identically for std::collections::BTreeMap):

```rust use scapegoat::SgMap; use tinyvec::{array_vec, ArrayVec};

// This const is an argument to each generic constructor below. // So we'll use only the bare minimum memory for 5 elements. // - Stack RAM usage can be precisely controlled: per map instance (constructor call-site). // - To save executable RAM/ROM (monomorphization!), stick to a global capacity like this. const CAPACITY: usize = 5;

let mut example = SgMap::<_, _, CAPACITY>::new(); // BTreeMap::new() let mut stack_str = "your friend the";

// Insert "dynamically" (as if heap) example.insert(3, "the"); example.insert(2, "don't blame"); example.insert(1, "Please");

// Fallible insert variant assert!(example.tryinsert(4, "borrow checker").isok());

// Ordered reference iterator assert!(example .iter() .map(|(_, v)| *v) .collect::

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

// Head removal let pleasetuple = example.popfirst().unwrap(); asserteq!(pleasetuple, (1, "Please"));

// By-predicate removal example.retain(|_, v| !v.contains("a"));

// Extension let iterable = arrayvec![ [(isize, &str); CAPACITY] => (1337, "safety!"), (0, "Leverage"), (100, "for") ]; example.extend(iterable.intoiter());

// Value mutation if let Some(threeval) = example.getmut(&3) { *threeval = &mut stackstr; }

// New message :) assert!(example .into_values() .collect::

Additional examples here.

Stack Capacity: Important Context

Per the above, const generic type parameters decide collection capacity. And thus also stack usage. That usage is fixed:

```rust use core::mem::sizeofval; use scapegoat::SgMap;

let smallmap: SgMap = SgMap::new(); // 100 item capacity let bigmap: SgMap = SgMap::new(); // 2,048 item capacity

[cfg(targetpointerwidth = "64")]

[cfg(not(feature = "lowmeminsert"))]

[cfg(not(feature = "fast_rebalance"))]

{ asserteq!(sizeofval(&smallmap), 2680); // 2.7 KB asserteq!(sizeofval(&bigmap), 53328); // 53.3 KB } ```

The maximum supported capacity is 65_535 (e.g. 0xffff or u16::MAX) items. Please note:

WARNING: Although stack usage is constant (no recursion), a stack overflow can happen at runtime if N (const generic capacity) and/or the stored item type (generic) is too large. Note stack overflow is distinct from buffer overflow (which safe Rust prevents). Regardless, you must test to ensure you don't exceed the stack size limit of your target platform. Rust only supports stack probes on x86/x64, although creative linking solutions have been suggested for other architectures.

For advanced configuration options, please see the documentation here.

Trusted Dependencies

This library has three dependencies, each of which have no dependencies of their own (e.g. exactly three total dependencies).

Because this library and all dependencies are #![forbid(unsafe_code)], no 3rd-party unsafe code is introduced into your project.

Additional Considerations

General Goals

This project is an exercise in safe, portable data structure design. The goal is to offer embedded developers familiar, ergonomic APIs on resource constrained systems that otherwise don't get the luxury of dynamic collections. Without sacrificing safety.

scapegoat is not as fast or mature as the standard library's BTreeMap/BTreeSet (benchmarks via cargo bench). The standard library has been heavily optimized for cache performance. This library is optimized for low, stack-only memory footprint. It offers:

Algorithmic Complexity

Space complexity is always O(n). Time complexity:

| Operation | Average Case | Worst Case | | --- | --- | --- | | get | O(log n) | O(log n) | | insert | O(log n) | Amortized O(log n) | | remove | O(log n) | Amortized O(log n) | | first | O(1) | O(1) | | last | O(1) | O(1) |

Memory Footprint Demos

License and Contributing

Licensed under the MIT license. Contributions are welcome!