ZeroVec

Struct ZeroVec 

Source
pub struct ZeroVec<'a, T>
where T: AsULE,
{ /* private fields */ }
Expand description

A zero-copy, byte-aligned 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. For variable-width types like str, see VarZeroVec. zerovec::make_ule may be used to automatically implement AsULE for a type and generate the underlying ULE type.

Typically, the zero-copy equivalent of a Vec<T> will simply be ZeroVec<'a, T>.

Most of the methods on ZeroVec<'a, T> come from its Deref implementation to ZeroSlice<T>.

For creating zero-copy vectors of fixed-size types, see VarZeroVec.

ZeroVec<T> behaves much like Cow, where it can be constructed from owned data (and then mutated!) but can also borrow from some buffer.

§Example

use zerovec::ZeroVec;

// The little-endian bytes correspond to the numbers on the following line.
let nums: &[u16] = &[211, 281, 421, 461];

#[derive(serde::Serialize, serde::Deserialize)]
struct Data<'a> {
    #[serde(borrow)]
    nums: ZeroVec<'a, u16>,
}

// The owned version will allocate
let data = Data {
    nums: ZeroVec::alloc_from_slice(nums),
};
let bincode_bytes =
    bincode::serialize(&data).expect("Serialization should be successful");

// Will deserialize without allocations
let deserialized: Data = bincode::deserialize(&bincode_bytes)
    .expect("Deserialization should be successful");

// This deserializes without allocation!
assert!(!deserialized.nums.is_owned());
assert_eq!(deserialized.nums.get(2), Some(421));
assert_eq!(deserialized.nums, nums);

§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, with some results found in the crate-level documentation.

See the design doc for more details.

Implementations§

Source§

impl<'a, T: AsULE> ZeroVec<'a, T>

Source

pub const fn new() -> Self

Creates a new, borrowed, empty ZeroVec<T>.

§Examples
use zerovec::ZeroVec;

let zv: ZeroVec<u16> = ZeroVec::new();
assert!(zv.is_empty());
Source

pub const fn const_len(&self) -> usize

Same as ZeroSlice::len, which is available through Deref and not const.

Source

pub fn new_owned(vec: Vec<T::ULE>) -> Self

Creates a new owned ZeroVec using an existing allocated backing buffer

If you have a slice of &[T]s, prefer using Self::alloc_from_slice().

Source

pub const fn new_borrowed(slice: &'a [T::ULE]) -> Self

Creates a new borrowed ZeroVec using an existing backing buffer

Source

pub fn with_capacity(capacity: usize) -> Self

Creates a new, owned, empty ZeroVec<T>, with a certain capacity pre-allocated.

Source

pub fn parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError>

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_bytes_to_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_bytes(bytes).expect("infallible");

assert!(!zerovec.is_owned());
assert_eq!(zerovec.get(2), Some(421));
Source

pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self

Uses a &[u8] buffer as a ZeroVec<T> without any verification.

§Safety

bytes need to be an output from ZeroSlice::as_bytes().

Source

pub fn into_bytes(self) -> ZeroVec<'a, u8>

Converts a ZeroVec<T> into a ZeroVec<u8>, retaining the current ownership model.

Note that the length of the ZeroVec may change.

§Examples

Convert a borrowed ZeroVec:

use zerovec::ZeroVec;

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

assert!(!zv_bytes.is_owned());
assert_eq!(zv_bytes.get(0), Some(0xD3));

Convert an owned ZeroVec:

use zerovec::ZeroVec;

let nums: &[u16] = &[211, 281, 421, 461];
let zerovec = ZeroVec::alloc_from_slice(nums);
let zv_bytes = zerovec.into_bytes();

assert!(zv_bytes.is_owned());
assert_eq!(zv_bytes.get(0), Some(0xD3));
Source

pub const fn as_slice(&self) -> &ZeroSlice<T>

Returns this ZeroVec as a ZeroSlice.

To get a reference with a longer lifetime from a borrowed ZeroVec, use ZeroVec::as_maybe_borrowed.

Source

pub fn cast<P>(self) -> ZeroVec<'a, P>
where P: AsULE<ULE = T::ULE>,

Casts a ZeroVec<T> to a compatible ZeroVec<P>.

T and P are compatible if they have the same ULE representation.

If the ULEs of T and P are different types but have the same size, use Self::try_into_converted().

§Examples
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];

let zerovec_u16: ZeroVec<u16> =
    ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec_u16.get(3), Some(32973));

