Enum zerovec::ZeroVec[][src]

#[non_exhaustive]
pub enum ZeroVec<'a, T> where
    T: AsULE + ?Sized
{ Owned(Vec<T::ULE>), Borrowed(&'a [T::ULE]), }
Expand description

A zero-copy vector for fixed-width types.

ZeroVec<T> is designed as a drop-in replacement for Vec<T> in situations where it is desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization.

T must implement AsULE, which is auto-implemented for a number of built-in types, including all fixed-width multibyte integers.

How it Works

ZeroVec<T> represents a slice of T as a slice of T::ULE. The difference between T and T::ULE is that T::ULE must be encoded in little-endian with 1-byte alignment. When accessing items from ZeroVec<T>, we fetch the T::ULE, convert it on the fly to T, and return T by value.

Benchmarks can be found in the project repository. We found that for common operations on small and large vectors, ZeroVec<T> performs from slightly faster to 15% slower than Vec<T>. However, the main performance improvement on ZeroVec<T> is when deserializing from a byte array; ZeroVec<T> deserializes 80% faster than Vec<T> in Serde Bincode, and it does not require any heap allocations.

Safety

ZeroVec<T> contains no unsafe code. However, the conversion from &[u8] to &[T::ULE] may be unsafe. For more information, see the ule module.

Example

use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];

// Conversion from &[u8] to &[u16::ULE] is infallible.
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert!(matches!(zerovec, ZeroVec::Borrowed(_)));
assert_eq!(zerovec.get(2), Some(421));
assert_eq!(zerovec, nums);

Variants (Non-exhaustive)

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
Owned(Vec<T::ULE>)

An owned ZeroVec<T>. This will typically be constructed by ZeroVec::clone_from_slice() or by calling ZeroVec::to_mut()/ZeroVec::for_each_mut()/etc on ZeroVec::Borrowed.

Tuple Fields of Owned

0: Vec<T::ULE>
Borrowed(&'a [T::ULE])

A borrowed ZeroVec<T>. This will typically be constructed by ZeroVec::parse_byte_slice(), ZeroVec::from_slice(), or deserializers capable of doing zero-copy deserialization.

If you already have a slice of [T::ULE]s, you can directly construct one of these.

Example

use zerovec::ZeroVec;
use zerovec::ule::*;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[PlainOldULE<2>] = &[211_u16.as_unaligned(), 281_u16.as_unaligned(),
                                421_u16.as_unaligned(), 461_u16.as_unaligned()];

let zerovec = ZeroVec::<u16>::Borrowed(nums);

assert!(matches!(zerovec, ZeroVec::Borrowed(_)));
assert_eq!(bytes, zerovec.as_bytes());

Tuple Fields of Borrowed

0: &'a [T::ULE]

Implementations

Parses a &[u8] buffer into a ZeroVec<T>.

This function is infallible for built-in integer types, but fallible for other types, such as char. For more information, see ULE::parse_byte_slice.

The bytes within the byte buffer must remain constant for the life of the ZeroVec.

Endianness

The byte buffer must be encoded in little-endian, even if running in a big-endian environment. This ensures a consistent representation of data across platforms.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert!(matches!(zerovec, ZeroVec::Borrowed(_)));
assert_eq!(zerovec.get(2), Some(421));

Returns a ZeroVec<T> as its underlying &[u8] byte buffer representation.

Useful for serialization.

Example
use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];

let zerovec = ZeroVec::clone_from_slice(nums);

assert_eq!(bytes, zerovec.as_bytes());

Dereferences this ZeroVec<T> as &[T::ULE]. Most other functions on ZeroVec<T> use this function as a building block.

Returns the number of elements in this ZeroVec<T>.

Example
use zerovec::ZeroVec;
use zerovec::ule::AsULE;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert_eq!(4, zerovec.len());
assert_eq!(
    bytes.len(),
    zerovec.len() * std::mem::size_of::<<u16 as AsULE>::ULE>()
);

Returns whether the vec is empty.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");
assert!(!zerovec.is_empty());

let emptyvec: ZeroVec<u16> = ZeroVec::parse_byte_slice(&[]).expect("infallible");
assert!(emptyvec.is_empty());

Creates a ZeroVec<T> from a &[T] by allocating memory.

This function results in an Owned instance of ZeroVec<T>.

Example
use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];

let zerovec = ZeroVec::clone_from_slice(nums);

assert!(matches!(zerovec, ZeroVec::Owned(_)));
assert_eq!(bytes, zerovec.as_bytes());

Creates a Vec<T> from a ZeroVec<T>.

Example
use zerovec::ZeroVec;

let nums: &[u16] = &[211, 281, 421, 461];
let vec: Vec<u16> = ZeroVec::clone_from_slice(nums).to_vec();

