Struct miniconf::Packed

source ·
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 TreeKeys a u16 or even a u8 is sufficient to hold a Packed in LSB notation. Together with the Postcard trait and 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

source

pub const BITS: u32 = 64u32

Number of bits in the representation including the marker bit

source

pub const CAPACITY: u32 = 63u32

The total number of bits this representation can store.

source

pub const EMPTY: Self = _

The empty value

source

pub const fn new(value: usize) -> Option<Self>

Create a new Packed from a usize.

The value must not be zero.

source

pub const fn new_from_lsb(value: usize) -> Option<Self>

Create a new Packed from LSB aligned usize

The value must not be zero.

source

pub const fn is_empty(&self) -> bool

The value is empty.

source

pub fn clear(&mut self)

Clear and discard all bits stored.

source

pub const fn len(&self) -> u32

Number of bits stored.

source

pub const fn into_lsb(self) -> NonZeroUsize

Return the representation aligned to the LSB with the marker bit moved from the LSB to the MSB.

source

pub const fn from_lsb(value: NonZeroUsize) -> Self

Build a Packed from a LSB-aligned representation with the marker bit moved from the MSB the LSB.

source

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.

source

pub fn pop_msb(&mut self, bits: u32) -> Option<usize>

Remove the given number of MSBs and return them.

If the value does not contain sufficient bits it is left unchanged and None is returned.

§Args
  • bits: Number of bits to pop. bits <= Self::CAPACITY
source

pub fn push_lsb(&mut self, bits: u32, value: usize) -> Option<u32>

Push the given number bits of value as new LSBs.

Returns the remaining number of unused bits on success.

§Args
  • bits: Number of bits to push. bits <= Self::CAPACITY
  • value: Value to push. value >> bits == 0

Trait Implementations§

source§

impl Clone for Packed

source§

fn clone(&self) -> Packed

Returns a copy of the value. Read more
1.0.0 · source§

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

Performs copy-assignment from source. Read more
source§

impl Debug for Packed

source§

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

Formats the value using the given formatter. Read more
source§

impl Default for Packed

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl Deref for Packed

§

type Target = NonZero<usize>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl DerefMut for Packed

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<'de> Deserialize<'de> for Packed

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl From<NonZero<usize>> for Packed

source§

fn from(value: NonZeroUsize) -> Self

Converts to this type from the input type.
source§

impl From<Packed> for NonZeroUsize

source§

fn from(value: Packed) -> Self

Converts to this type from the input type.
source§

impl Hash for Packed

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl IntoKeys for Packed

§

type IntoKeys = Packed

The specific Keys implementor.
source§

fn into_keys(self) -> Self::IntoKeys

Convert self into a Keys implementor.
source§

impl Keys for Packed

source§

fn next<M: KeyLookup + ?Sized>(&mut self) -> Result<usize, Traversal>

Look up the next key in a KeyLookup and convert to usize index.
source§

fn is_empty(&mut self) -> bool

Return whether there are more keys. Read more
source§

impl Ord for Packed

source§

fn cmp(&self, other: &Packed) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for Packed

source§

fn eq(&self, other: &Packed) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Packed

source§

fn partial_cmp(&self, other: &Packed) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl Serialize for Packed

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Copy for Packed

source§

impl Eq for Packed

source§

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

§

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

§

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.
source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,