let zerovec_i16: ZeroVec<i16> = zerovec_u16.cast();
assert_eq!(zerovec_i16.get(3), Some(-32563));
Source

pub fn try_into_converted<P: AsULE>(self) -> Result<ZeroVec<'a, P>, UleError>

Converts a ZeroVec<T> into a ZeroVec<P>, retaining the current ownership model.

If T and P have the exact same ULE, use Self::cast().

§Panics

Panics if T::ULE and P::ULE are not the same size.

§Examples

Convert a borrowed ZeroVec:

use zerovec::ZeroVec;

let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
    ZeroVec::parse_bytes(bytes).expect("valid code points");
let zv_u8_3: ZeroVec<[u8; 3]> =
    zv_char.try_into_converted().expect("infallible conversion");

assert!(!zv_u8_3.is_owned());
assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));

Convert an owned ZeroVec:

use zerovec::ZeroVec;

let chars: &[char] = &['🍿', '🙉'];
let zv_char = ZeroVec::alloc_from_slice(chars);
let zv_u8_3: ZeroVec<[u8; 3]> =
    zv_char.try_into_converted().expect("length is divisible");

assert!(zv_u8_3.is_owned());
assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));

If the types are not the same size, we refuse to convert:

use zerovec::ZeroVec;

let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
    ZeroVec::parse_bytes(bytes).expect("valid code points");

// Panics! core::mem::size_of::<char::ULE> != core::mem::size_of::<u16::ULE>
zv_char.try_into_converted::<u16>();

Instead, convert to bytes and then parse:

use zerovec::ZeroVec;

let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
    ZeroVec::parse_bytes(bytes).expect("valid code points");
let zv_u16: ZeroVec<u16> =
    zv_char.into_bytes().try_into_parsed().expect("infallible");

assert!(!zv_u16.is_owned());
assert_eq!(zv_u16.get(0), Some(0xF37F));
Source

pub fn is_owned(&self) -> bool

Check if this type is fully owned

Source

pub fn as_maybe_borrowed(&self) -> Option<&'a ZeroSlice<T>>

If this is a borrowed ZeroVec, return it as a slice that covers its lifetime parameter.

To infallibly get a ZeroSlice with a shorter lifetime, use ZeroVec::as_slice.

Source

pub fn owned_capacity(&self) -> Option<NonZeroUsize>

If the ZeroVec is owned, returns the capacity of the vector.

Otherwise, if the ZeroVec is borrowed, returns None.

§Examples
use zerovec::ZeroVec;

let mut zv = ZeroVec::<u8>::new_borrowed(&[0, 1, 2, 3]);
assert!(!zv.is_owned());
assert_eq!(zv.owned_capacity(), None);

// Convert to owned without appending anything
zv.with_mut(|v| ());
assert!(zv.is_owned());
assert_eq!(zv.owned_capacity(), Some(4.try_into().unwrap()));

// Double the size by appending
zv.with_mut(|v| v.push(0));
assert!(zv.is_owned());
assert_eq!(zv.owned_capacity(), Some(8.try_into().unwrap()));
Source§

impl<'a> ZeroVec<'a, u8>

Source

pub fn try_into_parsed<T: AsULE>(self) -> Result<ZeroVec<'a, T>, UleError>

Converts a ZeroVec<u8> into a ZeroVec<T>, retaining the current ownership model.

Note that the length of the ZeroVec may change.

§Examples

Convert a borrowed ZeroVec:

use zerovec::ZeroVec;

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

assert!(!zerovec.is_owned());
assert_eq!(zerovec.get(0), Some(211));

Convert an owned ZeroVec:

use zerovec::ZeroVec;

