Skip to main content

ColumnarEntityIndex

Struct ColumnarEntityIndex 

Source
pub struct ColumnarEntityIndex { /* private fields */ }
Expand description

Compact, sorted, binary-searched entity index. Columns are kept sorted by ids (strictly ascending, unique) so Self::lookup can binary_search.

Invariants (upheld by every constructor):

  • ids.len() == starts.len() == lengths.len()
  • ids is strictly ascending (hence unique)
  • starts[i] / lengths[i] are the byte offset / byte length of ids[i], so lookup returns (start, start + length) to match the (start, end) tuple layout of EntityIndex.

Implementations§

Source§

impl ColumnarEntityIndex

Source

pub fn from_columns(ids: &[u32], starts: &[u32], lengths: &[u32]) -> Self

Build from the three delivered columns (setEntityIndex ingestion).

Verifies the id column’s ordering once, O(n): the pre-pass emits in whatever order it iterates (its own FxHashMap iteration order is arbitrary), so this cannot assume ascending. If the ids are already strictly ascending the columns are used as-is (no sort); otherwise a single stable argsort permutation is applied and duplicate ids are collapsed last-in-input-order-wins.

Mismatched column lengths yield an empty index (the wasm caller guards this too), so a malformed payload never panics a worker.

Source

pub fn from_hashmap_consuming(map: EntityIndex) -> Self

Build from an already-scanned EntityIndex hashmap, CONSUMING it. On the wasm prepass path the map is ~436 MB at 19.1 M entities and the conversion runs while the whole source file is resident in the same <4 GiB heap; borrowing (from_hashmap) keeps the map alive across the copy AND the sort, spiking ~970 MB of transients.

Consuming drains into one interleaved Vec<(id, start, len)> (~229 MB) then sorts in place (sort_unstable; map keys are unique, so no stability/permutation buffer). Peak during the drain is map + rows capacity (~665 MB) until the map drops at end-of-loop; after that the sort is in-place and the final column split briefly overlaps rows + outputs (~458 MB) before rows drop. Still far below the borrowing path, and the steady-state index is ~229 MB.

Source

pub fn from_hashmap(map: &EntityIndex) -> Self

Build from an already-scanned EntityIndex hashmap. The map is unique by construction (last-in-file-order-wins was applied by HashMap::insert), so this only sorts the entries. Prefer Self::from_hashmap_consuming when the map is no longer needed - it avoids holding map + copies concurrently (P1 review finding on #1689).

Source

pub fn from_scan<T>(content: &T) -> Self
where T: AsRef<[u8]> + ?Sized,

Scan content and build the columns directly, replicating crate::build_entity_index’s HEADER-skipping / quoted-string scan and its last-in-file-order-wins duplicate handling — without ever materializing the intermediate FxHashMap. Used by the wasm lazy fallback when setEntityIndex was never called.

Source

pub fn lookup(&self, id: u32) -> Option<(usize, usize)>

Binary-search the byte span of id. Returns (start, end) where end = start + length, exactly matching EntityIndex’s tuple, or None if the id is absent.

Source

pub fn ids(&self) -> &[u32]

Sorted, unique id column (for re-emitting the entity-index event).

Source

pub fn starts(&self) -> &[u32]

Byte-start column, parallel to Self::ids.

Source

pub fn lengths(&self) -> &[u32]

Byte-length column, parallel to Self::ids.

Source

pub fn len(&self) -> usize

Number of indexed entities.

Source

pub fn is_empty(&self) -> bool

Whether the index is empty.

Auto Trait Implementations§

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> 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, 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.