use core::{fmt, hash, iter::FromIterator, mem::MaybeUninit, ops, ptr, slice}; use generic_array::{ArrayLength, GenericArray}; use hash32; impl crate::i::Vec { /// `Vec` `const` constructor; wrap the returned value in [`Vec`](../struct.Vec.html) pub const fn new() -> Self { Self { buffer: MaybeUninit::uninit(), len: 0, } } } impl crate::i::Vec> where N: ArrayLength, { pub(crate) fn as_slice(&self) -> &[T] { // NOTE(unsafe) avoid bound checks in the slicing operation // &buffer[..self.len] unsafe { slice::from_raw_parts(self.buffer.as_ptr() as *const T, self.len) } } pub(crate) fn as_mut_slice(&mut self) -> &mut [T] { // NOTE(unsafe) avoid bound checks in the slicing operation // &mut buffer[..len] unsafe { slice::from_raw_parts_mut(self.buffer.as_mut_ptr() as *mut T, self.len) } } pub(crate) fn capacity(&self) -> usize { N::to_usize() } pub(crate) fn clear(&mut self) { self.truncate(0); } pub(crate) fn clone(&self) -> Self where T: Clone, { let mut new = Self::new(); new.extend_from_slice(self.as_slice()).unwrap(); new } pub(crate) fn extend(&mut self, iter: I) where I: IntoIterator, { for elem in iter { self.push(elem).ok().unwrap() } } pub(crate) fn extend_from_slice(&mut self, other: &[T]) -> Result<(), ()> where T: Clone, { if self.len + other.len() > self.capacity() { // won't fit in the `Vec`; don't modify anything and return an error Err(()) } else { for elem in other { unsafe { self.push_unchecked(elem.clone()); } } Ok(()) } } pub(crate) fn is_full(&self) -> bool { self.len == self.capacity() } pub(crate) unsafe fn pop_unchecked(&mut self) -> T { debug_assert!(!self.as_slice().is_empty()); self.len -= 1; (self.buffer.as_ptr() as *const T).add(self.len).read() } pub(crate) fn push(&mut self, item: T) -> Result<(), T> { if self.len < self.capacity() { unsafe { self.push_unchecked(item) } Ok(()) } else { Err(item) } } pub(crate) unsafe fn push_unchecked(&mut self, item: T) { // NOTE(ptr::write) the memory slot that we are about to write to is uninitialized. We // use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory (self.buffer.as_mut_ptr() as *mut T) .add(self.len) .write(item); self.len += 1; } unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T { let length = self.len; debug_assert!(index < length); ptr::swap( self.as_mut_slice().get_unchecked_mut(index), self.as_mut_slice().get_unchecked_mut(length - 1), ); self.pop_unchecked() } pub(crate) fn swap_remove(&mut self, index: usize) -> T { assert!(index < self.len); unsafe { self.swap_remove_unchecked(index) } } pub(crate) fn truncate(&mut self, len: usize) { unsafe { // drop any extra elements while len < self.len { // decrement len before the drop_in_place(), so a panic on Drop // doesn't re-drop the just-failed value. self.len -= 1; let len = self.len; ptr::drop_in_place(self.as_mut_slice().get_unchecked_mut(len)); } } } } /// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// // A vector with a fixed capacity of 8 elements allocated on the stack /// let mut vec = Vec::<_, U8>::new(); /// vec.push(1); /// vec.push(2); /// /// assert_eq!(vec.len(), 2); /// assert_eq!(vec[0], 1); /// /// assert_eq!(vec.pop(), Some(2)); /// assert_eq!(vec.len(), 1); /// /// vec[0] = 7; /// assert_eq!(vec[0], 7); /// /// vec.extend([1, 2, 3].iter().cloned()); /// /// for x in &vec { /// println!("{}", x); /// } /// assert_eq!(vec, [7, 1, 2, 3]); /// ``` pub struct Vec(#[doc(hidden)] pub crate::i::Vec>) where N: ArrayLength; impl Clone for Vec where N: ArrayLength, T: Clone, { fn clone(&self) -> Self { Vec(self.0.clone()) } } impl Vec where N: ArrayLength, { /* Constructors */ /// Constructs a new, empty vector with a fixed capacity of `N` /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// // allocate the vector on the stack /// let mut x: Vec = Vec::new(); /// /// // allocate the vector in a static variable /// static mut X: Vec = Vec(heapless::i::Vec::new()); /// ``` pub fn new() -> Self { Vec(crate::i::Vec::new()) } /// Constructs a new vector with a fixed capacity of `N` and fills it /// with the provided slice. /// /// This is equivalent to the following code: /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// let mut v: Vec = Vec::new(); /// v.extend_from_slice(&[1, 2, 3]).unwrap(); /// ``` #[inline] pub fn from_slice(other: &[T]) -> Result where T: Clone, { let mut v = Vec::new(); v.extend_from_slice(other)?; Ok(v) } /* Public API */ /// Returns the maximum number of elements the vector can hold pub fn capacity(&self) -> usize { self.0.capacity() } /// Clears the vector, removing all values. pub fn clear(&mut self) { self.0.clear() } /// Clones and appends all elements in a slice to the `Vec`. /// /// Iterates over the slice `other`, clones each element, and then appends /// it to this `Vec`. The `other` vector is traversed in-order. /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// let mut vec = Vec::::new(); /// vec.push(1).unwrap(); /// vec.extend_from_slice(&[2, 3, 4]).unwrap(); /// assert_eq!(*vec, [1, 2, 3, 4]); /// ``` pub fn extend_from_slice(&mut self, other: &[T]) -> Result<(), ()> where T: Clone, { self.0.extend_from_slice(other) } /// Removes the last element from a vector and return it, or `None` if it's empty pub fn pop(&mut self) -> Option { if self.0.len != 0 { Some(unsafe { self.0.pop_unchecked() }) } else { None } } /// Appends an `item` to the back of the collection /// /// Returns back the `item` if the vector is full pub fn push(&mut self, item: T) -> Result<(), T> { self.0.push(item) } pub(crate) unsafe fn push_unchecked(&mut self, item: T) { self.0.push_unchecked(item) } /// Shortens the vector, keeping the first `len` elements and dropping the rest. pub fn truncate(&mut self, len: usize) { unsafe { // drop any extra elements while len < self.len() { // decrement len before the drop_in_place(), so a panic on Drop // doesn't re-drop the just-failed value. self.0.len -= 1; let len = self.len(); ptr::drop_in_place(self.get_unchecked_mut(len)); } } } /// Resizes the Vec in-place so that len is equal to new_len. /// /// If new_len is greater than len, the Vec is extended by the /// difference, with each additional slot filled with value. If /// new_len is less than len, the Vec is simply truncated. /// /// See also [`resize_default`](struct.Vec.html#method.resize_default). pub fn resize(&mut self, new_len: usize, value: T) -> Result<(), ()> where T: Clone, { if new_len > self.capacity() { return Err(()); } if new_len > self.len() { while self.len() < new_len { self.push(value.clone()).ok(); } } else { self.truncate(new_len); } Ok(()) } /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the /// difference, with each additional slot filled with `Default::default()`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// /// See also [`resize`](struct.Vec.html#method.resize). pub fn resize_default(&mut self, new_len: usize) -> Result<(), ()> where T: Clone + Default, { self.resize(new_len, T::default()) } /// Forces the length of the vector to `new_len`. /// /// This is a low-level operation that maintains none of the normal /// invariants of the type. Normally changing the length of a vector /// is done using one of the safe operations instead, such as /// [`truncate`], [`resize`], [`extend`], or [`clear`]. /// /// [`truncate`]: #method.truncate /// [`resize`]: #method.resize /// [`extend`]: https://doc.rust-lang.org/stable/core/iter/trait.Extend.html#tymethod.extend /// [`clear`]: #method.clear /// /// # Safety /// /// - `new_len` must be less than or equal to [`capacity()`]. /// - The elements at `old_len..new_len` must be initialized. /// /// [`capacity()`]: #method.capacity /// /// # Examples /// /// This method can be useful for situations in which the vector /// is serving as a buffer for other code, particularly over FFI: /// /// ```no_run /// # #![allow(dead_code)] /// use heapless::Vec; /// use heapless::consts::*; /// /// # // This is just a minimal skeleton for the doc example; /// # // don't use this as a starting point for a real library. /// # pub struct StreamWrapper { strm: *mut core::ffi::c_void } /// # const Z_OK: i32 = 0; /// # extern "C" { /// # fn deflateGetDictionary( /// # strm: *mut core::ffi::c_void, /// # dictionary: *mut u8, /// # dictLength: *mut usize, /// # ) -> i32; /// # } /// # impl StreamWrapper { /// pub fn get_dictionary(&self) -> Option> { /// // Per the FFI method's docs, "32768 bytes is always enough". /// let mut dict = Vec::new(); /// let mut dict_length = 0; /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: /// // 1. `dict_length` elements were initialized. /// // 2. `dict_length` <= the capacity (32_768) /// // which makes `set_len` safe to call. /// unsafe { /// // Make the FFI call... /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); /// if r == Z_OK { /// // ...and update the length to what was initialized. /// dict.set_len(dict_length); /// Some(dict) /// } else { /// None /// } /// } /// } /// # } /// ``` /// /// While the following example is sound, there is a memory leak since /// the inner vectors were not freed prior to the `set_len` call: /// /// ``` /// use core::iter::FromIterator; /// use heapless::Vec; /// use heapless::consts::*; /// /// let mut vec = Vec::, U3>::from_iter( /// [ /// Vec::from_iter([1, 0, 0].iter().cloned()), /// Vec::from_iter([0, 1, 0].iter().cloned()), /// Vec::from_iter([0, 0, 1].iter().cloned()), /// ] /// .iter() /// .cloned() /// ); /// // SAFETY: /// // 1. `old_len..0` is empty so no elements need to be initialized. /// // 2. `0 <= capacity` always holds whatever `capacity` is. /// unsafe { /// vec.set_len(0); /// } /// ``` /// /// Normally, here, one would use [`clear`] instead to correctly drop /// the contents and thus not leak memory. pub unsafe fn set_len(&mut self, new_len: usize) { debug_assert!(new_len <= self.capacity()); self.0.len = new_len } /// Removes an element from the vector and returns it. /// /// The removed element is replaced by the last element of the vector. /// /// This does not preserve ordering, but is O(1). /// /// # Panics /// /// Panics if `index` is out of bounds. /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// let mut v: Vec<_, U8> = Vec::new(); /// v.push("foo").unwrap(); /// v.push("bar").unwrap(); /// v.push("baz").unwrap(); /// v.push("qux").unwrap(); /// /// assert_eq!(v.swap_remove(1), "bar"); /// assert_eq!(&*v, ["foo", "qux", "baz"]); /// /// assert_eq!(v.swap_remove(0), "foo"); /// assert_eq!(&*v, ["baz", "qux"]); /// ``` pub fn swap_remove(&mut self, index: usize) -> T { self.0.swap_remove(index) } pub(crate) unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T { self.0.swap_remove_unchecked(index) } pub(crate) fn is_full(&self) -> bool { self.0.is_full() } /// Returns `true` if `needle` is a prefix of the Vec. /// /// Always returns `true` if `needle` is an empty slice. /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// let v: Vec<_, U8> = Vec::from_slice(b"abc").unwrap(); /// assert_eq!(v.starts_with(b""), true); /// assert_eq!(v.starts_with(b"ab"), true); /// assert_eq!(v.starts_with(b"bc"), false); /// ``` #[inline] pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq, { let n = needle.len(); self.len() >= n && needle == &self[..n] } /// Returns `true` if `needle` is a suffix of the Vec. /// /// Always returns `true` if `needle` is an empty slice. /// /// # Examples /// /// ``` /// use heapless::Vec; /// use heapless::consts::*; /// /// let v: Vec<_, U8> = Vec::from_slice(b"abc").unwrap(); /// assert_eq!(v.ends_with(b""), true); /// assert_eq!(v.ends_with(b"ab"), false); /// assert_eq!(v.ends_with(b"bc"), true); /// ``` #[inline] pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq, { let (v, n) = (self.len(), needle.len()); v >= n && needle == &self[v - n..] } } impl Default for Vec where N: ArrayLength, { fn default() -> Self { Self::new() } } impl fmt::Debug for Vec where T: fmt::Debug, N: ArrayLength, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { <[T] as fmt::Debug>::fmt(self, f) } } impl fmt::Write for Vec where N: ArrayLength, { fn write_str(&mut self, s: &str) -> fmt::Result { match self.extend_from_slice(s.as_bytes()) { Ok(()) => Ok(()), Err(_) => Err(fmt::Error), } } } impl Drop for Vec where N: ArrayLength, { fn drop(&mut self) { unsafe { ptr::drop_in_place(&mut self[..]) } } } impl Extend for Vec where N: ArrayLength, { fn extend(&mut self, iter: I) where I: IntoIterator, { self.0.extend(iter) } } impl<'a, T, N> Extend<&'a T> for Vec where T: 'a + Copy, N: ArrayLength, { fn extend(&mut self, iter: I) where I: IntoIterator, { self.extend(iter.into_iter().cloned()) } } impl hash::Hash for Vec where T: core::hash::Hash, N: ArrayLength, { fn hash(&self, state: &mut H) { <[T] as hash::Hash>::hash(self, state) } } impl hash32::Hash for Vec where T: hash32::Hash, N: ArrayLength, { fn hash(&self, state: &mut H) { <[T] as hash32::Hash>::hash(self, state) } } impl<'a, T, N> IntoIterator for &'a Vec where N: ArrayLength, { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, T, N> IntoIterator for &'a mut Vec where N: ArrayLength, { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl FromIterator for Vec where N: ArrayLength, { fn from_iter(iter: I) -> Self where I: IntoIterator, { let mut vec = Vec::new(); for i in iter { vec.push(i).ok().expect("Vec::from_iter overflow"); } vec } } /// An iterator that moves out of an [`Vec`][`Vec`]. /// /// This struct is created by calling the `into_iter` method on [`Vec`][`Vec`]. /// /// [`Vec`]: (https://doc.rust-lang.org/std/vec/struct.Vec.html) /// pub struct IntoIter where N: ArrayLength, { vec: Vec, next: usize, } impl Iterator for IntoIter where N: ArrayLength, { type Item = T; fn next(&mut self) -> Option { if self.next < self.vec.len() { let item = unsafe { (self.vec.0.buffer.as_ptr() as *const T) .add(self.next) .read() }; self.next += 1; Some(item) } else { None } } } impl Clone for IntoIter where T: Clone, N: ArrayLength, { fn clone(&self) -> Self { Self { vec: self.vec.clone(), next: self.next, } } } impl Drop for IntoIter where N: ArrayLength, { fn drop(&mut self) { unsafe { // Drop all the elements that have not been moved out of vec ptr::drop_in_place(&mut self.vec[self.next..]); // Prevent dropping of other elements self.vec.0.len = 0; } } } impl IntoIterator for Vec where N: ArrayLength, { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter { vec: self, next: 0 } } } impl PartialEq> for Vec where N1: ArrayLength, N2: ArrayLength, A: PartialEq, { fn eq(&self, other: &Vec) -> bool { <[A]>::eq(self, &**other) } } macro_rules! eq { ($Lhs:ty, $Rhs:ty) => { impl<'a, 'b, A, B, N> PartialEq<$Rhs> for $Lhs where A: PartialEq, N: ArrayLength, { fn eq(&self, other: &$Rhs) -> bool { <[A]>::eq(self, &other[..]) } } }; } eq!(Vec, [B]); eq!(Vec, &'a [B]); eq!(Vec, &'a mut [B]); macro_rules! array { ($($N:expr),+) => { $( eq!(Vec, [B; $N]); eq!(Vec, &'a [B; $N]); )+ } } array!( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ); impl Eq for Vec where N: ArrayLength, T: Eq, { } impl ops::Deref for Vec where N: ArrayLength, { type Target = [T]; fn deref(&self) -> &[T] { self.0.as_slice() } } impl ops::DerefMut for Vec where N: ArrayLength, { fn deref_mut(&mut self) -> &mut [T] { self.0.as_mut_slice() } } impl AsRef> for Vec where N: ArrayLength, { #[inline] fn as_ref(&self) -> &Self { self } } impl AsMut> for Vec where N: ArrayLength, { #[inline] fn as_mut(&mut self) -> &mut Self { self } } impl AsRef<[T]> for Vec where N: ArrayLength, { #[inline] fn as_ref(&self) -> &[T] { self } } impl AsMut<[T]> for Vec where N: ArrayLength, { #[inline] fn as_mut(&mut self) -> &mut [T] { self } } #[cfg(test)] mod tests { use crate::{consts::*, Vec}; use as_slice::AsSlice; use core::fmt::Write; #[test] fn static_new() { static mut _V: Vec = Vec(crate::i::Vec::new()); } macro_rules! droppable { () => { struct Droppable; impl Droppable { fn new() -> Self { unsafe { COUNT += 1; } Droppable } } impl Drop for Droppable { fn drop(&mut self) { unsafe { COUNT -= 1; } } } static mut COUNT: i32 = 0; }; } #[test] fn drop() { droppable!(); { let mut v: Vec = Vec::new(); v.push(Droppable::new()).ok().unwrap(); v.push(Droppable::new()).ok().unwrap(); v.pop().unwrap(); } assert_eq!(unsafe { COUNT }, 0); { let mut v: Vec = Vec::new(); v.push(Droppable::new()).ok().unwrap(); v.push(Droppable::new()).ok().unwrap(); } assert_eq!(unsafe { COUNT }, 0); } #[test] fn eq() { let mut xs: Vec = Vec::new(); let mut ys: Vec = Vec::new(); assert_eq!(xs, ys); xs.push(1).unwrap(); ys.push(1).unwrap(); assert_eq!(xs, ys); } #[test] fn full() { let mut v: Vec = Vec::new(); v.push(0).unwrap(); v.push(1).unwrap(); v.push(2).unwrap(); v.push(3).unwrap(); assert!(v.push(4).is_err()); } #[test] fn iter() { let mut v: Vec = Vec::new(); v.push(0).unwrap(); v.push(1).unwrap(); v.push(2).unwrap(); v.push(3).unwrap(); let mut items = v.iter(); assert_eq!(items.next(), Some(&0)); assert_eq!(items.next(), Some(&1)); assert_eq!(items.next(), Some(&2)); assert_eq!(items.next(), Some(&3)); assert_eq!(items.next(), None); } #[test] fn iter_mut() { let mut v: Vec = Vec::new(); v.push(0).unwrap(); v.push(1).unwrap(); v.push(2).unwrap(); v.push(3).unwrap(); let mut items = v.iter_mut(); assert_eq!(items.next(), Some(&mut 0)); assert_eq!(items.next(), Some(&mut 1)); assert_eq!(items.next(), Some(&mut 2)); assert_eq!(items.next(), Some(&mut 3)); assert_eq!(items.next(), None); } #[test] fn collect_from_iter() { let slice = &[1, 2, 3]; let vec = slice.iter().cloned().collect::>(); assert_eq!(vec, slice); } #[test] #[should_panic] fn collect_from_iter_overfull() { let slice = &[1, 2, 3]; let _vec = slice.iter().cloned().collect::>(); } #[test] fn iter_move() { let mut v: Vec = Vec::new(); v.push(0).unwrap(); v.push(1).unwrap(); v.push(2).unwrap(); v.push(3).unwrap(); let mut items = v.into_iter(); assert_eq!(items.next(), Some(0)); assert_eq!(items.next(), Some(1)); assert_eq!(items.next(), Some(2)); assert_eq!(items.next(), Some(3)); assert_eq!(items.next(), None); } #[test] fn iter_move_drop() { droppable!(); { let mut vec: Vec = Vec::new(); vec.push(Droppable::new()).ok().unwrap(); vec.push(Droppable::new()).ok().unwrap(); let mut items = vec.into_iter(); // Move all let _ = items.next(); let _ = items.next(); } assert_eq!(unsafe { COUNT }, 0); { let mut vec: Vec = Vec::new(); vec.push(Droppable::new()).ok().unwrap(); vec.push(Droppable::new()).ok().unwrap(); let _items = vec.into_iter(); // Move none } assert_eq!(unsafe { COUNT }, 0); { let mut vec: Vec = Vec::new(); vec.push(Droppable::new()).ok().unwrap(); vec.push(Droppable::new()).ok().unwrap(); let mut items = vec.into_iter(); let _ = items.next(); // Move partly } assert_eq!(unsafe { COUNT }, 0); } #[test] fn push_and_pop() { let mut v: Vec = Vec::new(); assert_eq!(v.len(), 0); assert_eq!(v.pop(), None); assert_eq!(v.len(), 0); v.push(0).unwrap(); assert_eq!(v.len(), 1); assert_eq!(v.pop(), Some(0)); assert_eq!(v.len(), 0); assert_eq!(v.pop(), None); assert_eq!(v.len(), 0); } #[test] fn resize_size_limit() { let mut v: Vec = Vec::new(); v.resize(0, 0).unwrap(); v.resize(4, 0).unwrap(); v.resize(5, 0).err().expect("full"); } #[test] fn resize_length_cases() { let mut v: Vec = Vec::new(); assert_eq!(v.len(), 0); // Grow by 1 v.resize(1, 0).unwrap(); assert_eq!(v.len(), 1); // Grow by 2 v.resize(3, 0).unwrap(); assert_eq!(v.len(), 3); // Resize to current size v.resize(3, 0).unwrap(); assert_eq!(v.len(), 3); // Shrink by 1 v.resize(2, 0).unwrap(); assert_eq!(v.len(), 2); // Shrink by 2 v.resize(0, 0).unwrap(); assert_eq!(v.len(), 0); } #[test] fn resize_contents() { let mut v: Vec = Vec::new(); // New entries take supplied value when growing v.resize(1, 17).unwrap(); assert_eq!(v[0], 17); // Old values aren't changed when growing v.resize(2, 18).unwrap(); assert_eq!(v[0], 17); assert_eq!(v[1], 18); // Old values aren't changed when length unchanged v.resize(2, 0).unwrap(); assert_eq!(v[0], 17); assert_eq!(v[1], 18); // Old values aren't changed when shrinking v.resize(1, 0).unwrap(); assert_eq!(v[0], 17); } #[test] fn resize_default() { let mut v: Vec = Vec::new(); // resize_default is implemented using resize, so just check the // correct value is being written. v.resize_default(1).unwrap(); assert_eq!(v[0], 0); } #[test] fn write() { let mut v: Vec = Vec::new(); write!(v, "{:x}", 1234).unwrap(); assert_eq!(&v[..], b"4d2"); } #[test] fn extend_from_slice() { let mut v: Vec = Vec::new(); assert_eq!(v.len(), 0); v.extend_from_slice(&[1, 2]).unwrap(); assert_eq!(v.len(), 2); assert_eq!(v.as_slice(), &[1, 2]); v.extend_from_slice(&[3]).unwrap(); assert_eq!(v.len(), 3); assert_eq!(v.as_slice(), &[1, 2, 3]); assert!(v.extend_from_slice(&[4, 5]).is_err()); assert_eq!(v.len(), 3); assert_eq!(v.as_slice(), &[1, 2, 3]); } #[test] fn from_slice() { // Successful construction let v: Vec = Vec::from_slice(&[1, 2, 3]).unwrap(); assert_eq!(v.len(), 3); assert_eq!(v.as_slice(), &[1, 2, 3]); // Slice too large assert!(Vec::::from_slice(&[1, 2, 3]).is_err()); } #[test] fn starts_with() { let v: Vec<_, U8> = Vec::from_slice(b"ab").unwrap(); assert!(v.starts_with(&[])); assert!(v.starts_with(b"")); assert!(v.starts_with(b"a")); assert!(v.starts_with(b"ab")); assert!(!v.starts_with(b"abc")); assert!(!v.starts_with(b"ba")); assert!(!v.starts_with(b"b")); } #[test] fn ends_with() { let v: Vec<_, U8> = Vec::from_slice(b"ab").unwrap(); assert!(v.ends_with(&[])); assert!(v.ends_with(b"")); assert!(v.ends_with(b"b")); assert!(v.ends_with(b"ab")); assert!(!v.ends_with(b"abc")); assert!(!v.ends_with(b"ba")); assert!(!v.ends_with(b"a")); } }