From b23f273169ec0568a5f1b7947878e57996b5200f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Fri, 15 Dec 2023 17:00:31 +0100 Subject: [PATCH] Implement https://github.com/rust-embedded/heapless/pull/424 but with the additional `impl Unsize for Vec` --- src/lib.rs | 2 +- src/vec.rs | 1004 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 969 insertions(+), 37 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 333a2d4d0b..9d77a9792c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,7 +86,7 @@ pub use indexmap::{ pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter}; pub use linear_map::LinearMap; pub use string::String; -pub use vec::Vec; +pub use vec::{Vec, VecView}; #[macro_use] #[cfg(test)] diff --git a/src/vec.rs b/src/vec.rs index 2df7d86c1c..8d1726b093 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -7,6 +7,34 @@ use core::{ ops, ptr, slice, }; +/// Workaround forbidden specialization of Drop +pub trait VecDrop { + fn drop_with_len(&mut self, len: usize); +} + +impl VecDrop for [MaybeUninit] { + fn drop_with_len(&mut self, _len: usize) { + // Case of a view, drop does nothing + } +} + +impl VecDrop for [MaybeUninit; N] { + fn drop_with_len(&mut self, len: usize) { + // NOTE(unsafe) avoid bound checks in the slicing operation + // &mut buffer[..self.len] + let mut_slice = unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut T, len) }; + // We drop each element used in the vector by turning into a `&mut [T]`. + unsafe { + ptr::drop_in_place(mut_slice); + } + } +} + +pub struct VecInner { + len: usize, + buffer: B, +} + /// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). /// /// # Examples @@ -35,14 +63,706 @@ use core::{ /// } /// assert_eq!(*vec, [7, 1, 2, 3]); /// ``` -pub struct Vec { - // NOTE order is important for optimizations. the `len` first layout lets the compiler optimize - // `new` to: reserve stack space and zero the first word. With the fields in the reverse order - // the compiler optimizes `new` to `memclr`-ing the *entire* stack space, including the `buffer` - // field which should be left uninitialized. Optimizations were last checked with Rust 1.60 - len: usize, +pub type Vec = VecInner<[MaybeUninit; N]>; +/// TODO: doc +pub type VecView = VecInner<[MaybeUninit]>; + +impl VecView { + /// Returns a raw pointer to the vector’s buffer. + pub fn as_ptr(&self) -> *const T { + self.buffer.as_ptr() as *const T + } + + /// Returns a raw pointer to the vector’s buffer, which may be mutated through. + pub fn as_mut_ptr(&mut self) -> *mut T { + self.buffer.as_mut_ptr() as *mut T + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// let buffer: Vec = Vec::from_slice(&[1, 2, 3, 5, 8]).unwrap(); + /// assert_eq!(buffer.as_slice(), &[1, 2, 3, 5, 8]); + /// ``` + pub 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) } + } + + /// Extracts a mutable slice containing the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// let mut buffer: Vec = Vec::from_slice(&[1, 2, 3, 5, 8]).unwrap(); + /// buffer[0] = 9; + /// assert_eq!(buffer.as_slice(), &[9, 2, 3, 5, 8]); + /// ``` + pub fn as_mut_slice(&mut self) -> &mut [T] { + // NOTE(unsafe) avoid bound checks in the slicing operation + // &mut buffer[..self.len] + unsafe { slice::from_raw_parts_mut(self.buffer.as_mut_ptr() as *mut T, self.len) } + } + + /// Returns the maximum number of elements the vector can hold. + pub const fn capacity(&self) -> usize { + self.buffer.len() + } + + /// Clears the vector, removing all values. + pub fn clear(&mut self) { + self.truncate(0); + } + + /// Extends the vec from an iterator. + /// + /// # Panic + /// + /// Panics if the vec cannot hold all elements of the iterator. + pub fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + for elem in iter { + self.push(elem).ok().unwrap() + } + } + + /// 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; + /// + /// let mut vec = Vec::::new(); + /// vec.push(1).unwrap(); + /// vec.extend_from_slice(&[2, 3, 4]).unwrap(); + /// assert_eq!(*vec, [1, 2, 3, 4]); + /// ``` + #[allow(clippy::result_unit_err)] + pub 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(()) + } + } + + /// Removes the last element from a vector and returns it, or `None` if it's empty + pub fn pop(&mut self) -> Option { + if self.len != 0 { + Some(unsafe { self.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> { + if self.len < self.capacity() { + unsafe { self.push_unchecked(item) } + Ok(()) + } else { + Err(item) + } + } + + /// Removes the last element from a vector and returns it + /// + /// # Safety + /// + /// This assumes the vec to have at least one element. + pub unsafe fn pop_unchecked(&mut self) -> T { + debug_assert!(!self.is_empty()); + + self.len -= 1; + self.buffer.get_unchecked_mut(self.len).as_ptr().read() + } + + /// Appends an `item` to the back of the collection + /// + /// # Safety + /// + /// This assumes the vec is not full. + pub 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 + debug_assert!(!self.is_full()); + + *self.buffer.get_unchecked_mut(self.len) = MaybeUninit::new(item); + + self.len += 1; + } + + /// Shortens the vector, keeping the first `len` elements and dropping the rest. + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + // Note: It's intentional that this is `>` and not `>=`. + // Changing it to `>=` has negative performance + // implications in some cases. See rust-lang/rust#78884 for more. + if len > self.len { + return; + } + let remaining_len = self.len - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.len = len; + ptr::drop_in_place(s); + } + } + + /// 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`](Self::resize_default). + #[allow(clippy::result_unit_err)] + 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`](Self::resize). + #[allow(clippy::result_unit_err)] + 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`]: Self::truncate + /// [`resize`]: Self::resize + /// [`extend`]: core::iter::Extend + /// [`clear`]: Self::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Self::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; + /// + /// # // 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; + /// + /// let mut vec = Vec::, 3>::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.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<_, 8> = 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 { + assert!(index < self.len); + unsafe { self.swap_remove_unchecked(index) } + } + + /// 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). + /// + /// # Safety + /// + /// Assumes `index` within bounds. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut v: Vec<_, 8> = Vec::new(); + /// v.push("foo").unwrap(); + /// v.push("bar").unwrap(); + /// v.push("baz").unwrap(); + /// v.push("qux").unwrap(); + /// + /// assert_eq!(unsafe { v.swap_remove_unchecked(1) }, "bar"); + /// assert_eq!(&*v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(unsafe { v.swap_remove_unchecked(0) }, "foo"); + /// assert_eq!(&*v, ["baz", "qux"]); + /// ``` + pub unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T { + let length = self.len(); + debug_assert!(index < length); + let value = ptr::read(self.as_ptr().add(index)); + let base_ptr = self.as_mut_ptr(); + ptr::copy(base_ptr.add(length - 1), base_ptr.add(index), 1); + self.len -= 1; + value + } + + /// Returns true if the vec is full + #[inline] + pub fn is_full(&self) -> bool { + self.len == self.capacity() + } + + /// Returns true if the vec is empty + #[inline] + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + /// Returns `true` if `needle` is a prefix of the Vec. + /// + /// Always returns `true` if `needle` is an empty slice. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let v: Vec<_, 8> = 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; + /// + /// let v: Vec<_, 8> = 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..] + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// Returns back the `element` if the vector is full. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3]).unwrap(); + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + pub fn insert(&mut self, index: usize, element: T) -> Result<(), T> { + let len = self.len(); + if index > len { + panic!( + "insertion index (is {}) should be <= len (is {})", + index, len + ); + } + + // check there's space for the new element + if self.is_full() { + return Err(element); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + + Ok(()) + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// Note: Because this shifts over the remaining elements, it has a + /// worst-case performance of *O*(n). If you don't need the order of + /// elements to be preserved, use [`swap_remove`] instead. If you'd like to + /// remove elements from the beginning of the `Vec`, consider using + /// [`Deque::pop_front`] instead. + /// + /// [`swap_remove`]: Vec::swap_remove + /// [`Deque::pop_front`]: crate::Deque::pop_front + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut v: Vec<_, 8> = Vec::from_slice(&[1, 2, 3]).unwrap(); + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + pub fn remove(&mut self, index: usize) -> T { + let len = self.len(); + if index >= len { + panic!("removal index (is {}) should be < len (is {})", index, len); + } + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` for which `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); + /// vec.retain(|&x| x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4, 5]).unwrap(); + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// vec.retain(|_| *iter.next().unwrap()); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate, passing a mutable reference to it. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// use heapless::Vec; + /// + /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); + /// vec.retain_mut(|x| { + /// if *x <= 3 { + /// *x += 1; + /// true + /// } else { + /// false + /// } + /// }); + /// assert_eq!(vec, [2, 3, 4]); + /// ``` + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, + { + let original_len = self.len(); + // Avoid double drop if the drop guard is not executed, + // since we may make some holes during the process. + unsafe { self.set_len(0) }; + + // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked] + // |<- processed len ->| ^- next to check + // |<- deleted cnt ->| + // |<- original_len ->| + // Kept: Elements which predicate returns true on. + // Hole: Moved or dropped element slot. + // Unchecked: Unchecked valid elements. + // + // This drop guard will be invoked when predicate or `drop` of element panicked. + // It shifts unchecked elements to cover holes and `set_len` to the correct length. + // In cases when predicate and `drop` never panick, it will be optimized out. + struct BackshiftOnDrop<'a, T> { + v: &'a mut VecView, + processed_len: usize, + deleted_cnt: usize, + original_len: usize, + } + + impl Drop for BackshiftOnDrop<'_, T> { + fn drop(&mut self) { + if self.deleted_cnt > 0 { + // SAFETY: Trailing unchecked items must be valid since we never touch them. + unsafe { + ptr::copy( + self.v.as_ptr().add(self.processed_len), + self.v + .as_mut_ptr() + .add(self.processed_len - self.deleted_cnt), + self.original_len - self.processed_len, + ); + } + } + // SAFETY: After filling holes, all items are in contiguous memory. + unsafe { + self.v.set_len(self.original_len - self.deleted_cnt); + } + } + } + + let mut g = BackshiftOnDrop { + v: self, + processed_len: 0, + deleted_cnt: 0, + original_len, + }; + + fn process_loop( + original_len: usize, + f: &mut F, + g: &mut BackshiftOnDrop<'_, T>, + ) where + F: FnMut(&mut T) -> bool, + { + while g.processed_len != original_len { + let p = g.v.as_mut_ptr(); + // SAFETY: Unchecked element must be valid. + let cur = unsafe { &mut *p.add(g.processed_len) }; + if !f(cur) { + // Advance early to avoid double drop if `drop_in_place` panicked. + g.processed_len += 1; + g.deleted_cnt += 1; + // SAFETY: We never touch this element again after dropped. + unsafe { ptr::drop_in_place(cur) }; + // We already advanced the counter. + if DELETED { + continue; + } else { + break; + } + } + if DELETED { + // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. + // We use copy for move, and never touch this element again. + unsafe { + let hole_slot = p.add(g.processed_len - g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; + } + } + + // Stage 1: Nothing was deleted. + process_loop::(original_len, &mut f, &mut g); - buffer: [MaybeUninit; N], + // Stage 2: Some elements were deleted. + process_loop::(original_len, &mut f, &mut g); + + // All item are processed. This can be optimized to `set_len` by LLVM. + drop(g); + } } impl Vec { @@ -146,14 +866,12 @@ impl Vec { new } - /// Returns a raw pointer to the vector’s buffer. - pub fn as_ptr(&self) -> *const T { - self.buffer.as_ptr() as *const T + pub const fn as_view(&self) -> &VecView { + self } - /// Returns a raw pointer to the vector’s buffer, which may be mutated through. - pub fn as_mut_ptr(&mut self) -> *mut T { - self.buffer.as_mut_ptr() as *mut T + pub fn as_mut_view(&mut self) -> &mut VecView { + self } /// Extracts a slice containing the entire vector. @@ -168,9 +886,7 @@ impl Vec { /// assert_eq!(buffer.as_slice(), &[1, 2, 3, 5, 8]); /// ``` pub 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) } + self.as_view().as_slice() } /// Returns the contents of the vector as an array of length `M` if the length @@ -212,9 +928,7 @@ impl Vec { /// assert_eq!(buffer.as_slice(), &[9, 2, 3, 5, 8]); /// ``` pub fn as_mut_slice(&mut self) -> &mut [T] { - // NOTE(unsafe) avoid bound checks in the slicing operation - // &mut buffer[..self.len] - unsafe { slice::from_raw_parts_mut(self.buffer.as_mut_ptr() as *mut T, self.len) } + self.as_mut_view().as_mut_slice() } /// Returns the maximum number of elements the vector can hold. @@ -224,7 +938,7 @@ impl Vec { /// Clears the vector, removing all values. pub fn clear(&mut self) { - self.truncate(0); + self.as_mut_view().clear() } /// Extends the vec from an iterator. @@ -236,9 +950,7 @@ impl Vec { where I: IntoIterator, { - for elem in iter { - self.push(elem).ok().unwrap() - } + self.as_mut_view().extend(iter) } /// Clones and appends all elements in a slice to the `Vec`. @@ -877,7 +1589,7 @@ impl Default for Vec { } } -impl fmt::Debug for Vec +impl fmt::Debug for VecView where T: fmt::Debug, { @@ -886,6 +1598,15 @@ where } } +impl fmt::Debug for Vec +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_view().fmt(f) + } +} + impl fmt::Write for Vec { fn write_str(&mut self, s: &str) -> fmt::Result { match self.extend_from_slice(s.as_bytes()) { @@ -895,11 +1616,11 @@ impl fmt::Write for Vec { } } -impl Drop for Vec { - fn drop(&mut self) { - // We drop each element used in the vector by turning into a `&mut [T]`. - unsafe { - ptr::drop_in_place(self.as_mut_slice()); +impl fmt::Write for VecView { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.extend_from_slice(s.as_bytes()) { + Ok(()) => Ok(()), + Err(_) => Err(fmt::Error), } } } @@ -910,6 +1631,12 @@ impl From<[T; M]> for Vec { } } +impl Drop for VecInner { + fn drop(&mut self) { + self.buffer.drop_with_len(self.len) + } +} + impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec { type Error = (); @@ -918,7 +1645,7 @@ impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec { } } -impl Extend for Vec { +impl Extend for VecView { fn extend(&mut self, iter: I) where I: IntoIterator, @@ -927,7 +1654,28 @@ impl Extend for Vec { } } +impl Extend for Vec { + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + self.as_mut_view().extend(iter) + } +} + impl<'a, T, const N: usize> Extend<&'a T> for Vec +where + T: 'a + Copy, +{ + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + self.as_mut_view().extend(iter.into_iter().cloned()) + } +} + +impl<'a, T> Extend<&'a T> for VecView where T: 'a + Copy, { @@ -940,6 +1688,15 @@ where } impl hash::Hash for Vec +where + T: core::hash::Hash, +{ + fn hash(&self, state: &mut H) { + self.as_view().hash(state) + } +} + +impl hash::Hash for VecView where T: core::hash::Hash, { @@ -952,6 +1709,15 @@ impl<'a, T, const N: usize> IntoIterator for &'a Vec { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + self.as_view().iter() + } +} + +impl<'a, T> IntoIterator for &'a VecView { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter() } @@ -961,6 +1727,15 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut Vec { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; + fn into_iter(self) -> Self::IntoIter { + self.as_mut_view().iter_mut() + } +} + +impl<'a, T> IntoIterator for &'a mut VecView { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } @@ -1046,12 +1821,49 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { + self.as_view().eq(other.as_view()) + } +} + +impl PartialEq> for VecView +where + A: PartialEq, +{ + fn eq(&self, other: &Vec) -> bool { + self.eq(other.as_view()) + } +} + +impl PartialEq> for Vec +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { + self.as_view().eq(other) + } +} + +impl PartialEq> for VecView +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { <[A]>::eq(self, &**other) } } // Vec == [B] impl PartialEq<[B]> for Vec +where + A: PartialEq, +{ + fn eq(&self, other: &[B]) -> bool { + self.as_view().eq(other) + } +} + +// VecView == [B] +impl PartialEq<[B]> for VecView where A: PartialEq, { @@ -1066,6 +1878,16 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { + other.as_view().eq(self) + } +} + +// [B] == VecView +impl PartialEq> for [B] +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { <[A]>::eq(other, self) } } @@ -1076,7 +1898,17 @@ where A: PartialEq, { fn eq(&self, other: &&[B]) -> bool { - <[A]>::eq(self, &other[..]) + self.as_view().eq(other) + } +} + +// VecView == &[B] +impl PartialEq<&[B]> for VecView +where + A: PartialEq, +{ + fn eq(&self, other: &&[B]) -> bool { + <[A]>::eq(self, *other) } } @@ -1086,12 +1918,32 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { - <[A]>::eq(other, &self[..]) + other.as_view().eq(self) + } +} + +// &[B] == VecView +impl PartialEq> for &[B] +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { + <[A]>::eq(other, *self) } } // Vec == &mut [B] impl PartialEq<&mut [B]> for Vec +where + A: PartialEq, +{ + fn eq(&self, other: &&mut [B]) -> bool { + self.as_view().eq(other) + } +} + +// VecView == &mut [B] +impl PartialEq<&mut [B]> for VecView where A: PartialEq, { @@ -1106,6 +1958,16 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { + other.as_view().eq(self) + } +} + +// &mut [B] == VecView +impl PartialEq> for &mut [B] +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { <[A]>::eq(other, &self[..]) } } @@ -1117,7 +1979,18 @@ where A: PartialEq, { fn eq(&self, other: &[B; M]) -> bool { - <[A]>::eq(self, &other[..]) + self.as_view().eq(other) + } +} + +// VecView == [B; M] +// Equality does not require equal capacity +impl PartialEq<[B; M]> for VecView +where + A: PartialEq, +{ + fn eq(&self, other: &[B; M]) -> bool { + <[A]>::eq(self, other) } } @@ -1128,7 +2001,18 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { - <[A]>::eq(other, &self[..]) + other.as_view().eq(self) + } +} + +// [B; M] == VecView +// Equality does not require equal capacity +impl PartialEq> for [B; M] +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { + <[A]>::eq(other, self) } } @@ -1139,7 +2023,18 @@ where A: PartialEq, { fn eq(&self, other: &&[B; M]) -> bool { - <[A]>::eq(self, &other[..]) + self.as_view().eq(other) + } +} + +// VecView == &[B; M] +// Equality does not require equal capacity +impl PartialEq<&[B; M]> for VecView +where + A: PartialEq, +{ + fn eq(&self, other: &&[B; M]) -> bool { + <[A]>::eq(self, *other) } } @@ -1150,18 +2045,41 @@ where A: PartialEq, { fn eq(&self, other: &Vec) -> bool { - <[A]>::eq(other, &self[..]) + other.as_view().eq(self) + } +} + +// &[B; M] == VecView +// Equality does not require equal capacity +impl PartialEq> for &[B; M] +where + A: PartialEq, +{ + fn eq(&self, other: &VecView) -> bool { + <[A]>::eq(other, *self) } } // Implements Eq if underlying data is Eq impl Eq for Vec where T: Eq {} +// Not sure about this one? Should two distinct capacities really be Eq? +// Anyways it derefs to &[u8] which implements Eq so I suppose it should +impl Eq for VecView where T: Eq {} impl PartialOrd> for Vec where T: PartialOrd, { fn partial_cmp(&self, other: &Vec) -> Option { + self.as_view().partial_cmp(other.as_view()) + } +} + +impl PartialOrd> for VecView +where + T: PartialOrd, +{ + fn partial_cmp(&self, other: &VecView) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } @@ -1190,6 +2108,20 @@ impl ops::DerefMut for Vec { } } +impl ops::Deref for VecView { + type Target = [T]; + + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +impl ops::DerefMut for VecView { + fn deref_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + impl AsRef> for Vec { #[inline] fn as_ref(&self) -> &Self {