Skip to main content

Interner

Struct Interner 

Source
pub struct Interner<'a> { /* private fields */ }
Expand description

A deduplicating string store over a BlobHeap and a flat hash table.

use plugmem_arena::{BlobHeapCfg, Interner};

let mut terms = Interner::new(BlobHeapCfg::new());
let apple = terms.intern("apple").unwrap();
let banana = terms.intern("banana").unwrap();
assert_eq!(terms.intern("apple").unwrap(), apple); // stable id
assert_ne!(apple, banana);
assert_eq!(terms.resolve(apple), "apple");
assert_eq!(terms.len(), 2);

Clone is cheap-ish (two flat memcpys) and safe: unlike the arena, every stored byte is initialized.

Implementations§

Source§

impl<'a> Interner<'a>

Source

pub fn new(cfg: BlobHeapCfg) -> Self

Creates an empty interner; cfg bounds the underlying string heap (BlobHeapCfg::max_blob caps a single term’s byte length). The hash table itself is small (4 bytes per slot) and not counted against cfg.max_bytes.

Source

pub fn intern(&mut self, s: &str) -> Result<TermId, Error>

Returns the id for s, storing it on first sight.

§Errors

A failed intern leaves the interner unchanged.

Source

pub fn lookup(&self, s: &str) -> Option<TermId>

Returns the id of an already-interned string, without creating it.

The read-only sibling of Interner::intern — query paths must not grow the vocabulary (a query is not a mutation).

Source

pub fn resolve(&self, id: TermId) -> &str

Returns the string behind an id. O(1).

§Panics

Panics if id was not returned by this interner’s Interner::intern — a dangling id is a caller bug.

Source

pub fn len(&self) -> usize

Number of distinct strings interned.

Source

pub fn is_empty(&self) -> bool

true when nothing has been interned.

Source

pub fn pool_bytes(&self) -> usize

Total bytes of interned string content (the underlying heap’s pool size; the hash table’s few bytes per slot are not counted).

Source

pub fn dump_index(&self, out: &mut Vec<u8>)

Appends the string heap’s index section to out; see BlobHeap::dump_index.

Source

pub fn dump_pool(&self, out: &mut Vec<u8>)

Appends the string heap’s pool section to out; see BlobHeap::dump_pool.

Source

pub fn dump_table(&self, out: &mut Vec<u8>)

Appends the hash-table section to out.

Layout (little-endian): [slots u32][len u32] then slots × u32 entries (0 = empty, else TermId + 1). The table is persisted rather than rebuilt on load: rebuilding is O(terms × hash) and the cold-start budget is tighter than the 4 bytes per slot.

Source

pub fn load( cfg: BlobHeapCfg, index: &[u8], pool: &[u8], table: &[u8], ) -> Result<Self, Error>

Rebuilds an interner from its three dumped sections.

The input is untrusted — no panic on arbitrary bytes. On top of BlobHeap::load, validation covers:

  • every stored blob is valid UTF-8 (O(pool bytes), SIMD-speed) — this is what keeps Interner::resolve infallible;
  • table shape: power-of-two slot count >= 16, exact section length, the ≤ 0.7 load factor, len equal to the heap’s blob count;
  • table entries: in bounds, no id stored twice, and exactly len of them (checked with a visited bitmap).

Entry placement (that each id sits on its hash’s probe path) is not re-verified — that would cost the full rebuild the stored table exists to avoid. A well-formed but misplaced table cannot cause memory unsafety or a panic; it degrades intern to assigning a duplicate id for the affected terms. Section checksums cover accidental corruption.

§Errors

Error::Corrupt for any inconsistency.

Source

pub fn load_borrowed( cfg: BlobHeapCfg, index: &[u8], pool: &'a [u8], table: &[u8], ) -> Result<Self, Error>

Rebuilds an interner that borrows its string bytes from a longer-lived buffer (a memory-mapped snapshot). The table stays owned; validation is identical to Interner::load. The term dictionary is small (Zipf vocabulary), so paging it in to check UTF-8 is cheap and the large pools (texts, vectors) still load lazily.

§Errors

Error::Corrupt for any inconsistency (same gates as load).

Trait Implementations§

Source§

impl<'a> Clone for Interner<'a>

Source§

fn clone(&self) -> Interner<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Interner<'_>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Summary only — the vocabulary is the owner’s data, not ours to dump.

Auto Trait Implementations§

§

impl<'a> Freeze for Interner<'a>

§

impl<'a> RefUnwindSafe for Interner<'a>

§

impl<'a> Send for Interner<'a>

§

impl<'a> Sync for Interner<'a>

§

impl<'a> Unpin for Interner<'a>

§

impl<'a> UnsafeUnpin for Interner<'a>

§

impl<'a> UnwindSafe for Interner<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.