Expand description
Fixed-size sliding ring buffer with anchor-preserving index math.
SlidingRing keeps a circular array of 256 slots whose indices are addressed
relative to an anchor coordinate (for example, the current best price in an
orderbook). When the anchor moves forward or backward, the ring clears the
newly entered slots and advances a pointer so that lookups by absolute
coordinate stay O(1).
§Model overview
anchorrepresents the absolute coordinate associated with the pointer slot.- Moving the anchor by
krewires slots branchlessly and clears thekslots that freshly enter the window (or the entire ring if|k| >= 256). - Reads/writes go through
SlidingRing::slot/SlidingRing::slot_mut, which translate absolute coordinates into ring indices via modulo arithmetic. SlidingRing::shift_to_keep_new_baseexists for workflows that promote the next best coordinate without clearing the new base slot (e.g., orderbooks).
§When to use it
Use this crate any time you need a cache-friendly sliding window tied to a monotonically moving reference point and you can tolerate a fixed resolution of 256 discrete offsets. Typical use-cases include:
- Aggregated orderbooks keyed by price ticks.
- Sliding time buckets for telemetry or rate-limiters.
- Game state timelines (e.g., ringed entity positions) where only a bounded horizon surrounding the current tick matters.
§When not to use it
- You need more than 256 distinct offsets at a time.
- The anchor jumps arbitrarily with sparse occupancy (use a hashmap instead).
- Slots require heap allocations on clear (prefer a structure that owns the heap nodes elsewhere and references them by ID).
§Slot flexibility
The buffer is generic over the stored slot type via Slot. Implement the
trait on your own type to hook into the ring’s lifecycle, or use one of the
bundled implementations (numeric primitives, Option<T>, or Cell<T>).
For ultra-low latency users, the main primitive is
SlidingRing::slices_from_anchor, which returns the two contiguous spans
that cover the ring starting at the anchor. Operate on those slices directly
with SIMD or unrolled loops when you need raw throughput. The iterator
variants (iter*) simply layer absolute coordinate reporting on top of the
same pointer arithmetic and remain zero-cost.
Pair those slices with a stable SIMD helper (e.g., the wide
crate demonstrated in examples/simd_scan.rs) to keep portable performance on stable Rust.
§Example
use sliding_ring::{SlidingRing, Slot};
#[derive(Debug, Default)]
struct Level { qty: u64 }
impl Slot for Level {
fn init() -> Self {
Self { qty: 0 }
}
fn clear(&mut self) {
self.qty = 0;
}
}
let mut ring = SlidingRing::<Level>::new(1_000);
ring.slot_mut(1_005).qty = 10;
ring.shift_to(1_005);
assert_eq!(ring.slot_at_pointer().qty, 10);§Telemetry counter example
#[derive(Clone, Copy, Default)]
struct Bucket { hits: u64 }
let mut ring = SlidingRing::<Bucket>::new(0);
ring.slot_mut(5).hits += 1;
ring.slot_mut(6).hits += 3;
let sum: u64 = ring
.iter_from_anchor(Direction::Forward)
.map(|(_, bucket)| bucket.hits)
.sum();
assert_eq!(sum, 4);Structs§
- Anchor
Iter - Anchor-ordered iterator (immutable).
- Anchor
Iter Mut - Anchor-ordered iterator (mutable).
- Sliding
Ring - Ring that slides over signed coordinates while keeping slot access O(1).
- Slots
- Raw-pointer iterator over an immutable ring slice.
- Slots
Mut - Raw-pointer iterator over a mutable ring slice.
Enums§
- Direction
- Iteration order relative to the anchor.
Constants§
- RING_
SIZE - Number of slots in the ring.
Traits§
- Slot
- Trait that describes how to create and reset an element stored in the ring.
Functions§
- advance_
and_ clear - advance_
and_ clear_ keep_ new_ base - diff_
mod_ 256 - Reduce a signed difference mod 256 (ring size).