pub struct Packed(/* private fields */);
Expand description
A bit-packed representation of multiple indices.
Given known bit width of each index, the bits are concatenated above a marker bit.
The value consists of (from storage MSB to LSB):
- Zero or more groups of variable bit length, concatenated, each containing one index. The first is aligned with the storage MSB.
- A set bit to mark the end of the used bits.
- Zero or more cleared bits corresponding to unused index space.
Packed::EMPTY
has the marker at the MSB.
During Packed::push_lsb()
the indices are inserted with their MSB
where the marker was and the marker moves toward the storage LSB.
During Packed::pop_msb()
the indices are removed with their MSB
aligned with the storage MSB and the remaining bits and the marker move
toward the storage MSB.
The representation is MSB aligned to make PartialOrd
/Ord
more natural and stable.
The Packed
key Ord
matches the ordering of nodes in a horizontal leaf tree
traversal. New nodes can be added/removed to the tree without changing the implicit
encoding (and ordering!) as long no new bits need to be allocated/deallocated (
as long as the number of child nodes of an internal node does not cross a
power-of-two boundary).
Under this condition the mapping between indices/paths and Packed
representation
is stable even if child nodes are added/removed.
“Small numbers” in LSB-aligned representation can be obtained through
Packed::into_lsb()
/Packed::from_lsb()
but don’t have the ordering
and stability properties.
Packed
can be used to uniquely identify
nodes in a TreeKey
using only a very small amount of bits.
For many realistic TreeKey
s a u16
or even a u8
is sufficient
to hold a Packed
in LSB notation. Together with the
postcard
serde
format, this then gives access to any node in a nested
heterogeneous Tree
with just a u16
or u8
as compact key and [u8]
as
compact value.
use miniconf::Packed;
let mut p = Packed::EMPTY;
let mut p_lsb = 0b1; // marker
for (bits, value) in [(2, 0b11), (1, 0b0), (0, 0b0), (3, 0b101)] {
p.push_lsb(bits, value).unwrap();
p_lsb <<= bits;
p_lsb |= value;
}
assert_eq!(p_lsb, 0b1_11_0__101);
// ^ marker
assert_eq!(p, Packed::from_lsb(p_lsb.try_into().unwrap()));
assert_eq!(p.get(), 0b11_0__101_1 << (Packed::CAPACITY - p.len()));
// ^ marker
Implementations§
source§impl Packed
impl Packed
sourcepub const fn new(value: usize) -> Option<Self>
pub const fn new(value: usize) -> Option<Self>
Create a new Packed
from a usize
.
The value must not be zero.
sourcepub const fn new_from_lsb(value: usize) -> Option<Self>
pub const fn new_from_lsb(value: usize) -> Option<Self>
Create a new Packed
from LSB aligned usize
The value must not be zero.
sourcepub const fn into_lsb(self) -> NonZero<usize>
pub const fn into_lsb(self) -> NonZero<usize>
Return the representation aligned to the LSB with the marker bit moved from the LSB to the MSB.
sourcepub const fn from_lsb(value: NonZero<usize>) -> Self
pub const fn from_lsb(value: NonZero<usize>) -> Self
Build a Packed
from a LSB-aligned representation with the marker bit
moved from the MSB the LSB.
sourcepub const fn bits_for(num: usize) -> u32
pub const fn bits_for(num: usize) -> u32
Return the number of bits required to represent num
.
Ensures that at least one bit is allocated.
Methods from Deref<Target = NonZero<usize>>§
pub const BITS: u32 = 8u32
pub const MIN: NonZero<u8> = _
pub const MAX: NonZero<u8> = _
pub const BITS: u32 = 16u32
pub const MIN: NonZero<u16> = _
pub const MAX: NonZero<u16> = _
pub const BITS: u32 = 32u32
pub const MIN: NonZero<u32> = _
pub const MAX: NonZero<u32> = _
pub const BITS: u32 = 64u32
pub const MIN: NonZero<u64> = _
pub const MAX: NonZero<u64> = _
pub const BITS: u32 = 128u32
pub const MIN: NonZero<u128> = _
pub const MAX: NonZero<u128> = _
pub const BITS: u32 = 32u32
pub const MIN: NonZero<usize> = _
pub const MAX: NonZero<usize> = _
pub const BITS: u32 = 8u32
pub const MIN: NonZero<i8> = _
pub const MAX: NonZero<i8> = _
pub const BITS: u32 = 16u32
pub const MIN: NonZero<i16> = _
pub const MAX: NonZero<i16> = _
pub const BITS: u32 = 32u32
pub const MIN: NonZero<i32> = _
pub const MAX: NonZero<i32> = _
pub const BITS: u32 = 64u32
pub const MIN: NonZero<i64> = _
pub const MAX: NonZero<i64> = _
pub const BITS: u32 = 128u32
pub const MIN: NonZero<i128> = _
pub const MAX: NonZero<i128> = _
pub const BITS: u32 = 32u32
pub const MIN: NonZero<isize> = _
pub const MAX: NonZero<isize> = _
Trait Implementations§
source§impl<'de> Deserialize<'de> for Packed
impl<'de> Deserialize<'de> for Packed
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
source§impl Keys for Packed
impl Keys for Packed
source§impl Ord for Packed
impl Ord for Packed
source§impl PartialOrd for Packed
impl PartialOrd for Packed
impl Copy for Packed
impl Eq for Packed
impl StructuralPartialEq for Packed
Auto Trait Implementations§
impl Freeze for Packed
impl RefUnwindSafe for Packed
impl Send for Packed
impl Sync for Packed
impl Unpin for Packed
impl UnwindSafe for Packed
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)