let bytes: Vec<u8> = vec![0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zv_bytes = ZeroVec::new_owned(bytes);
let zerovec: ZeroVec<u16> = zv_bytes.try_into_parsed().expect("infallible");

assert!(zerovec.is_owned());
assert_eq!(zerovec.get(0), Some(211));
Source§

impl<'a, T> ZeroVec<'a, T>
where T: AsULE,

Source

pub fn alloc_from_slice(other: &[T]) -> Self

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::alloc_from_slice(nums);

assert!(zerovec.is_owned());
assert_eq!(bytes, zerovec.as_bytes());
Source

pub fn to_vec(&self) -> Vec<T>

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

§Example
use zerovec::ZeroVec;

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

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

impl<'a, T> ZeroVec<'a, T>
where T: EqULE,

Source

pub fn try_from_slice(slice: &'a [T]) -> Option<Self>

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!(!zerovec.is_owned());
    assert_eq!(bytes, zerovec.as_bytes());
}
Source

pub fn from_slice_or_alloc(slice: &'a [T]) -> Self

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_or_alloc(nums);

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

impl<'a, T> ZeroVec<'a, T>
where T: AsULE,

Source

pub fn for_each_mut(&mut self, f: impl FnMut(&mut T))

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

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

§Example
use zerovec::ZeroVec;

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

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

assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
assert!(zerovec.is_owned());
Source

pub fn try_for_each_mut<E>( &mut self, f: impl FnMut(&mut T) -> Result<(), E>, ) -> Result<(), E>

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

§Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
    ZeroVec::parse_bytes(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!(zerovec.is_owned());
Source

pub fn into_owned(self) -> ZeroVec<'static, T>

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_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());

let owned = zerovec.into_owned();
assert!(owned.is_owned());
Source

pub fn with_mut<R>(&mut self, f: impl FnOnce(&mut Vec<T::ULE>) -> R) -> R

Allows the ZeroVec to be mutated by converting it to an owned variant, and producing a mutable vector of ULEs. If you only need a mutable slice, consider using Self::to_mut_slice() instead.

§Example
use zerovec::ZeroVec;

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

zerovec.with_mut(|v| v.push(12_u16.to_unaligned()));
assert!(zerovec.is_owned());
Source

pub fn to_mut_slice(&mut self) -> &mut [T::ULE]

Allows the ZeroVec to be mutated by converting it to an owned variant (if necessary) and returning a slice to its backing buffer. Self::with_mut() allows for mutation of the vector itself.

§Example
use zerovec::ZeroVec;

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

zerovec.to_mut_slice()[1] = 5u16.to_unaligned();
assert!(zerovec.is_owned());
Source

pub fn clear(&mut self)

Remove all elements from this ZeroVec and reset it to an empty borrowed state.

Source

pub fn take_first(&mut self) -> Option<T>

Removes the first element of the ZeroVec. The ZeroVec remains in the same borrowed or owned state.

§Examples
use zerovec::ZeroVec;

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

let first = zerovec.take_first().unwrap();
assert_eq!(first, 0x00D3);
assert!(!zerovec.is_owned());

let mut zerovec = zerovec.into_owned();
assert!(zerovec.is_owned());
let first = zerovec.take_first().unwrap();
assert_eq!(first, 0x0119);
assert!(zerovec.is_owned());
Source

pub fn take_last(&mut self) -> Option<T>

Removes the last element of the ZeroVec. The ZeroVec remains in the same borrowed or owned state.

§Examples
use zerovec::ZeroVec;

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

let last = zerovec.take_last().unwrap();
assert_eq!(last, 0x01CD);
assert!(!zerovec.is_owned());

let mut zerovec = zerovec.into_owned();
assert!(zerovec.is_owned());
let last = zerovec.take_last().unwrap();
assert_eq!(last, 0x01A5);
assert!(zerovec.is_owned());
Source

pub fn into_cow(self) -> Cow<'a, [T::ULE]>

Converts the type into a Cow<'a, [T::ULE]>, which is the logical equivalent of this type’s internal representation

Source

pub fn truncated(self, max: usize) -> Self

Truncates this vector to min(self.len(), max).

Methods from Deref<Target = ZeroSlice<T>>§

Source

pub fn as_zerovec(&self) -> ZeroVec<'_, T>

Get this ZeroSlice as a borrowed ZeroVec

ZeroSlice does not have most of the methods that ZeroVec does, so it is recommended to convert it to a ZeroVec before doing anything.

Source

pub fn as_bytes(&self) -> &[u8]

Returns this slice 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, 0x80];
let nums: &[u16] = &[211, 281, 421, 32973];

let zerovec = ZeroVec::alloc_from_slice(nums);

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

pub fn as_ule_slice(&self) -> &[T::ULE]

Dereferences this slice as &[T::ULE].

Source

pub fn len(&self) -> usize

Returns the number of elements in this slice.

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

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

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

pub fn is_empty(&self) -> bool

Returns whether this slice is empty.

§Example
use zerovec::ZeroVec;

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

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

pub fn get(&self, index: usize) -> Option<T>

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, 0x80];
let zerovec: ZeroVec<u16> =
    ZeroVec::parse_bytes(bytes).expect("infallible");

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

pub fn get_as_array<const N: usize>(&self) -> Option<[T; N]>

Gets the entire slice as an array of length N. Returns None if the slice does not have exactly N elements.

§Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
    ZeroVec::parse_bytes(bytes).expect("infallible");
let array: [u16; 4] =
    zerovec.get_as_array().expect("should be 4 items in array");

assert_eq!(array[2], 421);
Source

pub fn get_subslice(&self, range: Range<usize>) -> Option<&ZeroSlice<T>>

Gets a subslice of elements within a certain range. Returns None if the range is out of bounds of this ZeroSlice.

§Example
use zerovec::ZeroVec;

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

assert_eq!(
    zerovec.get_subslice(1..3),
    Some(&*ZeroVec::from_slice_or_alloc(&[0x0119, 0x01A5]))
);
assert_eq!(zerovec.get_subslice(3..5), None);
Source

pub fn get_ule_ref(&self, index: usize) -> Option<&T::ULE>

Get a borrowed reference to the underlying ULE type at a specified index.

Prefer Self::get() over this method where possible since working directly with ULE types is less ergonomic

Source

pub fn cast<P>(&self) -> &ZeroSlice<P>
where P: AsULE<ULE = T::ULE>,

Casts a ZeroSlice<T> to a compatible ZeroSlice<P>.

T and P are compatible if they have the same ULE representation.

If the ULEs of T and P are different, use Self::try_as_converted().

§Examples
use zerovec::ZeroSlice;

const BYTES: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
const ZS_U16: &ZeroSlice<u16> = {
    match ZeroSlice::<u16>::try_from_bytes(BYTES) {
        Ok(s) => s,
        Err(_) => unreachable!(),
    }
};

let zs_i16: &ZeroSlice<i16> = ZS_U16.cast();

assert_eq!(ZS_U16.get(3), Some(32973));
assert_eq!(zs_i16.get(3), Some(-32563));
Source

pub fn try_as_converted<P: AsULE>(&self) -> Result<&ZeroSlice<P>, UleError>

Converts a &ZeroSlice<T> into a &ZeroSlice<P>.

The resulting slice will have the same length as the original slice if and only if T::ULE and P::ULE are the same size.

If T and P have the exact same ULE, use Self::cast().

§Examples
use zerovec::ZeroSlice;

const BYTES: &[u8] = &[0x7F, 0xF3, 0x01, 0x00, 0x49, 0xF6, 0x01, 0x00];
const ZS_U32: &ZeroSlice<u32> = {
    match ZeroSlice::<u32>::try_from_bytes(BYTES) {
        Ok(s) => s,
        Err(_) => unreachable!(),
    }
};

let zs_u8_4: &ZeroSlice<[u8; 4]> =
    ZS_U32.try_as_converted().expect("valid code points");

assert_eq!(ZS_U32.get(0), Some(127871));
assert_eq!(zs_u8_4.get(0), Some([0x7F, 0xF3, 0x01, 0x00]));
Source

pub fn first(&self) -> Option<T>

Gets the first element. Returns None if empty.

§Example
use zerovec::ZeroVec;

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

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

pub fn last(&self) -> Option<T>

Gets the last element. Returns None if empty.

§Example
use zerovec::ZeroVec;

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

assert_eq!(zerovec.last(), Some(32973));
Source

pub fn iter<'a>(&'a self) -> ZeroSliceIter<'a, T>

Gets an iterator over the elements.

§Example
use zerovec::ZeroVec;

let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
    ZeroVec::parse_bytes(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(32973));
assert_eq!(it.next(), None);
Source

pub fn split_first(&self) -> Option<(T, &ZeroSlice<T>)>

Returns a tuple with the first element and a subslice of the remaining elements.

§Example
use zerovec::ule::AsULE;
use zerovec::ZeroSlice;

const DATA: &ZeroSlice<u16> =
    ZeroSlice::<u16>::from_ule_slice(&<u16 as AsULE>::ULE::from_array([
        211, 281, 421, 32973,
    ]));
const EXPECTED_VALUE: (u16, &ZeroSlice<u16>) = (
    211,
    ZeroSlice::<u16>::from_ule_slice(&<u16 as AsULE>::ULE::from_array([
        281, 421, 32973,
    ])),
);
assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap());

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, 0x80];
let zerovec: ZeroVec<u16> =
    ZeroVec::parse_bytes(bytes).expect("infallible");

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

pub fn binary_search_by( &self, predicate: impl FnMut(T) -> Ordering, ) -> Result<usize, usize>

Binary searches a sorted ZeroVec<T> based on a given predicate. For more information, see the primitive function binary_search_by.

§Example
use zerovec::ZeroVec;

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

