//! A forest of B+-trees.1//!2//! This crate provides a data structures representing a set of small ordered sets or maps.3//! It is implemented as a forest of B+-trees all allocating nodes out of the same pool.4//!5//! **These are not general purpose data structures that are somehow magically faster that the6//! standard library's `BTreeSet` and `BTreeMap` types.**7//!8//! The tradeoffs are different:9//!10//! - Keys and values are expected to be small and copyable. We optimize for 32-bit types.11//! - A comparator object is used to compare keys, allowing smaller "context free" keys.12//! - Empty trees have a very small 32-bit footprint.13//! - All the trees in a forest can be cleared in constant time.1415#![deny(missing_docs)]16#![no_std]1718#[cfg(test)]19extern crate alloc;2021#[macro_use]22extern crate cranelift_entity as entity;23use crate::entity::packed_option;2425use core::borrow::BorrowMut;26use core::cmp::Ordering;2728mod map;29mod node;30mod path;31mod pool;32mod set;3334pub use self::map::{Map, MapCursor, MapForest, MapIter};35pub use self::set::{Set, SetCursor, SetForest, SetIter};3637use self::node::NodeData;38use self::path::Path;39use self::pool::NodePool;4041/// The maximum branching factor of an inner node in a B+-tree.42/// The minimum number of outgoing edges is `INNER_SIZE/2`.43const INNER_SIZE: usize = 8;4445/// Given the worst case branching factor of `INNER_SIZE/2` = 4, this is the46/// worst case path length from the root node to a leaf node in a tree with 2^3247/// entries. We would run out of node references before we hit `MAX_PATH`.48const MAX_PATH: usize = 16;4950/// Key comparator.51///52/// Keys don't need to implement `Ord`. They are compared using a comparator object which53/// provides a context for comparison.54pub trait Comparator<K>55where56K: Copy,57{58/// Compare keys `a` and `b`.59///60/// This relation must provide a total ordering or the key space.61fn cmp(&self, a: K, b: K) -> Ordering;6263/// Binary search for `k` in an ordered slice.64///65/// Assume that `s` is already sorted according to this ordering, search for the key `k`.66///67/// Returns `Ok(idx)` if `k` was found in the slice or `Err(idx)` with the position where it68/// should be inserted to preserve the ordering.69fn search(&self, k: K, s: &[K]) -> Result<usize, usize> {70s.binary_search_by(|x| self.cmp(*x, k))71}72}7374/// Trivial comparator that doesn't actually provide any context.75impl<K> Comparator<K> for ()76where77K: Copy + Ord,78{79fn cmp(&self, a: K, b: K) -> Ordering {80a.cmp(&b)81}82}8384/// Family of types shared by the map and set forest implementations.85trait Forest {86/// The key type is present for both sets and maps.87type Key: Copy;8889/// The value type is `()` for sets.90type Value: Copy;9192/// An array of keys for the leaf nodes.93type LeafKeys: Copy + BorrowMut<[Self::Key]>;9495/// An array of values for the leaf nodes.96type LeafValues: Copy + BorrowMut<[Self::Value]>;9798/// Splat a single key into a whole array.99fn splat_key(key: Self::Key) -> Self::LeafKeys;100101/// Splat a single value inst a whole array102fn splat_value(value: Self::Value) -> Self::LeafValues;103}104105/// A reference to a B+-tree node.106#[derive(Clone, Copy, PartialEq, Eq)]107struct Node(u32);108entity_impl!(Node, "node");109110/// Empty type to be used as the "value" in B-trees representing sets.111#[derive(Clone, Copy)]112struct SetValue();113114/// Insert `x` into `s` at position `i`, pushing out the last element.115fn slice_insert<T: Copy>(s: &mut [T], i: usize, x: T) {116for j in (i + 1..s.len()).rev() {117s[j] = s[j - 1];118}119s[i] = x;120}121122/// Shift elements in `s` to the left by `n` positions.123fn slice_shift<T: Copy>(s: &mut [T], n: usize) {124for j in 0..s.len() - n {125s[j] = s[j + n];126}127}128129#[cfg(test)]130mod tests {131use super::*;132use crate::entity::EntityRef;133134/// An opaque reference to a basic block in a function.135#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]136pub struct Block(u32);137entity_impl!(Block, "block");138139#[test]140fn comparator() {141let block1 = Block::new(1);142let block2 = Block::new(2);143let block3 = Block::new(3);144let block4 = Block::new(4);145let vals = [block1, block2, block4];146let comp = ();147assert_eq!(comp.search(block1, &vals), Ok(0));148assert_eq!(comp.search(block3, &vals), Err(2));149assert_eq!(comp.search(block4, &vals), Ok(2));150}151152#[test]153fn slice_insertion() {154let mut a = ['a', 'b', 'c', 'd'];155156slice_insert(&mut a[0..1], 0, 'e');157assert_eq!(a, ['e', 'b', 'c', 'd']);158159slice_insert(&mut a, 0, 'a');160assert_eq!(a, ['a', 'e', 'b', 'c']);161162slice_insert(&mut a, 3, 'g');163assert_eq!(a, ['a', 'e', 'b', 'g']);164165slice_insert(&mut a, 1, 'h');166assert_eq!(a, ['a', 'h', 'e', 'b']);167}168169#[test]170fn slice_shifting() {171let mut a = ['a', 'b', 'c', 'd'];172173slice_shift(&mut a[0..1], 1);174assert_eq!(a, ['a', 'b', 'c', 'd']);175176slice_shift(&mut a[1..], 1);177assert_eq!(a, ['a', 'c', 'd', 'd']);178179slice_shift(&mut a, 2);180assert_eq!(a, ['d', 'd', 'd', 'd']);181}182}183184185