48 lines
1.5 KiB
Rust
48 lines
1.5 KiB
Rust
|
|
//! Opaque row identifiers.
|
||
|
|
//!
|
||
|
|
//! Each backend assigns its own bytes for a [`RowId`]; the trait treats them
|
||
|
|
//! opaquely. The in-memory backend and the KV backends use a big-endian `u64`
|
||
|
|
//! row counter; the geomerge backend encodes its `(CommitHash, counter)`
|
||
|
|
//! pair. Callers do not interpret the bytes: they hand a `RowId` back to the
|
||
|
|
//! same backend to reference an existing row.
|
||
|
|
//!
|
||
|
|
//! Storage is inline up to 36 bytes (the geomerge `(CommitHash, counter)`
|
||
|
|
//! width), which covers every encoding the workspace produces today. Wider
|
||
|
|
//! row-id encodings spill to the heap automatically via [`SmallVec`].
|
||
|
|
|
||
|
|
use smallvec::SmallVec;
|
||
|
|
|
||
|
|
const INLINE_BYTES: usize = 36;
|
||
|
|
|
||
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||
|
|
pub struct RowId(SmallVec<[u8; INLINE_BYTES]>);
|
||
|
|
|
||
|
|
impl RowId {
|
||
|
|
/// Build a row id by copying the given bytes into inline storage when they
|
||
|
|
/// fit (≤ 36 bytes) or onto the heap when they don't.
|
||
|
|
pub fn new(bytes: impl AsRef<[u8]>) -> Self {
|
||
|
|
Self(SmallVec::from_slice(bytes.as_ref()))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// View the underlying bytes.
|
||
|
|
#[must_use]
|
||
|
|
pub fn as_bytes(&self) -> &[u8] {
|
||
|
|
&self.0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl std::fmt::Display for RowId {
|
||
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
|
|
for byte in &self.0 {
|
||
|
|
write!(f, "{byte:02x}")?;
|
||
|
|
}
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl From<u64> for RowId {
|
||
|
|
fn from(value: u64) -> Self {
|
||
|
|
Self(SmallVec::from_slice(&value.to_be_bytes()))
|
||
|
|
}
|
||
|
|
}
|