assert_eq!(zerovec.binary_search_by(|x| x.cmp(&281)), Ok(1));
assert_eq!(zerovec.binary_search_by(|x| x.cmp(&282)), Err(2));

Trait Implementations§

Source§

impl<'a, T: AsULE> AsRef<[<T as AsULE>::ULE]> for ZeroVec<'a, T>

Source§

fn as_ref(&self) -> &[T::ULE]

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<'a, T: AsULE> AsRef<ZeroSlice<T>> for ZeroVec<'a, T>

Source§

fn as_ref(&self) -> &ZeroSlice<T>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<'a, T: AsULE> Clone for ZeroVec<'a, T>

Source§

fn clone(&self) -> Self

Returns a duplicate 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<T> Debug for ZeroVec<'_, T>
where T: AsULE + Debug,

Source§

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

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

impl<'a, T: AsULE> Default for ZeroVec<'a, T>

Source§

fn default() -> Self

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

impl<'a, T: AsULE> Deref for ZeroVec<'a, T>

Source§

type Target = ZeroSlice<T>

The resulting type after dereferencing.
Source§

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

Dereferences the value.
Source§

impl<T> EncodeAsVarULE<ZeroSlice<T>> for ZeroVec<'_, T>
where T: AsULE + 'static,

Source§

fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R

Calls cb with a piecewise list of byte slices that when concatenated produce the memory pattern of the corresponding instance of T. Read more
Source§

fn encode_var_ule_len(&self) -> usize

Return the length, in bytes, of the corresponding VarULE type
Source§

fn encode_var_ule_write(&self, dst: &mut [u8])

Write the corresponding VarULE type to the dst buffer. dst should be the size of Self::encode_var_ule_len()
Source§

impl<'a, T: AsULE> From<&'a [<T as AsULE>::ULE]> for ZeroVec<'a, T>

Source§

