Crate sliding_ring

Crate sliding_ring 

Source
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

  • anchor represents the absolute coordinate associated with the pointer slot.
  • Moving the anchor by k rewires slots branchlessly and clears the k slots 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_base exists 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§

AnchorIter
Anchor-ordered iterator (immutable).
AnchorIterMut
Anchor-ordered iterator (mutable).
SlidingRing
Ring that slides over signed coordinates while keeping slot access O(1).
Slots
Raw-pointer iterator over an immutable ring slice.
SlotsMut
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).

Type Aliases§

RingIndex