Shared low-level data structures for gossip-rs. This crate provides
allocation-silent containers and utilities for hot-path coordination
and scanning loops where heap allocation is the dominant cost. It exists
as a separate crate from gossip-contracts because several types here
require unsafe for MaybeUninit-based storage, and gossip-contracts
uses #![forbid(unsafe_code)].
| File | Public Type(s) | Purpose |
|---|---|---|
src/lib.rs |
(re-exports) | Module map, crate-level docs, compatibility mapping |
src/byte_slab.rs |
ByteSlab, ByteSlot, SlabFull, MIN_BLOCK |
Pre-allocated contiguous byte pool with hybrid bump + free-list allocator |
src/inline_vec.rs |
InlineVec<T, N> |
Stack-first small vector, one-way spill to heap |
src/ring_buffer.rs |
RingBuffer<T, N>, Iter, IntoIter |
Fixed-capacity circular buffer with power-of-2 bitwise indexing |
src/byte_ring.rs |
ByteRing |
Byte stream tail ring buffer keyed by absolute stream offsets |
src/atomic_bitset.rs |
AtomicBitSet |
Lock-free bitset with atomic test-and-set for concurrent dedup |
src/atomic_bitset_tests.rs |
— | Unit/property tests for AtomicBitSet |
src/atomic_seen_sets.rs |
AtomicSeenSets |
Composite concurrent dedup tracker for git object traversal |
src/atomic_seen_sets_tests.rs |
— | Unit/property tests for AtomicSeenSets |
src/bitset.rs |
DynamicBitSet, DynamicBitSetIterator, words_for_bits |
Runtime-sized bitset backed by Vec<u64> |
src/bitset_tests.rs |
— | Unit/property tests for DynamicBitSet |
src/byte_slab_tests.rs |
— | Unit/fuzz-adjacent tests for ByteSlab / ByteSlot |
src/fixed_set.rs |
FixedSet128 |
Epoch-resettable hash set for 128-bit keys |
src/timing_wheel.rs |
TimingWheel<T, G>, Bitset2, PushError, PushOutcome |
Hashed timing wheel with FIFO per bucket and bitmap occupancy |
src/timing_wheel_tests.rs |
— | Unit/property tests for TimingWheel |
src/spsc.rs |
OwnedSpscProducer, OwnedSpscConsumer, spsc_channel |
Wait-free SPSC bounded ring buffer |
src/fastrange.rs |
fast_range |
Division-free range reduction via multiply-high |
src/fnv.rs |
FNV_OFFSET, FNV_PRIME, fnv_mix_byte, fnv_mix_bytes, fnv_mix_opt_bytes, fnv_mix_u64 |
FNV-1a 64-bit hashing helpers for deterministic fingerprinting |
src/fnv_tests.rs |
— | Unit tests for FNV helpers |
src/git_test_support.rs |
git_available, run_git, git_stdout, git_output_raw, try_run_git, init_git_repo, init_committed_repo, decode_hex |
Shared git CLI fixtures and hex decoding for test/benchmark support (feature-gated: git-test-support) |
src/inline_vec_tests.rs |
— | Unit/fuzz-adjacent tests for InlineVec |
src/perf_stats.rs |
sat_add_u64, sat_add_u32, sat_add_usize, max_u64, max_u32, max_u16, set_u32, set_u64, set_usize |
Saturating counter helpers (no-op outside perf-stats + debug_assertions) |
src/ring_buffer_tests.rs |
— | Unit/fuzz-adjacent tests for RingBuffer |
src/test_support.rs |
proptest_cases, proptest_fuzz_multiplier |
Shared proptest configuration (feature-gated: stdx-proptest) |
Which container for which use case:
| Need | Type | Why |
|---|---|---|
| Variable-size byte fields per shard (keys, tokens, metadata) | ByteSlab / ByteSlot |
Pre-allocated pool; replaces per-field Box<[u8]> heap allocations |
| Small collection, usually 0-8 elements, rarely more | InlineVec<T, N> |
Stack-resident up to N; one-way spill avoids oscillation |
| Bounded event/history queue with FIFO semantics | RingBuffer<T, N> |
Fixed-capacity, zero heap allocation, O(1) push/pop |
| Tail of a byte stream with absolute offset lookups | ByteRing |
Circular buffer with has_range/contiguous_range by stream offset |
| Concurrent first-writer-wins dedup (bit-level) | AtomicBitSet |
Lock-free fetch_or; exactly one caller wins per bit |
| Git tree/blob/excluded-blob seen tracking | AtomicSeenSets |
Three independent AtomicBitSet instances with domain API |
| Runtime-sized bit tracking (single-threaded) | DynamicBitSet |
Heap-allocated, set/unset/iterate, padding invariant maintained |
| Per-chunk dedup with frequent resets | FixedSet128 |
O(1) epoch-based reset; open addressing with 128-bit keys |
| Scheduling windows by byte offset with bounded lateness | TimingWheel<T, G> |
Hashed timing wheel with FIFO buckets; fixed allocation |
| Cross-thread single-producer/single-consumer queue | spsc_channel |
Wait-free, no CAS, cache-line padded, power-of-2 capacity |
Map u64 to [0, p) without division |
fast_range |
Multiply-high; branch-free O(1) |
| Deterministic cross-platform hashing | fnv_mix_* |
FNV-1a 64-bit; same hash on all architectures/Rust versions |
Per the project allocation policy (AGENTS.md), types serve these tiers:
| Tier | Types | Rationale |
|---|---|---|
| HOT (per-shard/per-claim/per-tick steady-state) | ByteSlab/ByteSlot, InlineVec, RingBuffer, ByteRing, TimingWheel, FixedSet128, fast_range, fnv_mix_* |
All operations on these types are allocation-silent in steady state. ByteSlab uses bump + free-list within a pre-allocated buffer. InlineVec stays inline for typical small counts. RingBuffer is stack-allocated. FixedSet128 resets via epoch counter. TimingWheel uses a fixed node pool. |
| HOT (concurrent) | AtomicBitSet, AtomicSeenSets, OwnedSpscProducer/OwnedSpscConsumer |
Lock-free, wait-free operations with no allocation after construction. |
| WARM (frequent read/query/admin operations) | DynamicBitSet |
Heap-allocated at construction; all operations after construction are O(1) or O(WORDS) with no further allocation. |
| COLD (startup, registration, teardown) | All types at construction time | ByteSlab::with_capacity, AtomicBitSet::empty, TimingWheel::new, spsc_channel, etc. allocate once at startup. |
Purpose: Pre-allocated contiguous byte pool that replaces per-field Box<[u8]>
heap allocations for shard byte fields (start key, end key, metadata, cursor
last key, cursor token).
Key fields (ByteSlab):
buf: Vec<u8>— single allocation at construction, never resizedbump: u32— next free offset in the virgin regioncapacity: u32—buf.len()cached asu32free_list: Vec<(u32, u32)>— sorted by offset, pre-allocated at startup, never growsfree_bytes: u32— cached sum of all free-list block sizeslive_bytes: u32— sum ofalloc_sizefor all live slotslive_count: u32— number of live allocationsowner_id: u32— per-instance provenance tag
Key fields (ByteSlot):
offset: u32,len: u32,alloc_size: u32,owner_id: u32— 16 bytes total,Copy + Clone
Key methods:
ByteSlab::with_capacity(usize)— allocate once at startupByteSlab::allocate(&[u8]) -> Result<ByteSlot, SlabFull>— best-fit free-list, then bumpByteSlab::get(ByteSlot) -> &[u8]— O(1) slice into poolByteSlab::deallocate(ByteSlot)— coalesce with neighbors, reclaim trailing blocks into bumpByteSlab::clear()— O(1) reset; rotatesowner_idto invalidate stale slotsByteSlab::zeroize_used()— zero bytes in[0..bump)before clear (sensitive data)
Capacity/Sizing: All offsets, lengths, and capacities are u32 (max ~4 GiB).
Allocation sizes are rounded to the next power of 2 (min MIN_BLOCK = 16 bytes).
Worst-case internal fragmentation from rounding: ~50%. Expected average for
cursor-update workload: ~25%.
Thread safety: Not synchronized. Single-threaded usage assumed. Send + Sync
(compile-time asserted).
Invariants (machine-checked via debug_assert_invariants after every mutation):
bump <= capacity- Free list sorted, non-overlapping, no adjacent blocks
free_bytes == sum(free_list block sizes)live_bytes + free_bytes + (capacity - bump) == capacity(byte conservation)
Purpose: Stack-first small vector. Stores up to N elements inline; on the
N+1th push, all elements spill one-way to a heap Vec<T>. Typical use:
InlineVec<ShardId, 8> for spawned-children lists where 99%+ of shards have 0-2
children.
Key fields (internal Repr enum, no Drop impl on Repr):
Repr::Inline { buf: [MaybeUninit<T>; N], len: u32 }— stack storageRepr::Heap(Vec<T>)— after one-way spill
Key methods:
InlineVec::new()— empty, inline mode, zero heap allocationpush(T)— inline write or one-way spillextend_from_slice(&[T])whereT: Clone— fast-path bulk write when inline fitsfrom_slice(&[T])whereT: Copy— bulkcopy_nonoverlappingwhen fits inlineas_slice() -> &[T]— unified view regardless of representationas_mut_slice() -> &mut [T]iter() -> std::slice::Iter<'_, T>From<Vec<T>>— moves elements inline if they fit, otherwise adopts the VecFromIterator<T>— usessize_hintto choose strategy
Capacity/Sizing: N > 0 and N <= u32::MAX / 2 (compile-time assertion).
The half-u32 upper bound prevents len + 1 from overflowing during push.
Thread safety: No internal synchronization. Send when T: Send, Sync
when T: Sync (compile-time asserted).
Panic safety: extend_from_slice increments len after each successful
clone() + write (not after the whole loop), so Drop sees the correct count
if T::clone() panics mid-iteration.
Purpose: Fixed-capacity circular buffer with power-of-2 bitwise indexing. Zero heap allocation. Used for bounded event/history queues.
Key fields:
buf: [MaybeUninit<T>; N]— stack-allocated storagehead: u32— index of the logical frontlen: u32— number of initialized elements
Key methods:
RingBuffer::new()— empty, no heap allocationpush_back(T) -> Result<(), T>— returnsErr(value)if fullpush_back_overwrite(T) -> Option<T>— evicts oldest on overflowpop_front() -> Option<T>— removes oldestget(usize) -> Option<&T>— logical index 0 = oldestclear()— drops all elements in FIFO orderiter() -> Iter— borrowing iterator,DoubleEndedIterator+ExactSizeIteratorinto_iter() -> IntoIter— consuming iterator
Capacity/Sizing: N must be a power of 2, > 0, and <= u32::MAX / 2
(compile-time assertions). Bitwise AND masking for O(1) index calculation.
Thread safety: Not synchronized. Single-threaded usage assumed. Send + Sync
when T: Send + Sync (compile-time asserted).
Purpose: Byte stream tail ring buffer keyed by absolute stream offsets.
Models a logical, ever-growing byte stream; retains only the most recent
capacity bytes.
Key fields:
buf: Vec<u8>— circular storage, power-of-2 capacitymask: usize—capacity - 1for bitwise AND wrappinghead: usize— physical start of retained datalen: usize— number of retained bytesstart_offset: u64— absolute offset of the first retained byte
Key methods:
ByteRing::with_capacity(usize)— rounds up to next power of 2push(&[u8])— appends bytes, evicts oldest on overflowhas_range(lo: u64, hi: u64) -> bool— checks if[lo, hi)is retainedcontiguous_range(lo: u64, hi: u64) -> Option<&[u8]>— direct slice if range does not wrapextend_range_to(lo: u64, hi: u64, &mut Vec<u8>) -> bool— materializes range into outputsegments() -> (&[u8], &[u8])— up to two slices in logical orderreset()— clears all data, resetsstart_offsetto 0
Capacity/Sizing: Capacity is always a power of two. All index wrapping uses
& mask instead of modulo division.
Thread safety: Not synchronized. Single-threaded usage assumed.
Purpose: Lock-free bitset for concurrent first-writer-wins deduplication.
Atomic fetch_or guarantees exactly one caller observes "was-unset" per bit.
Key fields:
words: Vec<AtomicU64>— atomic storagebit_length: usize— number of addressable bits
Key methods:
AtomicBitSet::empty(bit_length: usize)— all bits zero; panics ifbit_length == 0test_and_set(idx: usize) -> bool— atomically sets bit; returnstrueif was previously unsetis_set(idx: usize) -> bool— snapshot readcount() -> usize— popcount across all words (snapshot)clear()— resets all bits; requires no concurrenttest_and_setcalls in-flight
Capacity/Sizing: ceil(bit_length / 64) words.
Thread safety: Send + Sync. All atomic operations use Relaxed ordering
(sufficient because fetch_or atomicity guarantees exactly one winner per bit,
and no dependent data requires acquire/release synchronization).
Purpose: Composite concurrent dedup tracker wrapping three AtomicBitSet
instances (trees, blobs, excluded-blobs) for git object traversal.
Key fields:
trees: AtomicBitSetblobs: AtomicBitSetblobs_excluded: AtomicBitSet
Key methods:
AtomicSeenSets::new(tree_capacity: usize, blob_capacity: usize)— both blob bitsets share the same capacitymark_tree(idx) -> bool/mark_blob(idx) -> bool/mark_blob_excluded(idx) -> bool— first-writer-winsis_tree_seen(idx)/is_blob_seen(idx)/is_blob_excluded(idx)— queryclear()— resets all three; requires no concurrentmark_*calls
Thread safety: Send + Sync (derived from AtomicBitSet). All operations
are lock-free.
Purpose: Runtime-sized bitset backed by Vec<u64>. Used when the number
of bits is not known at compile time.
Key fields:
words: Vec<u64>— non-atomic storagebit_length: usize
Key methods:
DynamicBitSet::empty(bit_length: usize)— all bits zero;bit_lengthmay be zeroset(idx)/unset(idx)/is_set(idx) -> bool— O(1) operationscount() -> usize— O(WORDS) popcountclear()— zero all wordstoggle_all()— inverts all bits; clears padding bits in last worditer_set() -> DynamicBitSetIterator— yields set bit indices in ascending order
Capacity/Sizing: words_for_bits(n) = ceil(n / 64) words.
Thread safety: Not synchronized. Single-threaded usage assumed.
Invariant: Padding bits in the last word are always zero. This is critical
for PartialEq correctness (relies on slice equality) and safe serialization.
Purpose: Fixed-capacity hash set for 128-bit key deduplication with O(1)
epoch-based reset. Used for per-chunk finding dedup (seen_findings in
ScanScratch).
Key fields:
slots: Vec<Slot128>— interleaved AoS layout (keyu128+ epochu32+ padding; 32 bytes/slot)cur: u32— current generation counter (never zero)mask: usize—slots.len() - 1
Key methods:
FixedSet128::with_pow2(cap_pow2: usize)— capacity must be power of twoinsert(key: u128) -> bool—falseif already present in current epoch;trueif newreset()— O(1) generation advance; rareu32wraparound triggers one full clear
Capacity/Sizing: Power-of-two slot count. Open addressing with linear probing. Upper 64 bits of the key used for initial probe slot selection.
Behavior when full: insert returns true but does not store the key
(best-effort dedupe). A later insert of the same key may return true again.
Thread safety: Not synchronized.
Purpose: Hashed timing wheel for scheduling windows by byte offset. Time
unit is "bytes of decoded stream." Bucket key is ceil(hi_end / G). Items are
guaranteed to never fire early; they may fire up to G-1 bytes late.
Key fields:
wheel_size: usize— power of two,>= 2head: Box<[u32]>/tail: Box<[u32]>— per-slot intrusive FIFO listslot_key: Box<[u64]>— absolute bucket key for occupied slotsocc: Bitset2— two-level occupancy bitmap for fast "next non-empty" scansnext: Box<[u32]>/payload: Box<[MaybeUninit<T>]>— fixed-size node poolfree_head: u32— free-list headcursor_abs: u64/cursor_slot: usize— next bucket to processlen: usize/cap: usize— current count / node pool capacity
Key methods:
TimingWheel::new(max_horizon_bytes: u64, node_cap: usize)— fixed allocation at constructionpush(hi_end: u64, payload: T) -> Result<PushOutcome<T>, PushError>— O(1); returnsReady(T)if already due,Scheduledif queued, orPushErroradvance_and_drain(now_offset: u64, on_ready: F) -> usize— drains buckets up tofloor(now_offset / G); O(buckets + items drained)advance_and_drain_into(now_offset: u64, &mut Vec<T>) -> usize— convenience wrapperreset()— clears all state without reallocating; rewinds cursor to bucket 0len()/is_empty()/capacity()
Capacity/Sizing: Wheel size is a power of two sized from
ceil((max_horizon_bytes + G-1) / G) + 1. Node pool is exactly node_cap.
Thread safety: Not synchronized. Single-threaded usage assumed.
Safety: One unsafe block in advance_and_drain for
MaybeUninit::assume_init_read. Sound because the node was initialized via
alloc_node and T: Copy prevents double-drop. debug_validate() method
walks all slots + free list asserting every node is either free or used exactly
once. Validated with unit tests, property-based tests, and Kani proofs.
Purpose: Wait-free single-producer/single-consumer bounded ring buffer.
Based on Rigtorp's SPSCQueue. No CAS; uses only Acquire/Release loads and
stores. On x86-64 TSO these compile to plain MOV instructions.
Key fields (internal SpscRing<T, N>):
buf: UnsafeCell<[MaybeUninit<T>; N]>— slot storagehead: CachePadded<AtomicU32>— consumer's read indextail: CachePadded<AtomicU32>— producer's write index
Key methods:
spsc_channel::<T: Send + 'static, const N: usize>() -> (OwnedSpscProducer<T, N>, OwnedSpscConsumer<T, N>)— creates a channelOwnedSpscProducer::try_push(T) -> Result<(), T>— returnsErr(value)if fullOwnedSpscConsumer::try_pop() -> Option<T>— returnsNoneif emptyOwnedSpscConsumer::try_pop_batch(&mut [MaybeUninit<T>]) -> usize— batch drain
Capacity/Sizing: N must be a power of 2, > 0, and <= u32::MAX / 2
(compile-time assertion). Single heap allocation for the shared ring.
Performance: Cached remote index reduces cache-coherence traffic. Producer
caches consumer's head; consumer caches producer's tail. Only refreshed
on apparent-full/apparent-empty. Head and tail live on separate cache lines
(via CachePadded) to prevent false sharing.
Thread safety: Send (not Sync by design). Each handle must be used
from exactly one thread (enforced by &mut self). Can be moved across threads.
Safety: Uses raw *const SpscRing pointers instead of &SpscRing to
avoid Stacked Borrows violations when producer and consumer access disjoint
slots concurrently. Ownership via Box::into_raw + Arc<OwnedSpscInner>.
Validated with unit tests, property-based tests (FIFO invariant), loom
exhaustive concurrency tests, and 8 Kani formal verification proofs (slot
bounds, FIFO, full/empty, wrapping near u32::MAX, batch bounds, drop).
Purpose: Division-free range reduction. Maps a 64-bit word into [0, p)
via multiply-high: ((word as u128) * (p as u128)) >> 64.
Signature: fast_range(word: u64, p: u64) -> u64
Guarantees: Returns a value in [0, p) when p > 0. Branch-free O(1).
Note: This is not equivalent to % p for non-uniform inputs. For uniform
64-bit input, outputs are close to uniform.
Purpose: Deterministic 64-bit hashing for page signatures and finding
fingerprints. FNV-1a was chosen over DefaultHasher/SipHash for cross-platform
determinism.
Functions:
fnv_mix_byte(sig: &mut u64, byte: u8)— mix one bytefnv_mix_u64(sig: &mut u64, value: u64)— mix u64 as 8 LE bytesfnv_mix_bytes(sig: &mut u64, bytes: &[u8])— length-prefixed, bulk 8-byte wordsfnv_mix_opt_bytes(sig: &mut u64, bytes: Option<&[u8]>)— domain-separated tag byte
Constants: FNV_OFFSET = 0xcbf29ce484222325, FNV_PRIME = 0x100000001b3
Contract: Variable-length fields are length-prefixed. Option<&[u8]> uses
a tag byte (0 = None, 1 = Some) for domain separation.
Purpose: Saturating counter helpers for scan-time instrumentation. All
functions compile to no-ops unless all(feature = "perf-stats", debug_assertions)
is enabled.
Functions: sat_add_u64, sat_add_u32, sat_add_usize, max_u64, max_u32,
max_u16, set_u32, set_u64, set_usize
| Type | Miri | Kani | Fuzz | Loom | Proptest |
|---|---|---|---|---|---|
ByteSlab / ByteSlot |
Yes | — | fuzz_byte_slab |
— | — |
InlineVec<T, N> |
Yes | 9 proofs (8 of 9 unsafe blocks) | fuzz_inline_vec |
— | — |
RingBuffer<T, N> |
Yes | — | fuzz_ring_buffer |
— | — |
ByteRing |
Yes | — | — | — | — |
AtomicBitSet |
Yes | 6 proofs | fuzz_atomic_bitset |
3 tests (concurrent dedup, no lost updates, three-thread) | Yes (proptest) |
AtomicSeenSets |
Yes | 5 proofs | — | 3 tests (tree dedup, blob dedup, independence) | Yes (proptest) |
DynamicBitSet |
Yes | 12 proofs | — | — | Yes (proptest: 6 property tests) |
FixedSet128 |
Yes | — | — | — | Yes (proptest: 5 property tests) |
TimingWheel<T, G> |
Yes | 14 proofs | fuzz_timing_wheel |
— | Yes (proptest) |
spsc_channel |
Yes | 8 proofs (bounds, FIFO, full/empty detection, wrapping, batch, drop) | fuzz_spsc |
2 tests (FIFO ordering, full retry) | Yes (proptest: FIFO invariant) |
fast_range |
Yes | — | — | — | Yes (proptest: range, power-of-2) |
fnv_mix_* |
Yes | — | — | — | — |
Miri: All tests run under Miri via cargo +nightly miri test -p gossip-stdx.
Kani: Feature-gated (cfg(kani)). 54 total proofs across the crate.
InlineVec has 9 formal proofs covering push bounds, spill preservation,
as_slice, drop, clone, from_slice, From<Vec>, uninit_array, and spill
element conservation. spsc_channel has 8 proofs covering slot index bounds,
FIFO ordering across wrap, full/empty detection, batch pop, wrapping near
u32::MAX, and drop coverage. TimingWheel has 14 proofs, DynamicBitSet
has 12, AtomicBitSet has 6, and AtomicSeenSets has 5.
Fuzz: Targets in fuzz/fuzz_targets/ exercise randomized operation sequences.
Loom: AtomicBitSet, AtomicSeenSets, and spsc_channel have loom tests
that exhaustively explore all thread interleavings for small state spaces.
Crate-level lints: deny(unsafe_op_in_unsafe_fn) forces explicit unsafe
blocks inside unsafe fn with // SAFETY: comments.
deny(clippy::undocumented_unsafe_blocks) requires // SAFETY: on every
unsafe block.
The crate includes Criterion benchmarks:
| Benchmark | File |
|---|---|
ring_buffer |
benches/ring_buffer.rs |
inline_vec |
benches/inline_vec.rs |
byte_slab |
benches/byte_slab.rs |
bitset_fixedset |
benches/bitset_fixedset.rs |
fixed_set |
benches/fixed_set.rs |
fixed_vec |
benches/fixed_vec.rs |
timing_wheel |
benches/timing_wheel.rs |
During scanner-rs consolidation, duplicate container implementations are avoided:
scanner-rs::stdx::fixed_vec::FixedVec<T, N>maps toInlineVec<T, N>scanner-rs::stdx::ring_buffer::RingBuffer<T, N>maps toRingBuffer<T, N>
crossbeam-utils(runtime) —CachePaddedfor SPSC cache-line separationcriterion(dev) — benchmarkingloom(dev) — concurrency testing for atomic types and SPSCproptest(dev) — property-based testing
| Feature | Purpose |
|---|---|
kani |
Enables Kani formal verification proofs |
stdx-proptest |
Enables test_support module and proptest-gated test modules |
perf-stats |
Enables instrumentation counter updates (combined with debug_assertions) |
git-test-support |
Enables git_test_support module with shared git CLI fixtures and hex decoding |
| Artifact | Authoritative Path |
|---|---|
| Crate root | crates/gossip-stdx/src/lib.rs |
| ByteSlab implementation | crates/gossip-stdx/src/byte_slab.rs |
| InlineVec implementation | crates/gossip-stdx/src/inline_vec.rs |
| RingBuffer implementation | crates/gossip-stdx/src/ring_buffer.rs |
| ByteRing implementation | crates/gossip-stdx/src/byte_ring.rs |
| AtomicBitSet implementation | crates/gossip-stdx/src/atomic_bitset.rs |
| AtomicSeenSets implementation | crates/gossip-stdx/src/atomic_seen_sets.rs |
| DynamicBitSet implementation | crates/gossip-stdx/src/bitset.rs |
| FixedSet128 implementation | crates/gossip-stdx/src/fixed_set.rs |
| TimingWheel implementation | crates/gossip-stdx/src/timing_wheel.rs |
| SPSC channel implementation | crates/gossip-stdx/src/spsc.rs |
| fast_range implementation | crates/gossip-stdx/src/fastrange.rs |
| FNV hashing implementation | crates/gossip-stdx/src/fnv.rs |
| perf_stats implementation | crates/gossip-stdx/src/perf_stats.rs |
| Fuzz targets | crates/gossip-stdx/fuzz/fuzz_targets/ |
| Cargo manifest | crates/gossip-stdx/Cargo.toml |
| This document | docs/gossip-stdx.md |