Struct zerovec::ZeroVec

source ·
pub struct ZeroVec<'a, T>
where T: AsULE,
{ vector: EyepatchHackVector<T::ULE>, marker: PhantomData<(Vec<T::ULE>, &'a [T::ULE])>, }
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.

Fields§

§vector: EyepatchHackVector<T::ULE>§marker: PhantomData<(Vec<T::ULE>, &'a [T::ULE])>

Marker type, signalling variance and dropck behavior by containing all potential types this type represents

Implementations§

source§

impl<'a, T> ZeroVec<'a, T>
where T: AsULE + ?Sized,

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_byte_slice(bytes: &'a [u8]) -> Result<Self, ZeroVecError>

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!(!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_byte_slice(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 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_byte_slice(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>, ZeroVecError>

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_byte_slice(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_byte_slice(bytes).expect("valid code points");

// Panics! mem::size_of::<char::ULE> != 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_byte_slice(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

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

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_byte_slice(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_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!(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_byte_slice(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_byte_slice(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_byte_slice(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_byte_slice(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_byte_slice(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

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

let emptyvec: ZeroVec<u16> =
    ZeroVec::parse_byte_slice(&[]).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_byte_slice(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_byte_slice(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_byte_slice(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>, ZeroVecError>

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

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

pub fn iter( &self, ) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator<Item = 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_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(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_byte_slice(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_byte_slice(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 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<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>

§

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,

§

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

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

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

source§

fn eq(&self, other: &&[T]) -> 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<T, const N: usize> PartialEq<[T; N]> for ZeroVec<'_, T>
where T: AsULE + PartialEq + ?Sized,

source§

fn eq(&self, other: &[T; N]) -> 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<'a, T> PartialEq<ZeroSlice<T>> for ZeroVec<'a, T>
where T: AsULE + PartialEq,

source§

fn eq(&self, other: &ZeroSlice<T>) -> 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<'a, T> PartialEq<ZeroVec<'a, T>> for ZeroSlice<T>
where T: AsULE + PartialEq,

source§

fn eq(&self, other: &ZeroVec<'a, T>) -> 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<'a, 'b, T> PartialEq<ZeroVec<'b, T>> for ZeroVec<'a, T>
where T: AsULE + PartialEq + ?Sized,

source§

fn eq(&self, other: &ZeroVec<'b, T>) -> 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<'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

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<'a, T: 'static + AsULE + ?Sized> Yokeable<'a> for ZeroVec<'static, T>

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

§

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 + ?Sized,

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 + ?Sized,

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,

§

type GetType = <T as AsULE>::ULE

The type returned by Self::get()
§

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_empty(&self) -> bool

Check if this vector is empty
source§

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

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: RefUnwindSafe + UnwindSafe,

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

§

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

§

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> ErasedDestructor for T
where T: 'static,