use core::cmp::Ordering; use core::fmt::{Debug, Formatter, Result}; use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator}; #[cfg(nightly)] use core::iter::TrustedLen; use core::marker::PhantomData; use core::mem::{align_of, size_of}; use core::str::from_utf8_unchecked;
impl<'a, T: 'a> Default for Vector<'a, T> { fn default() -> Self { // Static, length 0 vector. // Note that derived default causes UB due to issues in read_scalar_at /facepalm. Self(&[0; core::mem::size_of::<UOffsetT>()], 0, Default::default())
}
}
impl<'a, T> Debug for Vector<'a, T> where
T: 'a + Follow<'a>,
<T as Follow<'a>>::Inner: Debug,
{ fn fmt(&self, f: &mut Formatter) -> Result {
f.debug_list().entries(self.iter()).finish()
}
}
// We cannot use derive for these two impls, as it would only implement Copy // and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>` // can always be copied, no matter that `T` you have. impl<'a, T> Copy for Vector<'a, T> {}
impl<'a, T: 'a> Vector<'a, T> { /// # Safety /// /// `buf` contains a valid vector at `loc` consisting of /// /// - UOffsetT element count /// - Consecutive list of `T` elements #[inline(always)] pubunsafefn new(buf: &'a [u8], loc: usize) -> Self {
Vector(buf, loc, PhantomData)
}
#[inline(always)] pubfn len(&self) -> usize { // Safety: // Valid vector at time of construction starting with UOffsetT element count unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
}
/// # Safety /// /// `buf` must contain a value of T at `loc` and have alignment of 1 pubunsafefn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
assert_eq!(align_of::<T>(), 1); let sz = size_of::<T>(); let buf = &buf[loc..loc + sz]; let ptr = buf.as_ptr() as *const T; // SAFETY // buf contains a value at loc of type T and T has no alignment requirements
&*ptr
}
impl<'a> Follow<'a> for &'a str { type Inner = &'a str; unsafefn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let len = read_scalar_at::<UOffsetT>(buf, loc) as usize; let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
from_utf8_unchecked(slice)
}
}
impl<'a> Follow<'a> for &'a [u8] { type Inner = &'a [u8]; unsafefn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let len = read_scalar_at::<UOffsetT>(buf, loc) as usize;
&buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]
}
}
/// Implement Follow for all possible Vectors that have Follow-able elements. impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> { type Inner = Vector<'a, T>; unsafefn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Vector::new(buf, loc)
}
}
/// An iterator over a `Vector`. #[derive(Debug)] pubstruct VectorIter<'a, T: 'a> {
buf: &'a [u8],
loc: usize,
remaining: usize,
phantom: PhantomData<T>,
}
impl<'a, T: 'a> VectorIter<'a, T> { #[inline] pubfn from_vector(inner: Vector<'a, T>) -> Self {
VectorIter {
buf: inner.0, // inner.1 is the location of the data for the vector. // The first SIZE_UOFFSET bytes is the length. We skip // that to get to the actual vector content.
loc: inner.1 + SIZE_UOFFSET,
remaining: inner.len(),
phantom: PhantomData,
}
}
/// Creates a new `VectorIter` from the provided slice /// /// # Safety /// /// buf must contain a contiguous sequence of `items_num` values of `T` /// #[inline] pubunsafefn from_slice(buf: &'a [u8], items_num: usize) -> Self {
VectorIter { buf, loc: 0, remaining: items_num, phantom: PhantomData }
}
}
ifself.remaining == 0 {
None
} else { // Safety: // VectorIter can only be created from a contiguous sequence of `items_num` // And remaining is initialized to `items_num` let result = unsafe { T::follow(self.buf, self.loc) }; self.loc += sz; self.remaining -= 1;
Some(result)
}
}
// Note that this might overflow, but that is okay because // in that case self.remaining will have been set to zero. self.loc = self.loc.wrapping_add(sz * n);
ifself.remaining == 0 {
None
} else { self.remaining -= 1; // Safety: // VectorIter can only be created from a contiguous sequence of `items_num` // And remaining is initialized to `items_num`
Some(unsafe { T::follow(self.buf, self.loc + sz * self.remaining) })
}
}