mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-28 21:10:28 +00:00
Merge pull request #504 from GnomedDev/vec-generic-length
Implement a generic length parameter for Vec<T, N>
This commit is contained in:
commit
fb62d12ad5
@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Added `truncate` to `IndexMap`.
|
||||
- Added `get_index` and `get_index_mut` to `IndexMap`.
|
||||
- Added `String::uDisplay`.
|
||||
- Added `LenT` generic to `Vec<T, N>` and `VecView<T>` to save memory when using a sane capacity value.
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -57,7 +57,7 @@ impl private::Sealed for Min {}
|
||||
/// struct if you want to write code that's generic over both.
|
||||
pub struct BinaryHeapInner<T, K, S: VecStorage<T> + ?Sized> {
|
||||
pub(crate) _kind: PhantomData<K>,
|
||||
pub(crate) data: VecInner<T, S>,
|
||||
pub(crate) data: VecInner<T, usize, S>,
|
||||
}
|
||||
|
||||
/// A priority queue implemented with a binary heap.
|
||||
@ -181,7 +181,7 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
|
||||
|
||||
impl<T, K, const N: usize> BinaryHeap<T, K, N> {
|
||||
/// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1).
|
||||
pub fn into_vec(self) -> Vec<T, N> {
|
||||
pub fn into_vec(self) -> Vec<T, N, usize> {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
13
src/de.rs
13
src/de.rs
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
binary_heap::Kind as BinaryHeapKind, BinaryHeap, Deque, HistoryBuffer, IndexMap, IndexSet,
|
||||
LinearMap, String, Vec,
|
||||
binary_heap::Kind as BinaryHeapKind, len_type::LenType, BinaryHeap, Deque, HistoryBuffer,
|
||||
IndexMap, IndexSet, LinearMap, String, Vec,
|
||||
};
|
||||
use core::{
|
||||
fmt,
|
||||
@ -95,7 +95,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T, const N: usize> Deserialize<'de> for Vec<T, N>
|
||||
impl<'de, T, LenT: LenType, const N: usize> Deserialize<'de> for Vec<T, N, LenT>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
@ -103,13 +103,14 @@ where
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, T, const N: usize>(PhantomData<(&'de (), T)>);
|
||||
struct ValueVisitor<'de, T, LenT: LenType, const N: usize>(PhantomData<(&'de (), T, LenT)>);
|
||||
|
||||
impl<'de, T, const N: usize> serde::de::Visitor<'de> for ValueVisitor<'de, T, N>
|
||||
impl<'de, T, LenT, const N: usize> serde::de::Visitor<'de> for ValueVisitor<'de, T, LenT, N>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
LenT: LenType,
|
||||
{
|
||||
type Value = Vec<T, N>;
|
||||
type Value = Vec<T, N, LenT>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
|
@ -1,12 +1,13 @@
|
||||
//! Defmt implementations for heapless types
|
||||
|
||||
use crate::{
|
||||
len_type::LenType,
|
||||
string::{StringInner, StringStorage},
|
||||
vec::{VecInner, VecStorage},
|
||||
};
|
||||
use defmt::Formatter;
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> defmt::Format for VecInner<T, S>
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> defmt::Format for VecInner<T, LenT, S>
|
||||
where
|
||||
T: defmt::Format,
|
||||
{
|
||||
|
@ -138,7 +138,7 @@ macro_rules! probe_loop {
|
||||
}
|
||||
|
||||
struct CoreMap<K, V, const N: usize> {
|
||||
entries: Vec<Bucket<K, V>, N>,
|
||||
entries: Vec<Bucket<K, V>, N, usize>,
|
||||
indices: [Option<Pos>; N],
|
||||
}
|
||||
|
||||
@ -1417,7 +1417,7 @@ where
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IntoIter<K, V, const N: usize> {
|
||||
entries: Vec<Bucket<K, V>, N>,
|
||||
entries: Vec<Bucket<K, V>, N, usize>,
|
||||
}
|
||||
|
||||
impl<K, V, const N: usize> Iterator for IntoIter<K, V, N> {
|
||||
|
107
src/len_type.rs
Normal file
107
src/len_type.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use core::{
|
||||
fmt::{Debug, Display},
|
||||
ops::{Add, AddAssign, Sub, SubAssign},
|
||||
};
|
||||
|
||||
pub trait Sealed:
|
||||
Send
|
||||
+ Sync
|
||||
+ Copy
|
||||
+ Display
|
||||
+ Debug
|
||||
+ PartialEq
|
||||
+ Add<Output = Self>
|
||||
+ AddAssign
|
||||
+ Sub<Output = Self>
|
||||
+ SubAssign
|
||||
+ PartialOrd
|
||||
+ TryFrom<usize, Error: Debug>
|
||||
+ TryInto<usize, Error: Debug>
|
||||
{
|
||||
/// The zero value of the integer type.
|
||||
const ZERO: Self;
|
||||
/// The one value of the integer type.
|
||||
const ONE: Self;
|
||||
/// The maximum value of this type, as a `usize`.
|
||||
const MAX: usize;
|
||||
|
||||
/// An infallible conversion from `usize` to `LenT`.
|
||||
#[inline]
|
||||
fn from_usize(val: usize) -> Self {
|
||||
val.try_into().unwrap()
|
||||
}
|
||||
|
||||
/// An infallible conversion from `LenT` to `usize`.
|
||||
#[inline]
|
||||
fn into_usize(self) -> usize {
|
||||
self.try_into().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_lentype {
|
||||
($($(#[$meta:meta])* $LenT:ty),*) => {$(
|
||||
$(#[$meta])*
|
||||
impl Sealed for $LenT {
|
||||
const ZERO: Self = 0;
|
||||
const ONE: Self = 1;
|
||||
const MAX: usize = Self::MAX as _;
|
||||
}
|
||||
|
||||
$(#[$meta])*
|
||||
impl LenType for $LenT {}
|
||||
)*}
|
||||
}
|
||||
|
||||
/// A sealed trait representing a valid type to use as a length for a container.
|
||||
///
|
||||
/// This cannot be implemented in user code, and is restricted to `u8`, `u16`, `u32`, and `usize`.
|
||||
pub trait LenType: Sealed {}
|
||||
|
||||
impl_lentype!(
|
||||
u8,
|
||||
u16,
|
||||
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
|
||||
u32,
|
||||
usize
|
||||
);
|
||||
|
||||
macro_rules! impl_lentodefault {
|
||||
($LenT:ty: $($len:literal),*) => {$(
|
||||
impl SmallestLenType for Const<$len> {
|
||||
type Type = $LenT;
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
/// A struct to create individual types for mapping with [`SmallestLenType`].
|
||||
///
|
||||
/// See the documentation of [`DefaultLenType`] for a detailed explanation.
|
||||
pub struct Const<const N: usize>;
|
||||
|
||||
/// A trait to map [`Const`] to it's respective [`LenType`].
|
||||
///
|
||||
/// See the documentation of [`DefaultLenType`] for a detailed explanation.
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "Length `N` does not have a default `LenType` mapping",
|
||||
note = "Provide the `LenType` explicitly, such as `usize`"
|
||||
)]
|
||||
pub trait SmallestLenType {
|
||||
type Type: LenType;
|
||||
}
|
||||
|
||||
/// A type alias to perform the `const N: usize` -> `LenType` mapping.
|
||||
///
|
||||
/// This is impossible to perform directly, but it is possible to write a `const N: usize` -> related `Type` mapping via a const generic argument,
|
||||
/// then map from that to an unrelated type via a trait with associated types.
|
||||
///
|
||||
/// [`Const`] is the "related type" in the above explaination, [`SmallestLenType`] is the mapping trait.
|
||||
pub type DefaultLenType<const N: usize> = <Const<N> as SmallestLenType>::Type;
|
||||
|
||||
impl_lentodefault!(u8: 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, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255);
|
||||
impl_lentodefault!(u16: 256, 300, 400, 500, 512, 600, 700, 800, 900, 1000, 1024, 2000, 2048, 4000, 4096, 8000, 8192, 16000, 16384, 32000, 32768, 65000, 65535);
|
||||
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
|
||||
impl_lentodefault!(u32: 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648);
|
||||
|
||||
pub const fn check_capacity_fits<LenT: LenType, const N: usize>() {
|
||||
assert!(LenT::MAX >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity");
|
||||
}
|
@ -165,6 +165,7 @@ pub use indexmap::{
|
||||
ValuesMut as IndexMapValuesMut,
|
||||
};
|
||||
pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter};
|
||||
pub use len_type::LenType;
|
||||
pub use linear_map::LinearMap;
|
||||
pub use string::String;
|
||||
|
||||
@ -178,6 +179,7 @@ pub mod deque;
|
||||
pub mod histbuf;
|
||||
mod indexmap;
|
||||
mod indexset;
|
||||
mod len_type;
|
||||
pub mod linear_map;
|
||||
mod slice;
|
||||
pub mod storage;
|
||||
|
@ -89,7 +89,7 @@ pub type ViewStorage<K, V> = ViewVecStorage<(K, V)>;
|
||||
|
||||
/// Base struct for [`LinearMap`] and [`LinearMapView`]
|
||||
pub struct LinearMapInner<K, V, S: LinearMapStorage<K, V> + ?Sized> {
|
||||
pub(crate) buffer: VecInner<(K, V), S>,
|
||||
pub(crate) buffer: VecInner<(K, V), usize, S>,
|
||||
}
|
||||
|
||||
/// A fixed capacity map/dictionary that performs lookups via linear search.
|
||||
@ -543,7 +543,7 @@ pub struct IntoIter<K, V, const N: usize>
|
||||
where
|
||||
K: Eq,
|
||||
{
|
||||
inner: <Vec<(K, V), N> as IntoIterator>::IntoIter,
|
||||
inner: <Vec<(K, V), N, usize> as IntoIterator>::IntoIter,
|
||||
}
|
||||
|
||||
impl<K, V, const N: usize> Iterator for IntoIter<K, V, N>
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind},
|
||||
deque::DequeInner,
|
||||
histbuf::{HistBufStorage, HistoryBufferInner},
|
||||
len_type::LenType,
|
||||
linear_map::{LinearMapInner, LinearMapStorage},
|
||||
string::{StringInner, StringStorage},
|
||||
vec::{VecInner, VecStorage},
|
||||
@ -48,7 +49,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, St: VecStorage<T> + ?Sized> Serialize for VecInner<T, St>
|
||||
impl<T, LenT: LenType, St: VecStorage<T>> Serialize for VecInner<T, LenT, St>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
|
@ -11,8 +11,11 @@ use core::{
|
||||
str::{self, Utf8Error},
|
||||
};
|
||||
|
||||
use crate::vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage};
|
||||
use crate::CapacityError;
|
||||
use crate::{
|
||||
len_type::LenType,
|
||||
vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage},
|
||||
};
|
||||
|
||||
mod drain;
|
||||
pub use drain::Drain;
|
||||
@ -131,7 +134,7 @@ pub type ViewStorage = ViewVecStorage<u8>;
|
||||
/// In most cases you should use [`String`] or [`StringView`] directly. Only use this
|
||||
/// struct if you want to write code that's generic over both.
|
||||
pub struct StringInner<S: StringStorage + ?Sized> {
|
||||
vec: VecInner<u8, S>,
|
||||
vec: VecInner<u8, usize, S>,
|
||||
}
|
||||
|
||||
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
|
||||
@ -229,9 +232,11 @@ impl<const N: usize> String<N> {
|
||||
/// # Ok::<(), core::str::Utf8Error>(())
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_utf8(vec: Vec<u8, N>) -> Result<Self, Utf8Error> {
|
||||
pub fn from_utf8<LenT: LenType>(vec: Vec<u8, N, LenT>) -> Result<Self, Utf8Error> {
|
||||
core::str::from_utf8(&vec)?;
|
||||
Ok(Self { vec })
|
||||
|
||||
// SAFETY: UTF-8 invariant has just been checked by `str::from_utf8`.
|
||||
Ok(unsafe { Self::from_utf8_unchecked(vec) })
|
||||
}
|
||||
|
||||
/// Convert UTF-8 bytes into a `String`, without checking that the string
|
||||
@ -256,8 +261,10 @@ impl<const N: usize> String<N> {
|
||||
/// assert_eq!("💖", sparkle_heart);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const unsafe fn from_utf8_unchecked(vec: Vec<u8, N>) -> Self {
|
||||
Self { vec }
|
||||
pub unsafe fn from_utf8_unchecked<LenT: LenType>(vec: Vec<u8, N, LenT>) -> Self {
|
||||
Self {
|
||||
vec: vec.cast_len_type(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `String` into a byte vector.
|
||||
@ -279,7 +286,7 @@ impl<const N: usize> String<N> {
|
||||
/// # Ok::<(), heapless::CapacityError>(())
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn into_bytes(self) -> Vec<u8, N> {
|
||||
pub fn into_bytes(self) -> Vec<u8, N, usize> {
|
||||
self.vec
|
||||
}
|
||||
}
|
||||
@ -457,7 +464,7 @@ impl<S: StringStorage + ?Sized> StringInner<S> {
|
||||
/// assert_eq!(s, "olleh");
|
||||
/// # Ok::<(), heapless::CapacityError>(())
|
||||
/// ```
|
||||
pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, S> {
|
||||
pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, usize, S> {
|
||||
&mut self.vec
|
||||
}
|
||||
|
||||
@ -1068,7 +1075,7 @@ mod tests {
|
||||
#[test]
|
||||
fn into_bytes() {
|
||||
let s: String<4> = String::try_from("ab").unwrap();
|
||||
let b: Vec<u8, 4> = s.into_bytes();
|
||||
let b: Vec<u8, 4, usize> = s.into_bytes();
|
||||
assert_eq!(b.len(), 2);
|
||||
assert_eq!(b"ab", &b[..]);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
len_type::LenType,
|
||||
string::{StringInner, StringStorage},
|
||||
vec::{VecInner, VecStorage},
|
||||
CapacityError,
|
||||
@ -24,7 +25,7 @@ impl<S: StringStorage + ?Sized> uWrite for StringInner<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: VecStorage<u8> + ?Sized> uWrite for VecInner<u8, S> {
|
||||
impl<LenT: LenType, S: VecStorage<u8> + ?Sized> uWrite for VecInner<u8, LenT, S> {
|
||||
type Error = CapacityError;
|
||||
#[inline]
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
|
||||
|
@ -6,38 +6,31 @@ use core::{
|
||||
slice,
|
||||
};
|
||||
|
||||
use crate::len_type::LenType;
|
||||
|
||||
use super::VecView;
|
||||
|
||||
/// A draining iterator for [`Vec`](super::Vec).
|
||||
///
|
||||
/// This `struct` is created by [`Vec::drain`](super::Vec::drain).
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use heapless::{vec, Vec};
|
||||
///
|
||||
/// let mut v = Vec::<_, 4>::from_array([0, 1, 2]);
|
||||
/// let iter: vec::Drain<'_, _> = v.drain(..);
|
||||
/// ```
|
||||
pub struct Drain<'a, T: 'a> {
|
||||
pub struct Drain<'a, T: 'a, LenT: LenType> {
|
||||
/// Index of tail to preserve
|
||||
pub(super) tail_start: usize,
|
||||
pub(super) tail_start: LenT,
|
||||
/// Length of tail
|
||||
pub(super) tail_len: usize,
|
||||
pub(super) tail_len: LenT,
|
||||
/// Current remaining range to remove
|
||||
pub(super) iter: slice::Iter<'a, T>,
|
||||
pub(super) vec: NonNull<VecView<T>>,
|
||||
pub(super) vec: NonNull<VecView<T, LenT>>,
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
|
||||
impl<T: fmt::Debug, LenT: LenType> fmt::Debug for Drain<'_, T, LenT> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drain<'_, T> {
|
||||
impl<T, LenT: LenType> Drain<'_, T, LenT> {
|
||||
/// Returns the remaining items of this iterator as a slice.
|
||||
///
|
||||
/// # Examples
|
||||
@ -57,16 +50,16 @@ impl<T> Drain<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[T]> for Drain<'_, T> {
|
||||
impl<T, LenT: LenType> AsRef<[T]> for Drain<'_, T, LenT> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Sync> Sync for Drain<'_, T> {}
|
||||
unsafe impl<T: Send> Send for Drain<'_, T> {}
|
||||
unsafe impl<T: Sync, LenT: LenType> Sync for Drain<'_, T, LenT> {}
|
||||
unsafe impl<T: Send, LenT: LenType> Send for Drain<'_, T, LenT> {}
|
||||
|
||||
impl<T> Iterator for Drain<'_, T> {
|
||||
impl<T, LenT: LenType> Iterator for Drain<'_, T, LenT> {
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
@ -81,7 +74,7 @@ impl<T> Iterator for Drain<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DoubleEndedIterator for Drain<'_, T> {
|
||||
impl<T, LenT: LenType> DoubleEndedIterator for Drain<'_, T, LenT> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.iter
|
||||
@ -90,25 +83,26 @@ impl<T> DoubleEndedIterator for Drain<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Drain<'_, T> {
|
||||
impl<T, LenT: LenType> Drop for Drain<'_, T, LenT> {
|
||||
fn drop(&mut self) {
|
||||
/// Moves back the un-`Drain`ed elements to restore the original `Vec`.
|
||||
struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
|
||||
struct DropGuard<'r, 'a, T, LenT: LenType>(&'r mut Drain<'a, T, LenT>);
|
||||
|
||||
impl<T> Drop for DropGuard<'_, '_, T> {
|
||||
impl<T, LenT: LenType> Drop for DropGuard<'_, '_, T, LenT> {
|
||||
fn drop(&mut self) {
|
||||
if self.0.tail_len > 0 {
|
||||
if self.0.tail_len > LenT::ZERO {
|
||||
unsafe {
|
||||
let source_vec = self.0.vec.as_mut();
|
||||
// memmove back untouched tail, update to new length
|
||||
let start = source_vec.len();
|
||||
let tail = self.0.tail_start;
|
||||
let tail = self.0.tail_start.into_usize();
|
||||
let tail_len = self.0.tail_len.into_usize();
|
||||
if tail != start {
|
||||
let dst = source_vec.as_mut_ptr().add(start);
|
||||
let src = source_vec.as_ptr().add(tail);
|
||||
ptr::copy(src, dst, self.0.tail_len);
|
||||
ptr::copy(src, dst, tail_len);
|
||||
}
|
||||
source_vec.set_len(start + self.0.tail_len);
|
||||
source_vec.set_len(start + tail_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,8 +119,9 @@ impl<T> Drop for Drain<'_, T> {
|
||||
unsafe {
|
||||
let vec = vec.as_mut();
|
||||
let old_len = vec.len();
|
||||
vec.set_len(old_len + drop_len + self.tail_len);
|
||||
vec.truncate(old_len + self.tail_len);
|
||||
let tail_len = self.tail_len.into_usize();
|
||||
vec.set_len(old_len + drop_len + tail_len);
|
||||
vec.truncate(old_len + tail_len);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -159,9 +154,9 @@ impl<T> Drop for Drain<'_, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ExactSizeIterator for Drain<'_, T> {}
|
||||
impl<T, LenT: LenType> ExactSizeIterator for Drain<'_, T, LenT> {}
|
||||
|
||||
impl<T> FusedIterator for Drain<'_, T> {}
|
||||
impl<T, LenT: LenType> FusedIterator for Drain<'_, T, LenT> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
398
src/vec/mod.rs
398
src/vec/mod.rs
@ -11,6 +11,7 @@ use core::{
|
||||
slice,
|
||||
};
|
||||
|
||||
use crate::len_type::{check_capacity_fits, DefaultLenType, LenType};
|
||||
use crate::CapacityError;
|
||||
|
||||
mod drain;
|
||||
@ -21,6 +22,7 @@ mod storage {
|
||||
use crate::{
|
||||
binary_heap::{BinaryHeapInner, BinaryHeapView},
|
||||
deque::{DequeInner, DequeView},
|
||||
len_type::LenType,
|
||||
};
|
||||
|
||||
use super::{VecInner, VecView};
|
||||
@ -56,10 +58,12 @@ mod storage {
|
||||
fn borrow(&self) -> &[MaybeUninit<T>];
|
||||
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>];
|
||||
|
||||
fn as_vec_view(this: &VecInner<T, Self>) -> &VecView<T>
|
||||
fn as_vec_view<LenT: LenType>(this: &VecInner<T, LenT, Self>) -> &VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>;
|
||||
fn as_vec_mut_view(this: &mut VecInner<T, Self>) -> &mut VecView<T>
|
||||
fn as_vec_mut_view<LenT: LenType>(
|
||||
this: &mut VecInner<T, LenT, Self>,
|
||||
) -> &mut VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>;
|
||||
|
||||
@ -98,13 +102,15 @@ mod storage {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
fn as_vec_view(this: &VecInner<T, Self>) -> &VecView<T>
|
||||
fn as_vec_view<LenT: LenType>(this: &VecInner<T, LenT, Self>) -> &VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>,
|
||||
{
|
||||
this
|
||||
}
|
||||
fn as_vec_mut_view(this: &mut VecInner<T, Self>) -> &mut VecView<T>
|
||||
fn as_vec_mut_view<LenT: LenType>(
|
||||
this: &mut VecInner<T, LenT, Self>,
|
||||
) -> &mut VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>,
|
||||
{
|
||||
@ -148,13 +154,15 @@ mod storage {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
fn as_vec_view(this: &VecInner<T, Self>) -> &VecView<T>
|
||||
fn as_vec_view<LenT: LenType>(this: &VecInner<T, LenT, Self>) -> &VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>,
|
||||
{
|
||||
this
|
||||
}
|
||||
fn as_vec_mut_view(this: &mut VecInner<T, Self>) -> &mut VecView<T>
|
||||
fn as_vec_mut_view<LenT: LenType>(
|
||||
this: &mut VecInner<T, LenT, Self>,
|
||||
) -> &mut VecView<T, LenT>
|
||||
where
|
||||
Self: VecStorage<T>,
|
||||
{
|
||||
@ -200,9 +208,9 @@ pub use drain::Drain;
|
||||
///
|
||||
/// In most cases you should use [`Vec`] or [`VecView`] directly. Only use this
|
||||
/// struct if you want to write code that's generic over both.
|
||||
pub struct VecInner<T, S: VecStorage<T> + ?Sized> {
|
||||
pub struct VecInner<T, LenT: LenType, S: VecStorage<T> + ?Sized> {
|
||||
phantom: PhantomData<T>,
|
||||
len: usize,
|
||||
len: LenT,
|
||||
buffer: S,
|
||||
}
|
||||
|
||||
@ -241,9 +249,14 @@ pub struct VecInner<T, S: VecStorage<T> + ?Sized> {
|
||||
/// use heapless::{Vec, VecView};
|
||||
///
|
||||
/// let vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &VecView<_> = &vec;
|
||||
/// let view: &VecView<_, _> = &vec;
|
||||
/// ```
|
||||
pub type Vec<T, const N: usize> = VecInner<T, OwnedVecStorage<T, N>>;
|
||||
///
|
||||
/// For uncommmon capacity values, or in generic scenarios, you may have to provide the `LenT` generic yourself.
|
||||
///
|
||||
/// This should be the smallest unsigned integer type that your capacity fits in, or `usize` if you don't want to consider this.
|
||||
pub type Vec<T, const N: usize, LenT = DefaultLenType<N>> =
|
||||
VecInner<T, LenT, OwnedVecStorage<T, N>>;
|
||||
|
||||
/// A [`Vec`] with dynamic capacity
|
||||
///
|
||||
@ -259,16 +272,16 @@ pub type Vec<T, const N: usize> = VecInner<T, OwnedVecStorage<T, N>>;
|
||||
/// use heapless::{Vec, VecView};
|
||||
///
|
||||
/// let mut vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &VecView<_> = &vec;
|
||||
/// let view: &VecView<_, _> = &vec;
|
||||
/// assert_eq!(view, &[1, 2, 3, 4]);
|
||||
///
|
||||
/// let mut_view: &mut VecView<_> = &mut vec;
|
||||
/// let mut_view: &mut VecView<_, _> = &mut vec;
|
||||
/// mut_view.push(5);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
pub type VecView<T> = VecInner<T, ViewVecStorage<T>>;
|
||||
pub type VecView<T, LenT = usize> = VecInner<T, LenT, ViewVecStorage<T>>;
|
||||
|
||||
impl<T, const N: usize> Vec<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize> Vec<T, N, LenT> {
|
||||
const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
const INIT: [MaybeUninit<T>; N] = [Self::ELEM; N]; // important for optimization of `new`
|
||||
|
||||
@ -286,9 +299,11 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
/// static mut X: Vec<u8, 16> = Vec::new();
|
||||
/// ```
|
||||
pub const fn new() -> Self {
|
||||
const { check_capacity_fits::<LenT, N>() }
|
||||
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
len: 0,
|
||||
len: LenT::ZERO,
|
||||
buffer: VecStorageInner { buffer: Self::INIT },
|
||||
}
|
||||
}
|
||||
@ -333,7 +348,7 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
if N == M {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
len: N,
|
||||
len: LenT::from_usize(N),
|
||||
// NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit<T>; N]
|
||||
// have the same layout when N == M.
|
||||
buffer: unsafe { mem::transmute_copy(&src) },
|
||||
@ -347,7 +362,7 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
dst_elem.write(unsafe { ptr::read(src_elem) });
|
||||
}
|
||||
|
||||
v.len = M;
|
||||
unsafe { v.set_len(M) };
|
||||
v
|
||||
}
|
||||
}
|
||||
@ -392,9 +407,27 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
}
|
||||
new
|
||||
}
|
||||
|
||||
/// Casts the `LenT` type to a new type, preserving everything else about the vector.
|
||||
///
|
||||
/// This can be useful if you need to pass a `Vec<T, N, u8>` into a `Vec<T, N, usize>` for example.
|
||||
///
|
||||
/// This will check at compile time if the `N` value will fit into `NewLenT`, and error if not.
|
||||
pub fn cast_len_type<NewLenT: LenType>(self) -> Vec<T, N, NewLenT> {
|
||||
const { check_capacity_fits::<NewLenT, N>() }
|
||||
let this = ManuallyDrop::new(self);
|
||||
|
||||
// SAFETY: Pointer argument is derived from a reference, meeting the safety documented invariants.
|
||||
// This also prevents double drops by wrapping `self` in `ManuallyDrop`.
|
||||
Vec {
|
||||
len: NewLenT::from_usize(this.len()),
|
||||
buffer: unsafe { ptr::read(&this.buffer) },
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> VecInner<T, LenT, S> {
|
||||
/// Removes the specified range from the vector in bulk, returning all
|
||||
/// removed elements as an iterator. If the iterator is dropped before
|
||||
/// being fully consumed, it drops the remaining removed elements.
|
||||
@ -427,7 +460,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
/// v.drain(..);
|
||||
/// assert_eq!(v, &[]);
|
||||
/// ```
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, LenT>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
@ -450,8 +483,8 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
let vec = NonNull::from(self.as_mut_view());
|
||||
let range_slice = slice::from_raw_parts(vec.as_ref().as_ptr().add(start), end - start);
|
||||
Drain {
|
||||
tail_start: end,
|
||||
tail_len: len - end,
|
||||
tail_start: LenT::from_usize(end),
|
||||
tail_len: LenT::from_usize(len - end),
|
||||
iter: range_slice.iter(),
|
||||
vec,
|
||||
}
|
||||
@ -464,7 +497,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
/// ```rust
|
||||
/// # use heapless::{Vec, VecView};
|
||||
/// let vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &VecView<u8> = vec.as_view();
|
||||
/// let view: &VecView<u8, _> = vec.as_view();
|
||||
/// ```
|
||||
///
|
||||
/// It is often preferable to do the same through type coerction, since `Vec<T, N>` implements `Unsize<VecView<T>>`:
|
||||
@ -472,10 +505,10 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
/// ```rust
|
||||
/// # use heapless::{Vec, VecView};
|
||||
/// let vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &VecView<u8> = &vec;
|
||||
/// let view: &VecView<u8, _> = &vec;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_view(&self) -> &VecView<T> {
|
||||
pub fn as_view(&self) -> &VecView<T, LenT> {
|
||||
S::as_vec_view(self)
|
||||
}
|
||||
|
||||
@ -483,19 +516,19 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
///
|
||||
/// ```rust
|
||||
/// # use heapless::{Vec, VecView};
|
||||
/// let mut vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &mut VecView<u8> = vec.as_mut_view();
|
||||
/// let mut vec: Vec<u8, 10, u8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &mut VecView<u8, _> = vec.as_mut_view();
|
||||
/// ```
|
||||
///
|
||||
/// It is often preferable to do the same through type coerction, since `Vec<T, N>` implements `Unsize<VecView<T>>`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use heapless::{Vec, VecView};
|
||||
/// let mut vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &mut VecView<u8> = &mut vec;
|
||||
/// let mut vec: Vec<u8, 10, u8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
|
||||
/// let view: &mut VecView<u8, _> = &mut vec;
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_mut_view(&mut self) -> &mut VecView<T> {
|
||||
pub fn as_mut_view(&mut self) -> &mut VecView<T, LenT> {
|
||||
S::as_vec_mut_view(self)
|
||||
}
|
||||
|
||||
@ -523,7 +556,12 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
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.borrow().as_ptr().cast::<T>(), self.len) }
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
self.buffer.borrow().as_ptr().cast::<T>(),
|
||||
self.len.into_usize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts a mutable slice containing the entire vector.
|
||||
@ -543,7 +581,10 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
// NOTE(unsafe) avoid bound checks in the slicing operation
|
||||
// &mut buffer[..self.len]
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.buffer.borrow_mut().as_mut_ptr().cast::<T>(), self.len)
|
||||
slice::from_raw_parts_mut(
|
||||
self.buffer.borrow_mut().as_mut_ptr().cast::<T>(),
|
||||
self.len.into_usize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,21 +631,23 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
pub fn extend_from_slice_inner<T>(
|
||||
len: &mut usize,
|
||||
pub fn extend_from_slice_inner<T, LenT: LenType>(
|
||||
len: &mut LenT,
|
||||
buf: &mut [MaybeUninit<T>],
|
||||
other: &[T],
|
||||
) -> Result<(), CapacityError>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
if *len + other.len() > buf.len() {
|
||||
if len.into_usize() + other.len() > buf.len() {
|
||||
// won't fit in the `Vec`; don't modify anything and return an error
|
||||
Err(CapacityError)
|
||||
} else {
|
||||
for elem in other {
|
||||
unsafe { *buf.get_unchecked_mut(*len) = MaybeUninit::new(elem.clone()) }
|
||||
*len += 1;
|
||||
unsafe {
|
||||
*buf.get_unchecked_mut(len.into_usize()) = MaybeUninit::new(elem.clone());
|
||||
}
|
||||
*len += LenT::ONE;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -615,10 +658,10 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
|
||||
/// Removes the last element from a vector and returns it, or `None` if it's empty
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if self.len != 0 {
|
||||
Some(unsafe { self.pop_unchecked() })
|
||||
} else {
|
||||
if self.len == LenT::ZERO {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { self.pop_unchecked() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -626,7 +669,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
///
|
||||
/// Returns back the `item` if the vector is full.
|
||||
pub fn push(&mut self, item: T) -> Result<(), T> {
|
||||
if self.len < self.capacity() {
|
||||
if self.len() < self.capacity() {
|
||||
unsafe { self.push_unchecked(item) }
|
||||
Ok(())
|
||||
} else {
|
||||
@ -642,10 +685,10 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
pub unsafe fn pop_unchecked(&mut self) -> T {
|
||||
debug_assert!(!self.is_empty());
|
||||
|
||||
self.len -= 1;
|
||||
self.len -= LenT::ONE;
|
||||
self.buffer
|
||||
.borrow_mut()
|
||||
.get_unchecked_mut(self.len)
|
||||
.get_unchecked_mut(self.len.into_usize())
|
||||
.as_ptr()
|
||||
.read()
|
||||
}
|
||||
@ -660,9 +703,12 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
// use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory
|
||||
debug_assert!(!self.is_full());
|
||||
|
||||
*self.buffer.borrow_mut().get_unchecked_mut(self.len) = MaybeUninit::new(item);
|
||||
*self
|
||||
.buffer
|
||||
.borrow_mut()
|
||||
.get_unchecked_mut(self.len.into_usize()) = MaybeUninit::new(item);
|
||||
|
||||
self.len += 1;
|
||||
self.len += LenT::ONE;
|
||||
}
|
||||
|
||||
/// Shortens the vector, keeping the first `len` elements and dropping the rest.
|
||||
@ -678,12 +724,12 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
// 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 {
|
||||
if len > self.len() {
|
||||
return;
|
||||
}
|
||||
let remaining_len = self.len - len;
|
||||
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;
|
||||
self.len = LenT::from_usize(len);
|
||||
ptr::drop_in_place(s);
|
||||
}
|
||||
}
|
||||
@ -703,8 +749,8 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
return Err(CapacityError);
|
||||
}
|
||||
|
||||
if new_len > self.len {
|
||||
while self.len < new_len {
|
||||
if new_len > self.len() {
|
||||
while self.len() < new_len {
|
||||
self.push(value.clone()).ok();
|
||||
}
|
||||
} else {
|
||||
@ -820,7 +866,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
pub unsafe fn set_len(&mut self, new_len: usize) {
|
||||
debug_assert!(new_len <= self.capacity());
|
||||
|
||||
self.len = new_len;
|
||||
self.len = LenT::from_usize(new_len);
|
||||
}
|
||||
|
||||
/// Removes an element from the vector and returns it.
|
||||
@ -851,7 +897,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
/// assert_eq!(&*v, ["baz", "qux"]);
|
||||
/// ```
|
||||
pub fn swap_remove(&mut self, index: usize) -> T {
|
||||
assert!(index < self.len);
|
||||
assert!(index < self.len());
|
||||
unsafe { self.swap_remove_unchecked(index) }
|
||||
}
|
||||
|
||||
@ -888,18 +934,18 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
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;
|
||||
self.len -= LenT::ONE;
|
||||
value
|
||||
}
|
||||
|
||||
/// Returns true if the vec is full
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.len == self.capacity()
|
||||
self.len() == self.capacity()
|
||||
}
|
||||
|
||||
/// Returns true if the vec is empty
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
self.len == LenT::ZERO
|
||||
}
|
||||
|
||||
/// Returns `true` if `needle` is a prefix of the Vec.
|
||||
@ -921,7 +967,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
T: PartialEq,
|
||||
{
|
||||
let n = needle.len();
|
||||
self.len >= n && needle == &self[..n]
|
||||
self.len() >= n && needle == &self[..n]
|
||||
}
|
||||
|
||||
/// Returns `true` if `needle` is a suffix of the Vec.
|
||||
@ -1107,7 +1153,7 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
let original_len = self.len();
|
||||
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) };
|
||||
@ -1123,56 +1169,57 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
// 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, S: VecStorage<T> + ?Sized> {
|
||||
v: &'a mut VecInner<T, S>,
|
||||
processed_len: usize,
|
||||
deleted_cnt: usize,
|
||||
original_len: usize,
|
||||
struct BackshiftOnDrop<'a, T, LenT: LenType, S: VecStorage<T> + ?Sized> {
|
||||
v: &'a mut VecInner<T, LenT, S>,
|
||||
processed_len: LenT,
|
||||
deleted_cnt: LenT,
|
||||
original_len: LenT,
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> Drop for BackshiftOnDrop<'_, T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Drop for BackshiftOnDrop<'_, T, LenT, S> {
|
||||
fn drop(&mut self) {
|
||||
if self.deleted_cnt > 0 {
|
||||
if self.deleted_cnt > LenT::ZERO {
|
||||
// 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_ptr().add(self.processed_len.into_usize()),
|
||||
self.v
|
||||
.as_mut_ptr()
|
||||
.add(self.processed_len - self.deleted_cnt),
|
||||
self.original_len - self.processed_len,
|
||||
.add((self.processed_len - self.deleted_cnt).into_usize()),
|
||||
(self.original_len - self.processed_len).into_usize(),
|
||||
);
|
||||
}
|
||||
}
|
||||
// SAFETY: After filling holes, all items are in contiguous memory.
|
||||
unsafe {
|
||||
self.v.set_len(self.original_len - self.deleted_cnt);
|
||||
self.v
|
||||
.set_len((self.original_len - self.deleted_cnt).into_usize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut g = BackshiftOnDrop {
|
||||
v: self,
|
||||
processed_len: 0,
|
||||
deleted_cnt: 0,
|
||||
processed_len: LenT::ZERO,
|
||||
deleted_cnt: LenT::ZERO,
|
||||
original_len,
|
||||
};
|
||||
|
||||
fn process_loop<F, T, S: VecStorage<T> + ?Sized, const DELETED: bool>(
|
||||
original_len: usize,
|
||||
fn process_loop<F, T, LenT: LenType, S: VecStorage<T> + ?Sized, const DELETED: bool>(
|
||||
original_len: LenT,
|
||||
f: &mut F,
|
||||
g: &mut BackshiftOnDrop<'_, T, S>,
|
||||
g: &mut BackshiftOnDrop<'_, T, LenT, S>,
|
||||
) 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) };
|
||||
let cur = unsafe { &mut *p.add(g.processed_len.into_usize()) };
|
||||
if !f(cur) {
|
||||
// Advance early to avoid double drop if `drop_in_place` panicked.
|
||||
g.processed_len += 1;
|
||||
g.deleted_cnt += 1;
|
||||
g.processed_len += LenT::ONE;
|
||||
g.deleted_cnt += LenT::ONE;
|
||||
// SAFETY: We never touch this element again after dropped.
|
||||
unsafe { ptr::drop_in_place(cur) };
|
||||
// We already advanced the counter.
|
||||
@ -1186,19 +1233,19 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
// 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);
|
||||
let hole_slot = p.add((g.processed_len - g.deleted_cnt).into_usize());
|
||||
ptr::copy_nonoverlapping(cur, hole_slot, 1);
|
||||
}
|
||||
}
|
||||
g.processed_len += 1;
|
||||
g.processed_len += LenT::ONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Stage 1: Nothing was deleted.
|
||||
process_loop::<F, T, S, false>(original_len, &mut f, &mut g);
|
||||
process_loop::<F, T, LenT, S, false>(original_len, &mut f, &mut g);
|
||||
|
||||
// Stage 2: Some elements were deleted.
|
||||
process_loop::<F, T, S, true>(original_len, &mut f, &mut g);
|
||||
process_loop::<F, T, LenT, S, true>(original_len, &mut f, &mut g);
|
||||
|
||||
// All item are processed. This can be optimized to `set_len` by LLVM.
|
||||
drop(g);
|
||||
@ -1232,19 +1279,19 @@ impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
|
||||
&mut self.buffer.borrow_mut()[self.len..]
|
||||
&mut self.buffer.borrow_mut()[self.len.into_usize()..]
|
||||
}
|
||||
}
|
||||
|
||||
// Trait implementations
|
||||
|
||||
impl<T, const N: usize> Default for Vec<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize> Default for Vec<T, N, LenT> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> fmt::Debug for VecInner<T, S>
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> fmt::Debug for VecInner<T, LenT, S>
|
||||
where
|
||||
T: fmt::Debug,
|
||||
{
|
||||
@ -1253,7 +1300,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: VecStorage<u8> + ?Sized> fmt::Write for VecInner<u8, S> {
|
||||
impl<LenT: LenType, S: VecStorage<u8> + ?Sized> fmt::Write for VecInner<u8, LenT, S> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
match self.extend_from_slice(s.as_bytes()) {
|
||||
Ok(()) => Ok(()),
|
||||
@ -1262,13 +1309,13 @@ impl<S: VecStorage<u8> + ?Sized> fmt::Write for VecInner<u8, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize, const M: usize> From<[T; M]> for Vec<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize, const M: usize> From<[T; M]> for Vec<T, N, LenT> {
|
||||
fn from(array: [T; M]) -> Self {
|
||||
Self::from_array(array)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> Drop for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Drop for VecInner<T, LenT, S> {
|
||||
fn drop(&mut self) {
|
||||
let mut_slice = self.as_mut_slice();
|
||||
// We drop each element used in the vector by turning into a `&mut [T]`.
|
||||
@ -1279,7 +1326,7 @@ impl<T, S: VecStorage<T> + ?Sized> Drop for VecInner<T, S> {
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
/// Converts the given `alloc::vec::Vec<T>` into a `Vec<T, N>`.
|
||||
impl<T, const N: usize> TryFrom<alloc::vec::Vec<T>> for Vec<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize> TryFrom<alloc::vec::Vec<T>> for Vec<T, N, LenT> {
|
||||
type Error = CapacityError;
|
||||
|
||||
/// Converts the given `alloc::vec::Vec<T>` into a `Vec<T, N>`.
|
||||
@ -1288,7 +1335,7 @@ impl<T, const N: usize> TryFrom<alloc::vec::Vec<T>> for Vec<T, N> {
|
||||
///
|
||||
/// Returns `Err` if the length of the `alloc::vec::Vec<T>` is greater than `N`.
|
||||
fn try_from(alloc_vec: alloc::vec::Vec<T>) -> Result<Self, Self::Error> {
|
||||
let mut vec = Vec::new();
|
||||
let mut vec = Self::new();
|
||||
|
||||
for e in alloc_vec {
|
||||
// Push each element individually to allow handling capacity errors.
|
||||
@ -1301,7 +1348,7 @@ impl<T, const N: usize> TryFrom<alloc::vec::Vec<T>> for Vec<T, N> {
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
/// Converts the given `Vec<T, N>` into an `alloc::vec::Vec<T>`.
|
||||
impl<T, const N: usize> TryFrom<Vec<T, N>> for alloc::vec::Vec<T> {
|
||||
impl<T, LenT: LenType, const N: usize> TryFrom<Vec<T, N, LenT>> for alloc::vec::Vec<T> {
|
||||
type Error = alloc::collections::TryReserveError;
|
||||
|
||||
/// Converts the given `Vec<T, N>` into an `alloc::vec::Vec<T>`.
|
||||
@ -1309,8 +1356,8 @@ impl<T, const N: usize> TryFrom<Vec<T, N>> for alloc::vec::Vec<T> {
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if the `alloc::vec::Vec` fails to allocate memory.
|
||||
fn try_from(vec: Vec<T, N>) -> Result<Self, Self::Error> {
|
||||
let mut alloc_vec = alloc::vec::Vec::new();
|
||||
fn try_from(vec: Vec<T, N, LenT>) -> Result<Self, Self::Error> {
|
||||
let mut alloc_vec = Self::new();
|
||||
|
||||
// Allocate enough space for the elements, return an error if the
|
||||
// allocation fails.
|
||||
@ -1324,7 +1371,7 @@ impl<T, const N: usize> TryFrom<Vec<T, N>> for alloc::vec::Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
|
||||
impl<'a, T: Clone, LenT: LenType, const N: usize> TryFrom<&'a [T]> for Vec<T, N, LenT> {
|
||||
type Error = CapacityError;
|
||||
|
||||
fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
|
||||
@ -1332,7 +1379,7 @@ impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> Extend<T> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Extend<T> for VecInner<T, LenT, S> {
|
||||
fn extend<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
@ -1341,7 +1388,7 @@ impl<T, S: VecStorage<T> + ?Sized> Extend<T> for VecInner<T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S: VecStorage<T> + ?Sized> Extend<&'a T> for VecInner<T, S>
|
||||
impl<'a, T, LenT: LenType, S: VecStorage<T> + ?Sized> Extend<&'a T> for VecInner<T, LenT, S>
|
||||
where
|
||||
T: 'a + Copy,
|
||||
{
|
||||
@ -1353,7 +1400,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> hash::Hash for VecInner<T, S>
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> hash::Hash for VecInner<T, LenT, S>
|
||||
where
|
||||
T: core::hash::Hash,
|
||||
{
|
||||
@ -1362,7 +1409,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a VecInner<T, S> {
|
||||
impl<'a, T, LenT: LenType, S: VecStorage<T> + ?Sized> IntoIterator for &'a VecInner<T, LenT, S> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
|
||||
@ -1371,7 +1418,9 @@ impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a VecInner<T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a mut VecInner<T, S> {
|
||||
impl<'a, T, LenT: LenType, S: VecStorage<T> + ?Sized> IntoIterator
|
||||
for &'a mut VecInner<T, LenT, S>
|
||||
{
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = slice::IterMut<'a, T>;
|
||||
|
||||
@ -1380,7 +1429,7 @@ impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a mut VecInner<T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> FromIterator<T> for Vec<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize> FromIterator<T> for Vec<T, N, LenT> {
|
||||
fn from_iter<I>(iter: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
@ -1396,24 +1445,24 @@ impl<T, const N: usize> FromIterator<T> for Vec<T, N> {
|
||||
/// An iterator that moves out of an [`Vec`][`Vec`].
|
||||
///
|
||||
/// This struct is created by calling the `into_iter` method on [`Vec`][`Vec`].
|
||||
pub struct IntoIter<T, const N: usize> {
|
||||
vec: Vec<T, N>,
|
||||
next: usize,
|
||||
pub struct IntoIter<T, const N: usize, LenT: LenType> {
|
||||
vec: Vec<T, N, LenT>,
|
||||
next: LenT,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
impl<T, LenT: LenType, const N: usize> Iterator for IntoIter<T, N, LenT> {
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.next < self.vec.len() {
|
||||
if self.next < self.vec.len {
|
||||
let item = unsafe {
|
||||
self.vec
|
||||
.buffer
|
||||
.buffer
|
||||
.get_unchecked_mut(self.next)
|
||||
.get_unchecked_mut(self.next.into_usize())
|
||||
.as_ptr()
|
||||
.read()
|
||||
};
|
||||
self.next += 1;
|
||||
self.next += LenT::ONE;
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
@ -1421,105 +1470,128 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Clone for IntoIter<T, N>
|
||||
impl<T, LenT: LenType, const N: usize> Clone for IntoIter<T, N, LenT>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
if self.next < self.vec.len() {
|
||||
if self.next < self.vec.len {
|
||||
let s = unsafe {
|
||||
slice::from_raw_parts(
|
||||
self.vec.buffer.buffer.as_ptr().cast::<T>().add(self.next),
|
||||
self.vec.len() - self.next,
|
||||
self.vec
|
||||
.buffer
|
||||
.buffer
|
||||
.as_ptr()
|
||||
.cast::<T>()
|
||||
.add(self.next.into_usize()),
|
||||
(self.vec.len - self.next).into_usize(),
|
||||
)
|
||||
};
|
||||
vec.extend_from_slice(s).ok();
|
||||
}
|
||||
|
||||
Self { vec, next: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Drop for IntoIter<T, N> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Drop all the elements that have not been moved out of vec
|
||||
ptr::drop_in_place(&mut self.vec.as_mut_slice()[self.next..]);
|
||||
// Prevent dropping of other elements
|
||||
self.vec.len = 0;
|
||||
Self {
|
||||
vec,
|
||||
next: LenT::ZERO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIterator for Vec<T, N> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T, N>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter { vec: self, next: 0 }
|
||||
impl<T, LenT: LenType, const N: usize> Drop for IntoIter<T, N, LenT> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Drop all the elements that have not been moved out of vec
|
||||
ptr::drop_in_place(&mut self.vec.as_mut_slice()[self.next.into_usize()..]);
|
||||
// Prevent dropping of other elements
|
||||
self.vec.len = LenT::ZERO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>>
|
||||
for VecInner<A, SA>
|
||||
impl<T, LenT: LenType, const N: usize> IntoIterator for Vec<T, N, LenT> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T, N, LenT>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter {
|
||||
vec: self,
|
||||
next: LenT::ZERO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, LenTA, LenTB, SA, SB> PartialEq<VecInner<B, LenTB, SB>> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTA: LenType,
|
||||
LenTB: LenType,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
SB: VecStorage<B> + ?Sized,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
self.as_slice().eq(other.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, const M: usize, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for [A; M]
|
||||
impl<A, B, LenTB, const M: usize, SB> PartialEq<VecInner<B, LenTB, SB>> for [A; M]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTB: LenType,
|
||||
SB: VecStorage<B>,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
self.eq(other.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SB: VecStorage<B> + ?Sized, const M: usize> PartialEq<VecInner<B, SB>> for &[A; M]
|
||||
impl<A, B, LenTB, SB, const M: usize> PartialEq<VecInner<B, LenTB, SB>> for &[A; M]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTB: LenType,
|
||||
SB: VecStorage<B>,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
(*self).eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for [A]
|
||||
impl<A, B, LenTB, SB> PartialEq<VecInner<B, LenTB, SB>> for [A]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTB: LenType,
|
||||
SB: VecStorage<B>,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
self.eq(other.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for &[A]
|
||||
impl<A, B, LenTB, SB> PartialEq<VecInner<B, LenTB, SB>> for &[A]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTB: LenType,
|
||||
SB: VecStorage<B>,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
(*self).eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for &mut [A]
|
||||
impl<A, B, LenTB: LenType, SB: VecStorage<B>> PartialEq<VecInner<B, LenTB, SB>> for &mut [A]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
fn eq(&self, other: &VecInner<B, SB>) -> bool {
|
||||
fn eq(&self, other: &VecInner<B, LenTB, SB>) -> bool {
|
||||
(**self).eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized, const N: usize> PartialEq<[B; N]> for VecInner<A, SA>
|
||||
impl<A, B, LenTA: LenType, SA, const N: usize> PartialEq<[B; N]> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[B; N]) -> bool {
|
||||
@ -1527,9 +1599,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized, const N: usize> PartialEq<&[B; N]> for VecInner<A, SA>
|
||||
impl<A, B, LenTA, SA, const N: usize> PartialEq<&[B; N]> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTA: LenType,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&[B; N]) -> bool {
|
||||
@ -1537,9 +1611,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<[B]> for VecInner<A, SA>
|
||||
impl<A, B, LenTA, SA> PartialEq<[B]> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTA: LenType,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[B]) -> bool {
|
||||
@ -1547,9 +1623,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<&[B]> for VecInner<A, SA>
|
||||
impl<A, B, LenTA, SA> PartialEq<&[B]> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTA: LenType,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&[B]) -> bool {
|
||||
@ -1557,9 +1635,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<&mut [B]> for VecInner<A, SA>
|
||||
impl<A, B, LenTA, SA> PartialEq<&mut [B]> for VecInner<A, LenTA, SA>
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
LenTA: LenType,
|
||||
SA: VecStorage<A> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&mut [B]) -> bool {
|
||||
@ -1568,19 +1648,19 @@ where
|
||||
}
|
||||
|
||||
// Implements Eq if underlying data is Eq
|
||||
impl<T, S: VecStorage<T> + ?Sized> Eq for VecInner<T, S> where T: Eq {}
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Eq for VecInner<T, LenT, S> where T: Eq {}
|
||||
|
||||
impl<T, SA: VecStorage<T> + ?Sized, SB: VecStorage<T> + ?Sized> PartialOrd<VecInner<T, SA>>
|
||||
for VecInner<T, SB>
|
||||
impl<T, LenTA: LenType, LenTB: LenType, SA: VecStorage<T> + ?Sized, SB: VecStorage<T> + ?Sized>
|
||||
PartialOrd<VecInner<T, LenTA, SA>> for VecInner<T, LenTB, SB>
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
fn partial_cmp(&self, other: &VecInner<T, SA>) -> Option<Ordering> {
|
||||
fn partial_cmp(&self, other: &VecInner<T, LenTA, SA>) -> Option<Ordering> {
|
||||
self.as_slice().partial_cmp(other.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> Ord for VecInner<T, S>
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> Ord for VecInner<T, LenT, S>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
@ -1590,7 +1670,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> ops::Deref for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> ops::Deref for VecInner<T, LenT, S> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -1598,52 +1678,52 @@ impl<T, S: VecStorage<T> + ?Sized> ops::Deref for VecInner<T, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> ops::DerefMut for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> ops::DerefMut for VecInner<T, LenT, S> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.as_mut_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> borrow::Borrow<[T]> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> borrow::Borrow<[T]> for VecInner<T, LenT, S> {
|
||||
fn borrow(&self) -> &[T] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
impl<T, S: VecStorage<T> + ?Sized> borrow::BorrowMut<[T]> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> borrow::BorrowMut<[T]> for VecInner<T, LenT, S> {
|
||||
fn borrow_mut(&mut self) -> &mut [T] {
|
||||
self.as_mut_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> AsRef<Self> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> AsRef<Self> for VecInner<T, LenT, S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> AsMut<Self> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> AsMut<Self> for VecInner<T, LenT, S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> AsRef<[T]> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> AsRef<[T]> for VecInner<T, LenT, S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: VecStorage<T> + ?Sized> AsMut<[T]> for VecInner<T, S> {
|
||||
impl<T, LenT: LenType, S: VecStorage<T> + ?Sized> AsMut<[T]> for VecInner<T, LenT, S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Clone for Vec<T, N>
|
||||
impl<T, const N: usize, LenT: LenType> Clone for Vec<T, N, LenT>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
@ -1726,7 +1806,7 @@ mod tests {
|
||||
{
|
||||
let v: Vec<Droppable, 2> = Vec::new();
|
||||
let v: Box<Vec<Droppable, 2>> = Box::new(v);
|
||||
let mut v: Box<VecView<Droppable>> = v;
|
||||
let mut v: Box<VecView<Droppable, u8>> = v;
|
||||
v.push(Droppable::new()).ok().unwrap();
|
||||
v.push(Droppable::new()).ok().unwrap();
|
||||
assert_eq!(Droppable::count(), 2);
|
||||
@ -1739,7 +1819,7 @@ mod tests {
|
||||
{
|
||||
let v: Vec<Droppable, 2> = Vec::new();
|
||||
let v: Box<Vec<Droppable, 2>> = Box::new(v);
|
||||
let mut v: Box<VecView<Droppable>> = v;
|
||||
let mut v: Box<VecView<Droppable, u8>> = v;
|
||||
v.push(Droppable::new()).ok().unwrap();
|
||||
v.push(Droppable::new()).ok().unwrap();
|
||||
assert_eq!(Droppable::count(), 2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user