assert_eq!(nums, vec.as_slice());

Attempts to create a ZeroVec<'a, T> from a &'a [T] by borrowing the argument.

If this is not possible, such as on a big-endian platform, None is returned.

Example
use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];

if let Some(zerovec) = ZeroVec::try_from_slice(nums) {
    assert!(matches!(zerovec, ZeroVec::Borrowed(_)));
    assert_eq!(bytes, zerovec.as_bytes());
}

Creates a ZeroVec<'a, T> from a &'a [T], either by borrowing the argument or by allocating a new vector.

This is a cheap operation on little-endian platforms, falling back to a more expensive operation on big-endian platforms.

Example
use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];

let zerovec = ZeroVec::from_slice(nums);

// Note: zerovec could be either borrowed or owned.
assert_eq!(bytes, zerovec.as_bytes());

Gets the element at the specified index. Returns None if out of range.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert_eq!(zerovec.get(2), Some(421));
assert_eq!(zerovec.get(4), None);

Gets the first element. Returns None if empty.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert_eq!(zerovec.first(), Some(211));

Gets the last element. Returns None if empty.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert_eq!(zerovec.last(), Some(461));

Gets an iterator over the elements.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");
let mut it = zerovec.iter();

assert_eq!(it.next(), Some(211));
assert_eq!(it.next(), Some(281));
assert_eq!(it.next(), Some(421));
assert_eq!(it.next(), Some(461));
assert_eq!(it.next(), None);

Mutates each element according to a given function, meant to be a more convenient version of [ZeroVec::iter_mut()] which serves fewer use cases.

This will convert the ZeroVec into an owned ZeroVec if not already the case.

Example
use zerovec::ZeroVec;
use zerovec::ule::AsULE;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

zerovec.for_each_mut(|item| *item += 1);

assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
assert!(matches!(zerovec, ZeroVec::Owned(_)));

Same as ZeroVec::for_each_mut(), but bubbles up errors.

Example
use zerovec::ZeroVec;
use zerovec::ule::AsULE;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

zerovec.try_for_each_mut(|item| {
    *item = item.checked_add(1).ok_or(())?;
    Ok(())   
})?;

assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
assert!(matches!(zerovec, ZeroVec::Owned(_)));

Converts a borrowed ZeroVec to an owned ZeroVec. No-op if already owned.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");
assert!(matches!(zerovec, ZeroVec::Borrowed(_)));

let owned = zerovec.into_owned();
assert!(matches!(owned, ZeroVec::Owned(_)));

Allows the ZeroVec to be mutated by converting it to an owned variant, and producing a mutable vector of ULEs.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");
assert!(matches!(zerovec, ZeroVec::Borrowed(_)));

zerovec.to_mut().push(12_u16.as_unaligned());
assert!(matches!(zerovec, ZeroVec::Owned(_)));

Binary searches a sorted ZeroVec<T> for the given element. For more information, see the primitive function binary_search.

Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> = ZeroVec::parse_byte_slice(bytes).expect("infallible");

assert_eq!(zerovec.binary_search(&281), Ok(1));
assert_eq!(zerovec.binary_search(&282), Err(2));

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

This impl can be made available by enabling the optional serde feature of the zerovec crate

Deserialize this value from the given Serde deserializer. Read more

Creates a ZeroVec::Owned from an iterator of values.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This impl can be made available by enabling the optional serde feature of the zerovec crate

Serialize this value into the given Serde serializer. Read more

This impl can be made available by enabling the optional yoke feature of the zerovec crate

This type MUST be Self with the 'static replaced with 'a, i.e. Self<'a>

This method must cast self between &'a Self<'static> and &'a Self<'a>. Read more

This method must cast self between Self<'static> and Self<'a>. Read more

This method can be used to cast away Self<'a>’s lifetime. Read more

This method must cast self between &'a mut Self<'static> and &'a mut Self<'a>, and pass it to f. Read more

Clone the cart C into a Yokeable struct, which may retain references into C.

The type received by Self::binary_search()

The type returned by Self::get()

The type returned by Self::remove() and Self::replace()

Search for a key in a sorted vector, returns Ok(index) if found, returns Err(insert_index) if not found, where insert_index is the index where it should be inserted to maintain sort order. Read more

Get element at index

Insert an element at index

Remove the element at index (panicking if nonexistant)

Replace the element at index with another one, returning the old element

Push an element to the end of this vector

The length of this vector

Create a new, empty vector

Create a new, empty vector, with given capacity

Remove all elements from the vector

Reserve space for addl additional elements

Check if this vector is in ascending order according to Ts Ord impl

Check if this vector is empty

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The resulting type after obtaining ownership.

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

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.