fn from(other: &'a [T::ULE]) -> Self

Converts to this type from the input type.
Source§

impl<'a, T: AsULE> From<Vec<<T as AsULE>::ULE>> for ZeroVec<'a, T>

Source§

fn from(other: Vec<T::ULE>) -> Self

Converts to this type from the input type.
Source§

impl<T: AsULE> FromIterator<T> for ZeroVec<'_, T>

Source§

fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item = T>,

Creates an owned ZeroVec from an iterator of values.

Source§

impl<'a, T> MutableZeroVecLike<'a, T> for ZeroVec<'a, T>
where T: AsULE + Copy + 'static,

Source§

type OwnedType = T

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

fn zvl_insert(&mut self, index: usize, value: &T)

Insert an element at index
Source§

fn zvl_remove(&mut self, index: usize) -> T

Remove the element at index (panicking if nonexistant)
Source§

fn zvl_replace(&mut self, index: usize, value: &T) -> T

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

fn zvl_push(&mut self, value: &T)

Push an element to the end of this vector
Source§

fn zvl_with_capacity(cap: usize) -> Self

Create a new, empty vector, with given capacity
Source§

fn zvl_clear(&mut self)

Remove all elements from the vector
Source§

fn zvl_reserve(&mut self, addl: usize)

Reserve space for addl additional elements
Source§

fn owned_as_t(o: &Self::OwnedType) -> &T

Convert an owned value to a borrowed T
Source§

fn zvl_from_borrowed(b: &'a ZeroSlice<T>) -> Self

Construct from the borrowed version of the type Read more
Source§

fn zvl_as_borrowed_inner(&self) -> Option<&'a ZeroSlice<T>>

Extract the inner borrowed variant if possible. Returns None if the data is owned. Read more
Source§

fn zvl_permute(&mut self, permutation: &mut [usize])

Applies the permutation such that before.zvl_get(permutation[i]) == after.zvl_get(i). Read more
Source§

impl<'a, T: AsULE + Ord> Ord for ZeroVec<'a, T>

Source§

fn cmp(&self, other: &Self) -> 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,

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

impl<T> PartialEq<&[T]> for ZeroVec<'_, T>
where T: AsULE + PartialEq,

Source§

fn eq(&self, other: &&[T]) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, const N: usize> PartialEq<[T; N]> for ZeroVec<'_, T>
where T: AsULE + PartialEq,

Source§

fn eq(&self, other: &[T; N]) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, T> PartialEq<ZeroSlice<T>> for ZeroVec<'a, T>
where T: AsULE + PartialEq,

Source§

fn eq(&self, other: &ZeroSlice<T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, T> PartialEq<ZeroVec<'a, T>> for ZeroSlice<T>
where T: AsULE + PartialEq,

Source§

fn eq(&self, other: &ZeroVec<'a, T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, 'b, T> PartialEq<ZeroVec<'b, T>> for ZeroVec<'a, T>
where T: AsULE + PartialEq,

Source§

fn eq(&self, other: &ZeroVec<'b, T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroVec<'a, T>

Source§

fn partial_cmp(&self, other: &Self) -> 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

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

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

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

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<'a, T: 'static + AsULE> Yokeable<'a> for ZeroVec<'static, T>

This impl requires enabling the optional yoke Cargo feature of the zerovec crate

Source§

type Output = ZeroVec<'a, T>

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

fn transform(&'a self) -> &'a Self::Output

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

fn transform_owned(self) -> Self::Output

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

unsafe fn make(from: Self::Output) -> Self

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

fn transform_mut<F>(&'a mut self, f: F)
where F: 'static + for<'b> FnOnce(&'b mut Self::Output),

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

impl<'zf, T> ZeroFrom<'zf, ZeroSlice<T>> for ZeroVec<'zf, T>
where T: 'static + AsULE,

Source§

fn zero_from(other: &'zf ZeroSlice<T>) -> Self

Clone the other C into a struct that may retain references into C.
Source§

impl<'zf, T> ZeroFrom<'zf, ZeroVec<'_, T>> for ZeroVec<'zf, T>
where T: 'static + AsULE,

Source§

fn zero_from(other: &'zf ZeroVec<'_, T>) -> Self

Clone the other C into a struct that may retain references into C.
Source§

impl<'a, T> ZeroVecLike<T> for ZeroVec<'a, T>
where T: 'a + AsULE + Copy,

Source§

type GetType = <T as AsULE>::ULE

The type returned by Self::get()
Source§

type SliceVariant = ZeroSlice<T>

A fully borrowed version of this
Source§

fn zvl_new_borrowed() -> &'static Self::SliceVariant

Create a new, empty borrowed variant
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.
Source§

fn zvl_binary_search_in_range( &self, k: &T, range: Range<usize>, ) -> Option<Result<usize, usize>>
where T: Ord,

Search for a key within a certain range in a sorted vector. Returns None if the range is out of bounds, and Ok or Err in the same way as zvl_binary_search. Indices are returned relative to the start of the range.
Source§

fn zvl_binary_search_by( &self, predicate: impl FnMut(&T) -> Ordering, ) -> Result<usize, usize>

Search for a key in a sorted vector by a predicate, 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.
Source§

fn zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>

Search for a key within a certain range in a sorted vector by a predicate. Returns None if the range is out of bounds, and Ok or Err in the same way as zvl_binary_search. Indices are returned relative to the start of the range.
Source§

fn zvl_get(&self, index: usize) -> Option<&T::ULE>

Get element at index
Source§

fn zvl_len(&self) -> usize

The length of this vector
Source§

fn zvl_as_borrowed(&self) -> &ZeroSlice<T>

Construct a borrowed variant by borrowing from &self. Read more
Source§

fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R

Obtain a reference to T, passed to a closure Read more
Source§

fn zvl_is_ascending(&self) -> bool
where T: Ord,

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

fn zvl_is_empty(&self) -> bool

Check if this vector is empty
Source§

fn t_cmp_get(t: &T, g: &Self::GetType) -> Ordering
where T: Ord,

Compare this type with a Self::GetType. This must produce the same result as if g were converted to Self
Source§

fn get_cmp_get(a: &Self::GetType, b: &Self::GetType) -> Ordering
where T: Ord,

Compare two values of Self::GetType. This must produce the same result as if both a and b were converted to Self
Source§

impl<T> Eq for ZeroVec<'_, T>
where T: AsULE + Eq,

Source§

impl<'a, T: AsULE> Send for ZeroVec<'a, T>
where T::ULE: Send + Sync,

Source§

impl<'a, T: AsULE> Sync for ZeroVec<'a, T>
where T::ULE: Sync,

Auto Trait Implementations§

§

impl<'a, T> Freeze for ZeroVec<'a, T>

§

impl<'a, T> RefUnwindSafe for ZeroVec<'a, T>
where <T as AsULE>::ULE: RefUnwindSafe,

§

impl<'a, T> Unpin for ZeroVec<'a, T>
where <T as AsULE>::ULE: Unpin,

§

impl<'a, T> UnwindSafe for ZeroVec<'a, T>
where <T as AsULE>::ULE: UnwindSafe + RefUnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

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

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 24 bytes