Merge pull request #502 from Nitrokey/vec-covariance

Re-introduce covariance for containers
This commit is contained in:
Daniel Egger 2025-03-18 19:37:45 +00:00 committed by GitHub
commit 3c97d2f035
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 503 additions and 199 deletions

View File

@ -17,10 +17,7 @@ use core::{
ptr, slice, ptr, slice,
}; };
use crate::{ use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
storage::{OwnedStorage, Storage, ViewStorage},
vec::{Vec, VecInner},
};
/// Min-heap /// Min-heap
pub enum Min {} pub enum Min {}
@ -54,11 +51,11 @@ mod private {
impl private::Sealed for Max {} impl private::Sealed for Max {}
impl private::Sealed for Min {} impl private::Sealed for Min {}
/// Base struct for [`BinaryHeap`] and [`BinaryHeapView`], generic over the [`Storage`]. /// Base struct for [`BinaryHeap`] and [`BinaryHeapView`], generic over the [`VecStorage`].
/// ///
/// In most cases you should use [`BinaryHeap`] or [`BinaryHeapView`] directly. Only use this /// In most cases you should use [`BinaryHeap`] or [`BinaryHeapView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct BinaryHeapInner<T, K, S: Storage> { pub struct BinaryHeapInner<T, K, S: VecStorage<T> + ?Sized> {
pub(crate) _kind: PhantomData<K>, pub(crate) _kind: PhantomData<K>,
pub(crate) data: VecInner<T, S>, pub(crate) data: VecInner<T, S>,
} }
@ -109,7 +106,7 @@ pub struct BinaryHeapInner<T, K, S: Storage> {
/// // The heap should now be empty. /// // The heap should now be empty.
/// assert!(heap.is_empty()) /// assert!(heap.is_empty())
/// ``` /// ```
pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N>>; pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedVecStorage<T, N>>;
/// A priority queue implemented with a binary heap. /// A priority queue implemented with a binary heap.
/// ///
@ -158,7 +155,7 @@ pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N
/// // The heap should now be empty. /// // The heap should now be empty.
/// assert!(heap.is_empty()) /// assert!(heap.is_empty())
/// ``` /// ```
pub type BinaryHeapView<T, K> = BinaryHeapInner<T, K, ViewStorage>; pub type BinaryHeapView<T, K> = BinaryHeapInner<T, K, ViewVecStorage<T>>;
impl<T, K, const N: usize> BinaryHeap<T, K, N> { impl<T, K, const N: usize> BinaryHeap<T, K, N> {
/* Constructors */ /* Constructors */
@ -198,7 +195,7 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
} }
} }
impl<T, K, S: Storage> BinaryHeapInner<T, K, S> impl<T, K, S: VecStorage<T> + ?Sized> BinaryHeapInner<T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
@ -539,7 +536,7 @@ pub struct PeekMutInner<'a, T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
heap: &'a mut BinaryHeapInner<T, K, S>, heap: &'a mut BinaryHeapInner<T, K, S>,
sift: bool, sift: bool,
@ -550,20 +547,20 @@ where
/// ///
/// This `struct` is created by [`BinaryHeap::peek_mut`]. /// This `struct` is created by [`BinaryHeap::peek_mut`].
/// See its documentation for more. /// See its documentation for more.
pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedStorage<N>>; pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedVecStorage<T, N>>;
/// Structure wrapping a mutable reference to the greatest item on a /// Structure wrapping a mutable reference to the greatest item on a
/// `BinaryHeap`. /// `BinaryHeap`.
/// ///
/// This `struct` is created by [`BinaryHeapView::peek_mut`]. /// This `struct` is created by [`BinaryHeapView::peek_mut`].
/// See its documentation for more. /// See its documentation for more.
pub type PeekMutView<'a, T, K> = PeekMutInner<'a, T, K, ViewStorage>; pub type PeekMutView<'a, T, K> = PeekMutInner<'a, T, K, ViewVecStorage<T>>;
impl<T, K, S> Drop for PeekMutInner<'_, T, K, S> impl<T, K, S> Drop for PeekMutInner<'_, T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
fn drop(&mut self) { fn drop(&mut self) {
if self.sift { if self.sift {
@ -576,7 +573,7 @@ impl<T, K, S> Deref for PeekMutInner<'_, T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -590,7 +587,7 @@ impl<T, K, S> DerefMut for PeekMutInner<'_, T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
fn deref_mut(&mut self) -> &mut T { fn deref_mut(&mut self) -> &mut T {
debug_assert!(!self.heap.is_empty()); debug_assert!(!self.heap.is_empty());
@ -603,7 +600,7 @@ impl<'a, T, K, S> PeekMutInner<'a, T, K, S>
where where
T: Ord, T: Ord,
K: Kind, K: Kind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
/// Removes the peeked value from the heap and returns it. /// Removes the peeked value from the heap and returns it.
pub fn pop(mut this: PeekMutInner<'a, T, K, S>) -> T { pub fn pop(mut this: PeekMutInner<'a, T, K, S>) -> T {
@ -651,7 +648,7 @@ impl<T, K, S> fmt::Debug for BinaryHeapInner<T, K, S>
where where
K: Kind, K: Kind,
T: Ord + fmt::Debug, T: Ord + fmt::Debug,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish() f.debug_list().entries(self.iter()).finish()
@ -662,7 +659,7 @@ impl<'a, T, K, S> IntoIterator for &'a BinaryHeapInner<T, K, S>
where where
K: Kind, K: Kind,
T: Ord, T: Ord,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
type Item = &'a T; type Item = &'a T;
type IntoIter = slice::Iter<'a, T>; type IntoIter = slice::Iter<'a, T>;
@ -676,7 +673,7 @@ where
mod tests { mod tests {
use static_assertions::assert_not_impl_any; use static_assertions::assert_not_impl_any;
use super::{BinaryHeap, Max, Min}; use super::{BinaryHeap, BinaryHeapView, Max, Min};
// Ensure a `BinaryHeap` containing `!Send` values stays `!Send` itself. // Ensure a `BinaryHeap` containing `!Send` values stays `!Send` itself.
assert_not_impl_any!(BinaryHeap<*const (), Max, 4>: Send); assert_not_impl_any!(BinaryHeap<*const (), Max, 4>: Send);
@ -849,4 +846,13 @@ mod tests {
assert_eq!(heap.pop(), Some(1)); assert_eq!(heap.pop(), Some(1));
assert_eq!(heap.pop(), None); assert_eq!(heap.pop(), None);
} }
fn _test_variance<'a: 'b, 'b>(x: BinaryHeap<&'a (), Max, 42>) -> BinaryHeap<&'b (), Max, 42> {
x
}
fn _test_variance_view<'a: 'b, 'b, 'c>(
x: &'c BinaryHeapView<&'a (), Max>,
) -> &'c BinaryHeapView<&'b (), Max> {
x
}
} }

View File

@ -1,9 +1,12 @@
//! Defmt implementations for heapless types //! Defmt implementations for heapless types
use crate::{storage::Storage, string::StringInner, vec::VecInner}; use crate::{
string::StringInner,
vec::{VecInner, VecStorage},
};
use defmt::Formatter; use defmt::Formatter;
impl<T, S: Storage> defmt::Format for VecInner<T, S> impl<T, S: VecStorage<T> + ?Sized> defmt::Format for VecInner<T, S>
where where
T: defmt::Format, T: defmt::Format,
{ {
@ -12,7 +15,7 @@ where
} }
} }
impl<S: Storage> defmt::Format for StringInner<S> impl<S: VecStorage<u8> + ?Sized> defmt::Format for StringInner<S>
where where
u8: defmt::Format, u8: defmt::Format,
{ {

View File

@ -33,20 +33,22 @@
//! } //! }
//! ``` //! ```
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering; use core::cmp::Ordering;
use core::fmt; use core::fmt;
use core::iter::FusedIterator; use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::{ptr, slice}; use core::{ptr, slice};
use crate::storage::{OwnedStorage, Storage, ViewStorage}; use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage};
/// Base struct for [`Deque`] and [`DequeView`], generic over the [`Storage`]. /// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`].
/// ///
/// In most cases you should use [`Deque`] or [`DequeView`] directly. Only use this /// In most cases you should use [`Deque`] or [`DequeView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct DequeInner<T, S: Storage> { pub struct DequeInner<T, S: VecStorage<T> + ?Sized> {
// This phantomdata is required because otherwise rustc thinks that `T` is not used
phantom: PhantomData<T>,
/// Front index. Always 0..=(N-1) /// Front index. Always 0..=(N-1)
front: usize, front: usize,
/// Back index. Always 0..=(N-1). /// Back index. Always 0..=(N-1).
@ -55,7 +57,7 @@ pub struct DequeInner<T, S: Storage> {
/// Used to distinguish "empty" and "full" cases when `front == back`. /// Used to distinguish "empty" and "full" cases when `front == back`.
/// May only be `true` if `front == back`, always `false` otherwise. /// May only be `true` if `front == back`, always `false` otherwise.
full: bool, full: bool,
buffer: S::Buffer<MaybeUninit<T>>, buffer: S,
} }
/// A fixed capacity double-ended queue. /// A fixed capacity double-ended queue.
@ -92,7 +94,7 @@ pub struct DequeInner<T, S: Storage> {
/// println!("{}", x); /// println!("{}", x);
/// } /// }
/// ``` /// ```
pub type Deque<T, const N: usize> = DequeInner<T, OwnedStorage<N>>; pub type Deque<T, const N: usize> = DequeInner<T, OwnedVecStorage<T, N>>;
/// A double-ended queue with dynamic capacity. /// A double-ended queue with dynamic capacity.
/// ///
@ -131,7 +133,7 @@ pub type Deque<T, const N: usize> = DequeInner<T, OwnedStorage<N>>;
/// println!("{}", x); /// println!("{}", x);
/// } /// }
/// ``` /// ```
pub type DequeView<T> = DequeInner<T, ViewStorage>; pub type DequeView<T> = DequeInner<T, ViewVecStorage<T>>;
impl<T, const N: usize> Deque<T, N> { impl<T, const N: usize> Deque<T, N> {
const INIT: MaybeUninit<T> = MaybeUninit::uninit(); const INIT: MaybeUninit<T> = MaybeUninit::uninit();
@ -154,7 +156,10 @@ impl<T, const N: usize> Deque<T, N> {
crate::sealed::greater_than_0::<N>(); crate::sealed::greater_than_0::<N>();
Self { Self {
phantom: PhantomData,
buffer: VecStorageInner {
buffer: [Self::INIT; N], buffer: [Self::INIT; N],
},
front: 0, front: 0,
back: 0, back: 0,
full: false, full: false,
@ -192,7 +197,7 @@ impl<T, const N: usize> Deque<T, N> {
} }
} }
impl<T, S: Storage> DequeInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> DequeInner<T, S> {
/// Returns the maximum number of elements the deque can hold. /// Returns the maximum number of elements the deque can hold.
pub fn storage_capacity(&self) -> usize { pub fn storage_capacity(&self) -> usize {
self.buffer.borrow().len() self.buffer.borrow().len()
@ -866,7 +871,7 @@ impl<T, const N: usize> Default for Deque<T, N> {
} }
} }
impl<T, S: Storage> Drop for DequeInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> Drop for DequeInner<T, S> {
fn drop(&mut self) { fn drop(&mut self) {
// safety: `self` is left in an inconsistent state but it doesn't matter since // safety: `self` is left in an inconsistent state but it doesn't matter since
// it's getting dropped. Nothing should be able to observe `self` after drop. // it's getting dropped. Nothing should be able to observe `self` after drop.
@ -874,21 +879,21 @@ impl<T, S: Storage> Drop for DequeInner<T, S> {
} }
} }
impl<T: fmt::Debug, S: Storage> fmt::Debug for DequeInner<T, S> { impl<T: fmt::Debug, S: VecStorage<T> + ?Sized> fmt::Debug for DequeInner<T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self).finish() f.debug_list().entries(self).finish()
} }
} }
/// As with the standard library's `VecDeque`, items are added via `push_back`. /// As with the standard library's `VecDeque`, items are added via `push_back`.
impl<T, S: Storage> Extend<T> for DequeInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> Extend<T> for DequeInner<T, S> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter { for item in iter {
self.push_back(item).ok().unwrap(); self.push_back(item).ok().unwrap();
} }
} }
} }
impl<'a, T: 'a + Copy, S: Storage> Extend<&'a T> for DequeInner<T, S> { impl<'a, T: 'a + Copy, S: VecStorage<T> + ?Sized> Extend<&'a T> for DequeInner<T, S> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.extend(iter.into_iter().copied()) self.extend(iter.into_iter().copied())
} }
@ -918,7 +923,7 @@ impl<T, const N: usize> IntoIterator for Deque<T, N> {
} }
} }
impl<'a, T, S: Storage> IntoIterator for &'a DequeInner<T, S> { impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a DequeInner<T, S> {
type Item = &'a T; type Item = &'a T;
type IntoIter = Iter<'a, T>; type IntoIter = Iter<'a, T>;
@ -927,7 +932,7 @@ impl<'a, T, S: Storage> IntoIterator for &'a DequeInner<T, S> {
} }
} }
impl<'a, T, S: Storage> IntoIterator for &'a mut DequeInner<T, S> { impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a mut DequeInner<T, S> {
type Item = &'a mut T; type Item = &'a mut T;
type IntoIter = IterMut<'a, T>; type IntoIter = IterMut<'a, T>;

View File

@ -31,8 +31,6 @@
//! assert_eq!(avg, 4); //! assert_eq!(avg, 4);
//! ``` //! ```
use core::borrow::Borrow;
use core::borrow::BorrowMut;
use core::fmt; use core::fmt;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
@ -40,18 +38,89 @@ use core::ops::Deref;
use core::ptr; use core::ptr;
use core::slice; use core::slice;
use crate::storage::OwnedStorage; mod storage {
use crate::storage::Storage; use core::mem::MaybeUninit;
use crate::storage::ViewStorage;
/// Base struct for [`HistoryBuffer`] and [`HistoryBufferView`], generic over the [`Storage`]. /// Trait defining how data for a container is stored.
///
/// There's two implementations available:
///
/// - [`OwnedHistBufStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
/// - [`ViewHistBufStorage`]: stores the data in an unsized `[T]`.
///
/// This allows [`HistoryBuffer`] to be generic over either sized or unsized storage. The [`histbuf`]
/// module contains a [`HistoryBufferInner`] struct that's generic on [`HistBufStorage`],
/// and two type aliases for convenience:
///
/// - [`HistBuf<T, N>`](super::HistoryBuffer) = `HistoryBufferInner<T, OwnedHistBufStorage<T, N>>`
/// - [`HistBufView<T>`](super::HistoryBufferView) = `HistoryBufferInner<T, ViewHistBufStorage<T>>`
///
/// `HistoryBuffer` can be unsized into `HistoryBufferView`, either by unsizing coercions such as `&mut HistoryBuffer -> &mut HistoryBufferView` or
/// `Box<HistoryBuffer> -> Box<HistoryBufferView>`, or explicitly with [`.as_view()`](super::HistoryBuffer::as_view) or [`.as_mut_view()`](super::HistoryBuffer::as_mut_view).
///
/// This trait is sealed, so you cannot implement it for your own types. You can only use
/// the implementations provided by this crate.
///
/// [`HistoryBufferInner`]: super::HistoryBufferInner
/// [`HistoryBuffer`]: super::HistoryBuffer
/// [`HistoryBufferView`]: super::HistoryBufferView
/// [`histbuf`]: super
#[allow(private_bounds)]
pub trait HistBufStorage<T>: HistBufSealedStorage<T> {}
pub trait HistBufSealedStorage<T> {
// part of the sealed trait so that no trait is publicly implemented by `OwnedHistBufStorage` besides `Storage`
fn borrow(&self) -> &[MaybeUninit<T>];
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>];
}
// One sealed layer of indirection to hide the internal details (The MaybeUninit).
pub struct HistBufStorageInner<T: ?Sized> {
pub(crate) buffer: T,
}
/// Implementation of [`HistBufStorage`] that stores the data in an array `[T; N]` whose size is known at compile time.
pub type OwnedHistBufStorage<T, const N: usize> = HistBufStorageInner<[MaybeUninit<T>; N]>;
/// Implementation of [`HistBufStorage`] that stores the data in an unsized `[T]`.
pub type ViewHistBufStorage<T> = HistBufStorageInner<[MaybeUninit<T>]>;
impl<T, const N: usize> HistBufSealedStorage<T> for OwnedHistBufStorage<T, N> {
fn borrow(&self) -> &[MaybeUninit<T>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
}
impl<T, const N: usize> HistBufStorage<T> for OwnedHistBufStorage<T, N> {}
impl<T> HistBufSealedStorage<T> for ViewHistBufStorage<T> {
fn borrow(&self) -> &[MaybeUninit<T>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
}
impl<T> HistBufStorage<T> for ViewHistBufStorage<T> {}
}
pub use storage::{HistBufStorage, OwnedHistBufStorage, ViewHistBufStorage};
use storage::HistBufStorageInner;
use self::storage::HistBufSealedStorage;
/// Base struct for [`HistoryBuffer`] and [`HistoryBufferView`], generic over the [`HistBufStorage`].
/// ///
/// In most cases you should use [`HistoryBuffer`] or [`HistoryBufferView`] directly. Only use this /// In most cases you should use [`HistoryBuffer`] or [`HistoryBufferView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct HistoryBufferInner<T, S: Storage> { pub struct HistoryBufferInner<T, S: HistBufStorage<T> + ?Sized> {
// This phantomdata is required because otherwise rustc thinks that `T` is not used
phantom: PhantomData<T>,
write_at: usize, write_at: usize,
filled: bool, filled: bool,
data: S::Buffer<MaybeUninit<T>>, data: S,
} }
/// A "history buffer", similar to a write-only ring buffer of fixed length. /// A "history buffer", similar to a write-only ring buffer of fixed length.
@ -86,7 +155,7 @@ pub struct HistoryBufferInner<T, S: Storage> {
/// let avg = buf.as_slice().iter().sum::<usize>() / buf.len(); /// let avg = buf.as_slice().iter().sum::<usize>() / buf.len();
/// assert_eq!(avg, 4); /// assert_eq!(avg, 4);
/// ``` /// ```
pub type HistoryBuffer<T, const N: usize> = HistoryBufferInner<T, OwnedStorage<N>>; pub type HistoryBuffer<T, const N: usize> = HistoryBufferInner<T, OwnedHistBufStorage<T, N>>;
/// A "view" into a [`HistoryBuffer`] /// A "view" into a [`HistoryBuffer`]
/// ///
@ -119,7 +188,7 @@ pub type HistoryBuffer<T, const N: usize> = HistoryBufferInner<T, OwnedStorage<N
/// let avg = buf.as_slice().iter().sum::<usize>() / buf.len(); /// let avg = buf.as_slice().iter().sum::<usize>() / buf.len();
/// assert_eq!(avg, 4); /// assert_eq!(avg, 4);
/// ``` /// ```
pub type HistoryBufferView<T> = HistoryBufferInner<T, ViewStorage>; pub type HistoryBufferView<T> = HistoryBufferInner<T, ViewHistBufStorage<T>>;
impl<T, const N: usize> HistoryBuffer<T, N> { impl<T, const N: usize> HistoryBuffer<T, N> {
const INIT: MaybeUninit<T> = MaybeUninit::uninit(); const INIT: MaybeUninit<T> = MaybeUninit::uninit();
@ -143,11 +212,26 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
crate::sealed::greater_than_0::<N>(); crate::sealed::greater_than_0::<N>();
Self { Self {
data: [Self::INIT; N], phantom: PhantomData,
data: HistBufStorageInner {
buffer: [Self::INIT; N],
},
write_at: 0, write_at: 0,
filled: false, filled: false,
} }
} }
/// Get a reference to the `HistoryBuffer`, erasing the `N` const-generic.
#[inline]
pub const fn as_view(&self) -> &HistoryBufferView<T> {
self
}
/// Get a mutable reference to the `HistoryBuffer`, erasing the `N` const-generic.
#[inline]
pub fn as_mut_view(&mut self) -> &mut HistoryBufferView<T> {
self
}
} }
impl<T, const N: usize> HistoryBuffer<T, N> impl<T, const N: usize> HistoryBuffer<T, N>
@ -169,13 +253,16 @@ where
#[inline] #[inline]
pub fn new_with(t: T) -> Self { pub fn new_with(t: T) -> Self {
Self { Self {
data: [MaybeUninit::new(t); N], phantom: PhantomData,
data: HistBufStorageInner {
buffer: [MaybeUninit::new(t); N],
},
write_at: 0, write_at: 0,
filled: true, filled: true,
} }
} }
} }
impl<T: Copy, S: Storage> HistoryBufferInner<T, S> { impl<T: Copy, S: HistBufStorage<T> + ?Sized> HistoryBufferInner<T, S> {
/// Clears the buffer, replacing every element with the given value. /// Clears the buffer, replacing every element with the given value.
pub fn clear_with(&mut self, t: T) { pub fn clear_with(&mut self, t: T) {
// SAFETY: we reset the values just after // SAFETY: we reset the values just after
@ -189,7 +276,7 @@ impl<T: Copy, S: Storage> HistoryBufferInner<T, S> {
} }
} }
impl<T, S: Storage> HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> HistoryBufferInner<T, S> {
/// Clears the buffer /// Clears the buffer
pub fn clear(&mut self) { pub fn clear(&mut self) {
// SAFETY: we reset the values just after // SAFETY: we reset the values just after
@ -199,7 +286,7 @@ impl<T, S: Storage> HistoryBufferInner<T, S> {
} }
} }
impl<T, S: Storage> HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> HistoryBufferInner<T, S> {
unsafe fn drop_contents(&mut self) { unsafe fn drop_contents(&mut self) {
unsafe { unsafe {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut( ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
@ -407,7 +494,7 @@ impl<T, S: Storage> HistoryBufferInner<T, S> {
} }
} }
impl<T, S: Storage> Extend<T> for HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> Extend<T> for HistoryBufferInner<T, S> {
fn extend<I>(&mut self, iter: I) fn extend<I>(&mut self, iter: I)
where where
I: IntoIterator<Item = T>, I: IntoIterator<Item = T>,
@ -418,7 +505,7 @@ impl<T, S: Storage> Extend<T> for HistoryBufferInner<T, S> {
} }
} }
impl<'a, T, S: Storage> Extend<&'a T> for HistoryBufferInner<T, S> impl<'a, T, S: HistBufStorage<T> + ?Sized> Extend<&'a T> for HistoryBufferInner<T, S>
where where
T: 'a + Clone, T: 'a + Clone,
{ {
@ -436,7 +523,7 @@ where
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut ret = Self::new(); let mut ret = Self::new();
for (new, old) in ret.data.iter_mut().zip(self.as_slice()) { for (new, old) in ret.data.borrow_mut().iter_mut().zip(self.as_slice()) {
new.write(old.clone()); new.write(old.clone());
} }
ret.filled = self.filled; ret.filled = self.filled;
@ -445,13 +532,13 @@ where
} }
} }
impl<T, S: Storage> Drop for HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> Drop for HistoryBufferInner<T, S> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { self.drop_contents() } unsafe { self.drop_contents() }
} }
} }
impl<T, S: Storage> Deref for HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> Deref for HistoryBufferInner<T, S> {
type Target = [T]; type Target = [T];
fn deref(&self) -> &[T] { fn deref(&self) -> &[T] {
@ -459,14 +546,14 @@ impl<T, S: Storage> Deref for HistoryBufferInner<T, S> {
} }
} }
impl<T, S: Storage> AsRef<[T]> for HistoryBufferInner<T, S> { impl<T, S: HistBufStorage<T> + ?Sized> AsRef<[T]> for HistoryBufferInner<T, S> {
#[inline] #[inline]
fn as_ref(&self) -> &[T] { fn as_ref(&self) -> &[T] {
self self
} }
} }
impl<T, S: Storage> fmt::Debug for HistoryBufferInner<T, S> impl<T, S: HistBufStorage<T> + ?Sized> fmt::Debug for HistoryBufferInner<T, S>
where where
T: fmt::Debug, T: fmt::Debug,
{ {
@ -481,7 +568,7 @@ impl<T, const N: usize> Default for HistoryBuffer<T, N> {
} }
} }
impl<T, S: Storage> PartialEq for HistoryBufferInner<T, S> impl<T, S: HistBufStorage<T> + ?Sized> PartialEq for HistoryBufferInner<T, S>
where where
T: PartialEq, T: PartialEq,
{ {
@ -490,11 +577,11 @@ where
} }
} }
/// Base struct for [`OldestOrdered`] and [`OldestOrderedView`], generic over the [`Storage`]. /// Base struct for [`OldestOrdered`] and [`OldestOrderedView`], generic over the [`HistBufStorage`].
/// ///
/// In most cases you should use [`OldestOrdered`] or [`OldestOrderedView`] directly. Only use this /// In most cases you should use [`OldestOrdered`] or [`OldestOrderedView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct OldestOrderedInner<'a, T, S: Storage> { pub struct OldestOrderedInner<'a, T, S: HistBufStorage<T> + ?Sized> {
phantom: PhantomData<S>, phantom: PhantomData<S>,
inner: core::iter::Chain<core::slice::Iter<'a, T>, core::slice::Iter<'a, T>>, inner: core::iter::Chain<core::slice::Iter<'a, T>, core::slice::Iter<'a, T>>,
} }
@ -502,11 +589,12 @@ pub struct OldestOrderedInner<'a, T, S: Storage> {
/// Double ended iterator on the underlying buffer ordered from the oldest data /// Double ended iterator on the underlying buffer ordered from the oldest data
/// to the newest /// to the newest
/// This type exists for backwards compatibility. It is always better to convert it to an [`OldestOrderedView`] with [`into_view`](OldestOrdered::into_view) /// This type exists for backwards compatibility. It is always better to convert it to an [`OldestOrderedView`] with [`into_view`](OldestOrdered::into_view)
pub type OldestOrdered<'a, T, const N: usize> = OldestOrderedInner<'a, T, OwnedStorage<N>>; pub type OldestOrdered<'a, T, const N: usize> =
OldestOrderedInner<'a, T, OwnedHistBufStorage<T, N>>;
/// Double ended iterator on the underlying buffer ordered from the oldest data /// Double ended iterator on the underlying buffer ordered from the oldest data
/// to the newest /// to the newest
pub type OldestOrderedView<'a, T> = OldestOrderedInner<'a, T, ViewStorage>; pub type OldestOrderedView<'a, T> = OldestOrderedInner<'a, T, ViewHistBufStorage<T>>;
impl<'a, T, const N: usize> OldestOrdered<'a, T, N> { impl<'a, T, const N: usize> OldestOrdered<'a, T, N> {
/// Remove the `N` const-generic parameter from the iterator /// Remove the `N` const-generic parameter from the iterator
@ -534,7 +622,7 @@ impl<'a, T> OldestOrderedView<'a, T> {
} }
} }
impl<T, S: Storage> Clone for OldestOrderedInner<'_, T, S> { impl<T, S: HistBufStorage<T> + ?Sized> Clone for OldestOrderedInner<'_, T, S> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
phantom: PhantomData, phantom: PhantomData,
@ -543,7 +631,7 @@ impl<T, S: Storage> Clone for OldestOrderedInner<'_, T, S> {
} }
} }
impl<'a, T, S: Storage> Iterator for OldestOrderedInner<'a, T, S> { impl<'a, T, S: HistBufStorage<T> + ?Sized> Iterator for OldestOrderedInner<'a, T, S> {
type Item = &'a T; type Item = &'a T;
fn next(&mut self) -> Option<&'a T> { fn next(&mut self) -> Option<&'a T> {
@ -568,7 +656,7 @@ mod tests {
use static_assertions::assert_not_impl_any; use static_assertions::assert_not_impl_any;
use super::HistoryBuffer; use super::{HistoryBuffer, HistoryBufferView};
// Ensure a `HistoryBuffer` containing `!Send` values stays `!Send` itself. // Ensure a `HistoryBuffer` containing `!Send` values stays `!Send` itself.
assert_not_impl_any!(HistoryBuffer<*const (), 4>: Send); assert_not_impl_any!(HistoryBuffer<*const (), 4>: Send);
@ -855,4 +943,13 @@ mod tests {
x.clear(); x.clear();
assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3); assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3);
} }
fn _test_variance<'a: 'b, 'b>(x: HistoryBuffer<&'a (), 42>) -> HistoryBuffer<&'b (), 42> {
x
}
fn _test_variance_view<'a: 'b, 'b, 'c>(
x: &'c HistoryBufferView<&'a ()>,
) -> &'c HistoryBufferView<&'b ()> {
x
}
} }

View File

@ -4,26 +4,22 @@
use core::{borrow::Borrow, fmt, mem, ops, slice}; use core::{borrow::Borrow, fmt, mem, ops, slice};
use crate::{ use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
storage::{OwnedStorage, Storage, ViewStorage},
vec::VecInner,
Vec,
};
/// Base struct for [`LinearMap`] and [`LinearMapView`] /// Base struct for [`LinearMap`] and [`LinearMapView`]
pub struct LinearMapInner<K, V, S: Storage> { pub struct LinearMapInner<K, V, S: VecStorage<(K, V)> + ?Sized> {
pub(crate) buffer: VecInner<(K, V), S>, pub(crate) buffer: VecInner<(K, V), S>,
} }
/// A fixed capacity map/dictionary that performs lookups via linear search. /// A fixed capacity map/dictionary that performs lookups via linear search.
/// ///
/// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1). /// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).
pub type LinearMap<K, V, const N: usize> = LinearMapInner<K, V, OwnedStorage<N>>; pub type LinearMap<K, V, const N: usize> = LinearMapInner<K, V, OwnedVecStorage<(K, V), N>>;
/// A dynamic capacity map/dictionary that performs lookups via linear search. /// A dynamic capacity map/dictionary that performs lookups via linear search.
/// ///
/// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1). /// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).
pub type LinearMapView<K, V> = LinearMapInner<K, V, ViewStorage>; pub type LinearMapView<K, V> = LinearMapInner<K, V, ViewVecStorage<(K, V)>>;
impl<K, V, const N: usize> LinearMap<K, V, N> { impl<K, V, const N: usize> LinearMap<K, V, N> {
/// Creates an empty `LinearMap`. /// Creates an empty `LinearMap`.
@ -54,7 +50,7 @@ impl<K, V, const N: usize> LinearMap<K, V, N> {
} }
} }
impl<K, V, S: Storage> LinearMapInner<K, V, S> impl<K, V, S: VecStorage<(K, V)> + ?Sized> LinearMapInner<K, V, S>
where where
K: Eq, K: Eq,
{ {
@ -392,7 +388,7 @@ where
} }
} }
impl<K, V, Q, S: Storage> ops::Index<&Q> for LinearMapInner<K, V, S> impl<K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::Index<&'_ Q> for LinearMapInner<K, V, S>
where where
K: Borrow<Q> + Eq, K: Borrow<Q> + Eq,
Q: Eq + ?Sized, Q: Eq + ?Sized,
@ -404,7 +400,7 @@ where
} }
} }
impl<K, V, Q, S: Storage> ops::IndexMut<&Q> for LinearMapInner<K, V, S> impl<K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::IndexMut<&'_ Q> for LinearMapInner<K, V, S>
where where
K: Borrow<Q> + Eq, K: Borrow<Q> + Eq,
Q: Eq + ?Sized, Q: Eq + ?Sized,
@ -435,7 +431,7 @@ where
} }
} }
impl<K, V, S: Storage> fmt::Debug for LinearMapInner<K, V, S> impl<K, V, S: VecStorage<(K, V)> + ?Sized> fmt::Debug for LinearMapInner<K, V, S>
where where
K: Eq + fmt::Debug, K: Eq + fmt::Debug,
V: fmt::Debug, V: fmt::Debug,
@ -493,7 +489,7 @@ where
} }
} }
impl<'a, K, V, S: Storage> IntoIterator for &'a LinearMapInner<K, V, S> impl<'a, K, V, S: VecStorage<(K, V)> + ?Sized> IntoIterator for &'a LinearMapInner<K, V, S>
where where
K: Eq, K: Eq,
{ {
@ -540,8 +536,8 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
} }
} }
impl<K, V, S1: Storage, S2: Storage> PartialEq<LinearMapInner<K, V, S2>> impl<K, V, S1: VecStorage<(K, V)> + ?Sized, S2: VecStorage<(K, V)> + ?Sized>
for LinearMapInner<K, V, S1> PartialEq<LinearMapInner<K, V, S2>> for LinearMapInner<K, V, S1>
where where
K: Eq, K: Eq,
V: PartialEq, V: PartialEq,
@ -554,7 +550,7 @@ where
} }
} }
impl<K, V, S: Storage> Eq for LinearMapInner<K, V, S> impl<K, V, S: VecStorage<(K, V)> + ?Sized> Eq for LinearMapInner<K, V, S>
where where
K: Eq, K: Eq,
V: PartialEq, V: PartialEq,
@ -565,7 +561,7 @@ where
mod test { mod test {
use static_assertions::assert_not_impl_any; use static_assertions::assert_not_impl_any;
use super::LinearMap; use super::{LinearMap, LinearMapView};
// Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself. // Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself.
assert_not_impl_any!(LinearMap<*const (), (), 4>: Send); assert_not_impl_any!(LinearMap<*const (), (), 4>: Send);
@ -640,4 +636,23 @@ mod test {
assert_eq!(v, src.remove(k).unwrap()); assert_eq!(v, src.remove(k).unwrap());
} }
} }
fn _test_variance_value<'a: 'b, 'b>(
x: LinearMap<u32, &'a (), 42>,
) -> LinearMap<u32, &'b (), 42> {
x
}
fn _test_variance_value_view<'a: 'b, 'b, 'c>(
x: &'c LinearMapView<u32, &'a ()>,
) -> &'c LinearMapView<u32, &'b ()> {
x
}
fn _test_variance_key<'a: 'b, 'b>(x: LinearMap<&'a (), u32, 42>) -> LinearMap<&'b (), u32, 42> {
x
}
fn _test_variance_key_view<'a: 'b, 'b, 'c>(
x: &'c LinearMapView<&'a (), u32>,
) -> &'c LinearMapView<&'b (), u32> {
x
}
} }

View File

@ -3,11 +3,10 @@ use core::hash::{BuildHasher, Hash};
use crate::{ use crate::{
binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind}, binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind},
deque::DequeInner, deque::DequeInner,
histbuf::HistoryBufferInner, histbuf::{HistBufStorage, HistoryBufferInner},
linear_map::LinearMapInner, linear_map::LinearMapInner,
storage::Storage,
string::StringInner, string::StringInner,
vec::VecInner, vec::{VecInner, VecStorage},
IndexMap, IndexSet, IndexMap, IndexSet,
}; };
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer}; use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
@ -18,7 +17,7 @@ impl<T, KIND, S> Serialize for BinaryHeapInner<T, KIND, S>
where where
T: Ord + Serialize, T: Ord + Serialize,
KIND: BinaryHeapKind, KIND: BinaryHeapKind,
S: Storage, S: VecStorage<T> + ?Sized,
{ {
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error> fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
where where
@ -49,7 +48,7 @@ where
} }
} }
impl<T, St: Storage> Serialize for VecInner<T, St> impl<T, St: VecStorage<T> + ?Sized> Serialize for VecInner<T, St>
where where
T: Serialize, T: Serialize,
{ {
@ -65,7 +64,7 @@ where
} }
} }
impl<T, S: Storage> Serialize for DequeInner<T, S> impl<T, S: VecStorage<T> + ?Sized> Serialize for DequeInner<T, S>
where where
T: Serialize, T: Serialize,
{ {
@ -81,7 +80,7 @@ where
} }
} }
impl<T, S: Storage> Serialize for HistoryBufferInner<T, S> impl<T, S: HistBufStorage<T> + ?Sized> Serialize for HistoryBufferInner<T, S>
where where
T: Serialize, T: Serialize,
{ {
@ -117,7 +116,7 @@ where
} }
} }
impl<K, V, S: Storage> Serialize for LinearMapInner<K, V, S> impl<K, V, S: VecStorage<(K, V)> + ?Sized> Serialize for LinearMapInner<K, V, S>
where where
K: Eq + Serialize, K: Eq + Serialize,
V: Serialize, V: Serialize,
@ -136,7 +135,7 @@ where
// String containers // String containers
impl<S: Storage> Serialize for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> Serialize for StringInner<S> {
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error> fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
where where
SER: Serializer, SER: Serializer,

View File

@ -26,7 +26,6 @@
//! //!
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap` //! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering; use core::cmp::Ordering;
use core::fmt; use core::fmt;
use core::marker::PhantomData; use core::marker::PhantomData;
@ -34,7 +33,80 @@ use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use core::ptr; use core::ptr;
use crate::storage::{OwnedStorage, Storage, ViewStorage}; mod storage {
use super::Node;
/// Trait defining how data for a container is stored.
///
/// There's two implementations available:
///
/// - [`OwnedSortedLinkedListStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
/// - [`ViewSortedLinkedListStorage`]: stores the data in an unsized `[T]`.
///
/// This allows [`SortedLinkedList`] to be generic over either sized or unsized storage. The [`sorted_linked_list`](super)
/// module contains a [`SortedLinkedListInner`] struct that's generic on [`SortedLinkedListStorage`],
/// and two type aliases for convenience:
///
/// - [`SortedLinkedList<T, Idx, N>`](super::SortedLinkedList) = `SortedLinkedListInner<T, OwnedSortedLinkedListStorage<T, Idx, N>>`
/// - [`SortedLinkedListView<T, Idx>`](super::SortedLinkedListView) = `SortedLinkedListInner<T, ViewSortedLinkedListStorage<T, Idx>>`
///
/// `SortedLinkedList` can be unsized into `SortedLinkedListView`, either by unsizing coercions such as `&mut SortedLinkedList -> &mut SortedLinkedListView` or
/// `Box<SortedLinkedList> -> Box<SortedLinkedListView>`, or explicitly with [`.as_view()`](super::SortedLinkedList::as_view) or [`.as_mut_view()`](super::SortedLinkedList::as_mut_view).
///
/// This trait is sealed, so you cannot implement it for your own types. You can only use
/// the implementations provided by this crate.
///
/// [`SortedLinkedListInner`]: super::SortedLinkedListInner
/// [`SortedLinkedList`]: super::SortedLinkedList
/// [`SortedLinkedListView`]: super::SortedLinkedListView
#[allow(private_bounds)]
pub trait SortedLinkedListStorage<T, Idx>: SortedLinkedListSealedStorage<T, Idx> {}
pub trait SortedLinkedListSealedStorage<T, Idx> {
// part of the sealed trait so that no trait is publicly implemented by `OwnedSortedLinkedListStorage` besides `Storage`
fn borrow(&self) -> &[Node<T, Idx>];
fn borrow_mut(&mut self) -> &mut [Node<T, Idx>];
}
// One sealed layer of indirection to hide the internal details (The MaybeUninit).
pub struct SortedLinkedListStorageInner<T: ?Sized> {
pub(crate) buffer: T,
}
/// Implementation of [`SortedLinkedListStorage`] that stores the data in an array `[T; N]` whose size is known at compile time.
pub type OwnedSortedLinkedListStorage<T, Idx, const N: usize> =
SortedLinkedListStorageInner<[Node<T, Idx>; N]>;
/// Implementation of [`SortedLinkedListStorage`] that stores the data in an unsized `[T]`.
pub type ViewSortedLinkedListStorage<T, Idx> = SortedLinkedListStorageInner<[Node<T, Idx>]>;
impl<T, Idx, const N: usize> SortedLinkedListSealedStorage<T, Idx>
for OwnedSortedLinkedListStorage<T, Idx, N>
{
fn borrow(&self) -> &[Node<T, Idx>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [Node<T, Idx>] {
&mut self.buffer
}
}
impl<T, Idx, const N: usize> SortedLinkedListStorage<T, Idx>
for OwnedSortedLinkedListStorage<T, Idx, N>
{
}
impl<T, Idx> SortedLinkedListSealedStorage<T, Idx> for ViewSortedLinkedListStorage<T, Idx> {
fn borrow(&self) -> &[Node<T, Idx>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [Node<T, Idx>] {
&mut self.buffer
}
}
impl<T, Idx> SortedLinkedListStorage<T, Idx> for ViewSortedLinkedListStorage<T, Idx> {}
}
pub use storage::{
OwnedSortedLinkedListStorage, SortedLinkedListStorage, ViewSortedLinkedListStorage,
};
/// Trait for defining an index for the linked list, never implemented by users. /// Trait for defining an index for the linked list, never implemented by users.
pub trait SortedLinkedListIndex: Copy { pub trait SortedLinkedListIndex: Copy {
@ -86,27 +158,28 @@ pub struct Node<T, Idx> {
next: Idx, next: Idx,
} }
/// Base struct for [`SortedLinkedList`] and [`SortedLinkedListView`], generic over the [`Storage`]. /// Base struct for [`SortedLinkedList`] and [`SortedLinkedListView`], generic over the [`SortedLinkedListStorage`].
/// ///
/// In most cases you should use [`SortedLinkedList`] or [`SortedLinkedListView`] directly. Only use this /// In most cases you should use [`SortedLinkedList`] or [`SortedLinkedListView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct SortedLinkedListInner<T, Idx, K, S> pub struct SortedLinkedListInner<T, Idx, K, S>
where where
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
head: Idx, head: Idx,
free: Idx, free: Idx,
_kind: PhantomData<K>, phantom: PhantomData<(K, T)>,
list: S::Buffer<Node<T, Idx>>, list: S,
} }
/// The linked list. /// The linked list.
pub type SortedLinkedList<T, Idx, K, const N: usize> = pub type SortedLinkedList<T, Idx, K, const N: usize> =
SortedLinkedListInner<T, Idx, K, OwnedStorage<N>>; SortedLinkedListInner<T, Idx, K, OwnedSortedLinkedListStorage<T, Idx, N>>;
/// The linked list. /// The linked list.
pub type SortedLinkedListView<T, Idx, K> = SortedLinkedListInner<T, Idx, K, ViewStorage>; pub type SortedLinkedListView<T, Idx, K> =
SortedLinkedListInner<T, Idx, K, ViewSortedLinkedListStorage<T, Idx>>;
// Internal macro for generating indexes for the linkedlist and const new for the linked list // Internal macro for generating indexes for the linkedlist and const new for the linked list
macro_rules! impl_index_and_const_new { macro_rules! impl_index_and_const_new {
@ -168,10 +241,12 @@ macro_rules! impl_index_and_const_new {
crate::sealed::smaller_than::<N, $max_val>(); crate::sealed::smaller_than::<N, $max_val>();
let mut list = SortedLinkedList { let mut list = SortedLinkedList {
list: [Self::UNINIT; N], list: OwnedSortedLinkedListStorage {
buffer: [Self::UNINIT; N],
},
head: $name::none(), head: $name::none(),
free: unsafe { $name::new_unchecked(0) }, free: unsafe { $name::new_unchecked(0) },
_kind: PhantomData, phantom: PhantomData,
}; };
if N == 0 { if N == 0 {
@ -183,7 +258,7 @@ macro_rules! impl_index_and_const_new {
// Initialize indexes // Initialize indexes
while free < N - 1 { while free < N - 1 {
list.list[free].next = unsafe { $name::new_unchecked(free as $ty + 1) }; list.list.buffer[free].next = unsafe { $name::new_unchecked(free as $ty + 1) };
free += 1; free += 1;
} }
@ -215,7 +290,7 @@ where
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S> impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
where where
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
/// Internal access helper /// Internal access helper
#[inline(always)] #[inline(always)]
@ -267,7 +342,7 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
/// Pushes a value onto the list without checking if the list is full. /// Pushes a value onto the list without checking if the list is full.
/// ///
@ -545,7 +620,7 @@ where
} }
} }
/// Base struct for [`Iter`] and [`IterView`], generic over the [`Storage`]. /// Base struct for [`Iter`] and [`IterView`], generic over the [`SortedLinkedListStorage`].
/// ///
/// In most cases you should use [`Iter`] or [`IterView`] directly. Only use this /// In most cases you should use [`Iter`] or [`IterView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
@ -554,23 +629,24 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
list: &'a SortedLinkedListInner<T, Idx, K, S>, list: &'a SortedLinkedListInner<T, Idx, K, S>,
index: Idx, index: Idx,
} }
/// Iterator for the linked list. /// Iterator for the linked list.
pub type Iter<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, OwnedStorage<N>>; pub type Iter<'a, T, Idx, K, const N: usize> =
IterInner<'a, T, Idx, K, OwnedSortedLinkedListStorage<T, Idx, N>>;
/// Iterator for the linked list. /// Iterator for the linked list.
pub type IterView<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, ViewStorage>; pub type IterView<'a, T, Idx, K> = IterInner<'a, T, Idx, K, ViewSortedLinkedListStorage<T, Idx>>;
impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S> impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S>
where where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
type Item = &'a T; type Item = &'a T;
@ -584,7 +660,7 @@ where
} }
} }
/// Base struct for [`FindMut`] and [`FindMutView`], generic over the [`Storage`]. /// Base struct for [`FindMut`] and [`FindMutView`], generic over the [`SortedLinkedListStorage`].
/// ///
/// In most cases you should use [`FindMut`] or [`FindMutView`] directly. Only use this /// In most cases you should use [`FindMut`] or [`FindMutView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
@ -593,7 +669,7 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
list: &'a mut SortedLinkedListInner<T, Idx, K, S>, list: &'a mut SortedLinkedListInner<T, Idx, K, S>,
is_head: bool, is_head: bool,
@ -603,16 +679,18 @@ where
} }
/// Comes from [`SortedLinkedList::find_mut`]. /// Comes from [`SortedLinkedList::find_mut`].
pub type FindMut<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, OwnedStorage<N>>; pub type FindMut<'a, T, Idx, K, const N: usize> =
FindMutInner<'a, T, Idx, K, OwnedSortedLinkedListStorage<T, Idx, N>>;
/// Comes from [`SortedLinkedList::find_mut`]. /// Comes from [`SortedLinkedList::find_mut`].
pub type FindMutView<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, ViewStorage>; pub type FindMutView<'a, T, Idx, K, const N: usize> =
FindMutInner<'a, T, Idx, K, ViewSortedLinkedListStorage<T, Idx>>;
impl<T, Idx, K, S> FindMutInner<'_, T, Idx, K, S> impl<T, Idx, K, S> FindMutInner<'_, T, Idx, K, S>
where where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
fn pop_internal(&mut self) -> T { fn pop_internal(&mut self) -> T {
if self.is_head { if self.is_head {
@ -701,7 +779,7 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
fn drop(&mut self) { fn drop(&mut self) {
// Only resort the list if the element has changed // Only resort the list if the element has changed
@ -717,7 +795,7 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
type Target = T; type Target = T;
@ -732,7 +810,7 @@ where
T: Ord, T: Ord,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self.maybe_changed = true; self.maybe_changed = true;
@ -771,7 +849,7 @@ where
T: Ord + core::fmt::Debug, T: Ord + core::fmt::Debug,
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
K: Kind, K: Kind,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish() f.debug_list().entries(self.iter()).finish()
@ -781,7 +859,7 @@ where
impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S> impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S>
where where
Idx: SortedLinkedListIndex, Idx: SortedLinkedListIndex,
S: Storage, S: SortedLinkedListStorage<T, Idx> + ?Sized,
{ {
fn drop(&mut self) { fn drop(&mut self) {
let mut index = self.head; let mut index = self.head;
@ -927,4 +1005,15 @@ mod tests {
assert_eq!(ll.peek().unwrap(), &1001); assert_eq!(ll.peek().unwrap(), &1001);
} }
fn _test_variance<'a: 'b, 'b>(
x: SortedLinkedList<&'a (), LinkedIndexUsize, Max, 42>,
) -> SortedLinkedList<&'b (), LinkedIndexUsize, Max, 42> {
x
}
fn _test_variance_view<'a: 'b, 'b, 'c>(
x: &'c SortedLinkedListView<&'a (), LinkedIndexUsize, Max>,
) -> &'c SortedLinkedListView<&'b (), LinkedIndexUsize, Max> {
x
}
} }

View File

@ -11,11 +11,7 @@ use core::{
str::{self, Utf8Error}, str::{self, Utf8Error},
}; };
use crate::{ use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
storage::{OwnedStorage, Storage, ViewStorage},
vec::VecInner,
Vec,
};
mod drain; mod drain;
pub use drain::Drain; pub use drain::Drain;
@ -42,19 +38,19 @@ impl fmt::Display for FromUtf16Error {
} }
} }
/// Base struct for [`String`] and [`StringView`], generic over the [`Storage`]. /// Base struct for [`String`] and [`StringView`], generic over the [`VecStorage`].
/// ///
/// In most cases you should use [`String`] or [`StringView`] directly. Only use this /// 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. /// struct if you want to write code that's generic over both.
pub struct StringInner<S: Storage> { pub struct StringInner<S: VecStorage<u8> + ?Sized> {
vec: VecInner<u8, S>, vec: VecInner<u8, S>,
} }
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). /// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
pub type String<const N: usize> = StringInner<OwnedStorage<N>>; pub type String<const N: usize> = StringInner<OwnedVecStorage<u8, N>>;
/// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). /// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
pub type StringView = StringInner<ViewStorage>; pub type StringView = StringInner<ViewVecStorage<u8>>;
impl StringView { impl StringView {
/// Removes the specified range from the string in bulk, returning all /// Removes the specified range from the string in bulk, returning all
@ -349,7 +345,7 @@ impl<const N: usize> String<N> {
} }
} }
impl<S: Storage> StringInner<S> { impl<S: VecStorage<u8> + ?Sized> StringInner<S> {
/// Extracts a string slice containing the entire string. /// Extracts a string slice containing the entire string.
/// ///
/// # Examples /// # Examples
@ -690,26 +686,26 @@ impl<const N: usize> Clone for String<N> {
} }
} }
impl<S: Storage> fmt::Debug for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> fmt::Debug for StringInner<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as fmt::Debug>::fmt(self, f) <str as fmt::Debug>::fmt(self, f)
} }
} }
impl<S: Storage> fmt::Display for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> fmt::Display for StringInner<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as fmt::Display>::fmt(self, f) <str as fmt::Display>::fmt(self, f)
} }
} }
impl<S: Storage> hash::Hash for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> hash::Hash for StringInner<S> {
#[inline] #[inline]
fn hash<H: hash::Hasher>(&self, hasher: &mut H) { fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
<str as hash::Hash>::hash(self, hasher) <str as hash::Hash>::hash(self, hasher)
} }
} }
impl<S: Storage> fmt::Write for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> fmt::Write for StringInner<S> {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
self.push_str(s).map_err(|_| fmt::Error) self.push_str(s).map_err(|_| fmt::Error)
} }
@ -719,7 +715,7 @@ impl<S: Storage> fmt::Write for StringInner<S> {
} }
} }
impl<S: Storage> ops::Deref for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> ops::Deref for StringInner<S> {
type Target = str; type Target = str;
fn deref(&self) -> &str { fn deref(&self) -> &str {
@ -727,45 +723,47 @@ impl<S: Storage> ops::Deref for StringInner<S> {
} }
} }
impl<S: Storage> ops::DerefMut for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> ops::DerefMut for StringInner<S> {
fn deref_mut(&mut self) -> &mut str { fn deref_mut(&mut self) -> &mut str {
self.as_mut_str() self.as_mut_str()
} }
} }
impl<S: Storage> borrow::Borrow<str> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> borrow::Borrow<str> for StringInner<S> {
fn borrow(&self) -> &str { fn borrow(&self) -> &str {
self.as_str() self.as_str()
} }
} }
impl<S: Storage> borrow::BorrowMut<str> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> borrow::BorrowMut<str> for StringInner<S> {
fn borrow_mut(&mut self) -> &mut str { fn borrow_mut(&mut self) -> &mut str {
self.as_mut_str() self.as_mut_str()
} }
} }
impl<S: Storage> AsRef<str> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> AsRef<str> for StringInner<S> {
#[inline] #[inline]
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
self self
} }
} }
impl<S: Storage> AsRef<[u8]> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> AsRef<[u8]> for StringInner<S> {
#[inline] #[inline]
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
self.as_bytes() self.as_bytes()
} }
} }
impl<S1: Storage, S2: Storage> PartialEq<StringInner<S1>> for StringInner<S2> { impl<S1: VecStorage<u8> + ?Sized, S2: VecStorage<u8> + ?Sized> PartialEq<StringInner<S1>>
for StringInner<S2>
{
fn eq(&self, rhs: &StringInner<S1>) -> bool { fn eq(&self, rhs: &StringInner<S1>) -> bool {
str::eq(&**self, &**rhs) str::eq(&**self, &**rhs)
} }
} }
// String<N> == str // String<N> == str
impl<S: Storage> PartialEq<str> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> PartialEq<str> for StringInner<S> {
#[inline] #[inline]
fn eq(&self, other: &str) -> bool { fn eq(&self, other: &str) -> bool {
str::eq(self, other) str::eq(self, other)
@ -773,7 +771,7 @@ impl<S: Storage> PartialEq<str> for StringInner<S> {
} }
// String<N> == &'str // String<N> == &'str
impl<S: Storage> PartialEq<&str> for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> PartialEq<&str> for StringInner<S> {
#[inline] #[inline]
fn eq(&self, other: &&str) -> bool { fn eq(&self, other: &&str) -> bool {
str::eq(self, &other[..]) str::eq(self, &other[..])
@ -781,7 +779,7 @@ impl<S: Storage> PartialEq<&str> for StringInner<S> {
} }
// str == String<N> // str == String<N>
impl<S: Storage> PartialEq<StringInner<S>> for str { impl<S: VecStorage<u8> + ?Sized> PartialEq<StringInner<S>> for str {
#[inline] #[inline]
fn eq(&self, other: &StringInner<S>) -> bool { fn eq(&self, other: &StringInner<S>) -> bool {
str::eq(self, &other[..]) str::eq(self, &other[..])
@ -789,23 +787,25 @@ impl<S: Storage> PartialEq<StringInner<S>> for str {
} }
// &'str == String<N> // &'str == String<N>
impl<S: Storage> PartialEq<StringInner<S>> for &str { impl<S: VecStorage<u8> + ?Sized> PartialEq<StringInner<S>> for &str {
#[inline] #[inline]
fn eq(&self, other: &StringInner<S>) -> bool { fn eq(&self, other: &StringInner<S>) -> bool {
str::eq(self, &other[..]) str::eq(self, &other[..])
} }
} }
impl<S: Storage> Eq for StringInner<S> {} impl<S: VecStorage<u8> + ?Sized> Eq for StringInner<S> {}
impl<S1: Storage, S2: Storage> PartialOrd<StringInner<S1>> for StringInner<S2> { impl<S1: VecStorage<u8> + ?Sized, S2: VecStorage<u8> + ?Sized> PartialOrd<StringInner<S1>>
for StringInner<S2>
{
#[inline] #[inline]
fn partial_cmp(&self, other: &StringInner<S1>) -> Option<Ordering> { fn partial_cmp(&self, other: &StringInner<S1>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other) PartialOrd::partial_cmp(&**self, &**other)
} }
} }
impl<S: Storage> Ord for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> Ord for StringInner<S> {
#[inline] #[inline]
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other) Ord::cmp(&**self, &**other)

View File

@ -1,14 +1,17 @@
use crate::{storage::Storage, string::StringInner, vec::VecInner}; use crate::{
string::StringInner,
vec::{VecInner, VecStorage},
};
use ufmt_write::uWrite; use ufmt_write::uWrite;
impl<S: Storage> uWrite for StringInner<S> { impl<S: VecStorage<u8> + ?Sized> uWrite for StringInner<S> {
type Error = (); type Error = ();
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.push_str(s) self.push_str(s)
} }
} }
impl<S: Storage> uWrite for VecInner<u8, S> { impl<S: VecStorage<u8> + ?Sized> uWrite for VecInner<u8, S> {
type Error = (); type Error = ();
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.extend_from_slice(s.as_bytes()) self.extend_from_slice(s.as_bytes())

View File

@ -1,8 +1,8 @@
//! A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). //! A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html).
use core::borrow; use core::borrow;
use core::marker::PhantomData;
use core::{ use core::{
borrow::{Borrow, BorrowMut},
cmp::Ordering, cmp::Ordering,
fmt, hash, fmt, hash,
mem::{self, ManuallyDrop, MaybeUninit}, mem::{self, ManuallyDrop, MaybeUninit},
@ -11,18 +11,87 @@ use core::{
slice, slice,
}; };
use crate::storage::{OwnedStorage, Storage, ViewStorage};
mod drain; mod drain;
mod storage {
use core::mem::MaybeUninit;
/// Trait defining how data for a container is stored.
///
/// There's two implementations available:
///
/// - [`OwnedVecStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
/// - [`ViewVecStorage`]: stores the data in an unsized `[T]`.
///
/// This allows [`Vec`] to be generic over either sized or unsized storage. The [`vec`](super)
/// module contains a [`VecInner`] struct that's generic on [`VecStorage`],
/// and two type aliases for convenience:
///
/// - [`Vec<T, N>`](crate::vec::Vec) = `VecInner<T, OwnedStorage<T, N>>`
/// - [`VecView<T>`](crate::vec::VecView) = `VecInner<T, ViewStorage<T>>`
///
/// `Vec` can be unsized into `VecView`, either by unsizing coercions such as `&mut Vec -> &mut VecView` or
/// `Box<Vec> -> Box<VecView>`, or explicitly with [`.as_view()`](crate::vec::Vec::as_view) or [`.as_mut_view()`](crate::vec::Vec::as_mut_view).
///
/// This trait is sealed, so you cannot implement it for your own types. You can only use
/// the implementations provided by this crate.
///
/// [`VecInner`]: super::VecInner
/// [`Vec`]: super::Vec
/// [`VecView`]: super::VecView
#[allow(private_bounds)]
pub trait VecStorage<T>: VecSealedStorage<T> {}
pub trait VecSealedStorage<T> {
// part of the sealed trait so that no trait is publicly implemented by `OwnedVecStorage` besides `Storage`
fn borrow(&self) -> &[MaybeUninit<T>];
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>];
}
// One sealed layer of indirection to hide the internal details (The MaybeUninit).
pub struct VecStorageInner<T: ?Sized> {
pub(crate) buffer: T,
}
/// Implementation of [`VecStorage`] that stores the data in an array `[T; N]` whose size is known at compile time.
pub type OwnedVecStorage<T, const N: usize> = VecStorageInner<[MaybeUninit<T>; N]>;
/// Implementation of [`VecStorage`] that stores the data in an unsized `[T]`.
pub type ViewVecStorage<T> = VecStorageInner<[MaybeUninit<T>]>;
impl<T, const N: usize> VecSealedStorage<T> for OwnedVecStorage<T, N> {
fn borrow(&self) -> &[MaybeUninit<T>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
}
impl<T, const N: usize> VecStorage<T> for OwnedVecStorage<T, N> {}
impl<T> VecSealedStorage<T> for ViewVecStorage<T> {
fn borrow(&self) -> &[MaybeUninit<T>] {
&self.buffer
}
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
}
impl<T> VecStorage<T> for ViewVecStorage<T> {}
}
pub use storage::{OwnedVecStorage, VecStorage, ViewVecStorage};
pub(crate) use storage::VecStorageInner;
pub use drain::Drain; pub use drain::Drain;
/// Base struct for [`Vec`] and [`VecView`], generic over the [`Storage`]. /// Base struct for [`Vec`] and [`VecView`], generic over the [`VecStorage`].
/// ///
/// In most cases you should use [`Vec`] or [`VecView`] directly. Only use this /// 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. /// struct if you want to write code that's generic over both.
pub struct VecInner<T, S: Storage> { pub struct VecInner<T, S: VecStorage<T> + ?Sized> {
phantom: PhantomData<T>,
len: usize, len: usize,
buffer: S::Buffer<MaybeUninit<T>>, buffer: S,
} }
/// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). /// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html).
@ -62,7 +131,7 @@ pub struct VecInner<T, S: Storage> {
/// let vec: Vec<u8, 10> = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); /// 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, OwnedStorage<N>>; pub type Vec<T, const N: usize> = VecInner<T, OwnedVecStorage<T, N>>;
/// A [`Vec`] with dynamic capacity /// A [`Vec`] with dynamic capacity
/// ///
@ -85,7 +154,7 @@ pub type Vec<T, const N: usize> = VecInner<T, OwnedStorage<N>>;
/// mut_view.push(5); /// mut_view.push(5);
/// assert_eq!(vec, [1, 2, 3, 4, 5]); /// assert_eq!(vec, [1, 2, 3, 4, 5]);
/// ``` /// ```
pub type VecView<T> = VecInner<T, ViewStorage>; pub type VecView<T> = VecInner<T, ViewVecStorage<T>>;
impl<T, const N: usize> Vec<T, N> { impl<T, const N: usize> Vec<T, N> {
const ELEM: MaybeUninit<T> = MaybeUninit::uninit(); const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
@ -106,8 +175,9 @@ impl<T, const N: usize> Vec<T, N> {
/// ``` /// ```
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
phantom: PhantomData,
len: 0, len: 0,
buffer: Self::INIT, buffer: VecStorageInner { buffer: Self::INIT },
} }
} }
@ -152,6 +222,7 @@ impl<T, const N: usize> Vec<T, N> {
if N == M { if N == M {
Self { Self {
phantom: PhantomData,
len: N, len: N,
// NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit<T>; N] // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit<T>; N]
// have the same layout when N == M. // have the same layout when N == M.
@ -160,7 +231,7 @@ impl<T, const N: usize> Vec<T, N> {
} else { } else {
let mut v = Vec::<T, N>::new(); let mut v = Vec::<T, N>::new();
for (src_elem, dst_elem) in src.iter().zip(v.buffer.iter_mut()) { for (src_elem, dst_elem) in src.iter().zip(v.buffer.buffer.iter_mut()) {
// NOTE(unsafe) src element is not going to drop as src itself // NOTE(unsafe) src element is not going to drop as src itself
// is wrapped in a ManuallyDrop. // is wrapped in a ManuallyDrop.
dst_elem.write(unsafe { ptr::read(src_elem) }); dst_elem.write(unsafe { ptr::read(src_elem) });
@ -296,7 +367,7 @@ impl<T, const N: usize> Vec<T, N> {
/// ///
/// This method is not available on a `VecView`, use [`storage_len`](VecInner::storage_capacity) instead /// This method is not available on a `VecView`, use [`storage_len`](VecInner::storage_capacity) instead
pub const fn capacity(&self) -> usize { pub const fn capacity(&self) -> usize {
self.buffer.len() self.buffer.buffer.len()
} }
} }
@ -365,7 +436,7 @@ impl<T> VecView<T> {
} }
} }
impl<T, S: Storage> VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
/// Returns a raw pointer to the vectors buffer. /// Returns a raw pointer to the vectors buffer.
pub fn as_ptr(&self) -> *const T { pub fn as_ptr(&self) -> *const T {
self.buffer.borrow().as_ptr() as *const T self.buffer.borrow().as_ptr() as *const T
@ -993,14 +1064,14 @@ impl<T, S: Storage> VecInner<T, S> {
// This drop guard will be invoked when predicate or `drop` of element panicked. // 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. // 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. // In cases when predicate and `drop` never panick, it will be optimized out.
struct BackshiftOnDrop<'a, T, S: Storage> { struct BackshiftOnDrop<'a, T, S: VecStorage<T> + ?Sized> {
v: &'a mut VecInner<T, S>, v: &'a mut VecInner<T, S>,
processed_len: usize, processed_len: usize,
deleted_cnt: usize, deleted_cnt: usize,
original_len: usize, original_len: usize,
} }
impl<T, S: Storage> Drop for BackshiftOnDrop<'_, T, S> { impl<T, S: VecStorage<T> + ?Sized> Drop for BackshiftOnDrop<'_, T, S> {
fn drop(&mut self) { fn drop(&mut self) {
if self.deleted_cnt > 0 { if self.deleted_cnt > 0 {
// SAFETY: Trailing unchecked items must be valid since we never touch them. // SAFETY: Trailing unchecked items must be valid since we never touch them.
@ -1028,7 +1099,7 @@ impl<T, S: Storage> VecInner<T, S> {
original_len, original_len,
}; };
fn process_loop<F, T, S: Storage, const DELETED: bool>( fn process_loop<F, T, S: VecStorage<T> + ?Sized, const DELETED: bool>(
original_len: usize, original_len: usize,
f: &mut F, f: &mut F,
g: &mut BackshiftOnDrop<'_, T, S>, g: &mut BackshiftOnDrop<'_, T, S>,
@ -1114,7 +1185,7 @@ impl<T, const N: usize> Default for Vec<T, N> {
} }
} }
impl<T, S: Storage> fmt::Debug for VecInner<T, S> impl<T, S: VecStorage<T> + ?Sized> fmt::Debug for VecInner<T, S>
where where
T: fmt::Debug, T: fmt::Debug,
{ {
@ -1123,7 +1194,7 @@ where
} }
} }
impl<S: Storage> fmt::Write for VecInner<u8, S> { impl<S: VecStorage<u8> + ?Sized> fmt::Write for VecInner<u8, S> {
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
match self.extend_from_slice(s.as_bytes()) { match self.extend_from_slice(s.as_bytes()) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
@ -1138,7 +1209,7 @@ impl<T, const N: usize, const M: usize> From<[T; M]> for Vec<T, N> {
} }
} }
impl<T, S: Storage> Drop for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> Drop for VecInner<T, S> {
fn drop(&mut self) { fn drop(&mut self) {
let mut_slice = self.as_mut_slice(); let mut_slice = self.as_mut_slice();
// We drop each element used in the vector by turning into a `&mut [T]`. // We drop each element used in the vector by turning into a `&mut [T]`.
@ -1155,7 +1226,7 @@ impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
} }
} }
impl<T, S: Storage> Extend<T> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> Extend<T> for VecInner<T, S> {
fn extend<I>(&mut self, iter: I) fn extend<I>(&mut self, iter: I)
where where
I: IntoIterator<Item = T>, I: IntoIterator<Item = T>,
@ -1164,7 +1235,7 @@ impl<T, S: Storage> Extend<T> for VecInner<T, S> {
} }
} }
impl<'a, T, S: Storage> Extend<&'a T> for VecInner<T, S> impl<'a, T, S: VecStorage<T> + ?Sized> Extend<&'a T> for VecInner<T, S>
where where
T: 'a + Copy, T: 'a + Copy,
{ {
@ -1176,7 +1247,7 @@ where
} }
} }
impl<T, S: Storage> hash::Hash for VecInner<T, S> impl<T, S: VecStorage<T> + ?Sized> hash::Hash for VecInner<T, S>
where where
T: core::hash::Hash, T: core::hash::Hash,
{ {
@ -1185,7 +1256,7 @@ where
} }
} }
impl<'a, T, S: Storage> IntoIterator for &'a VecInner<T, S> { impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a VecInner<T, S> {
type Item = &'a T; type Item = &'a T;
type IntoIter = slice::Iter<'a, T>; type IntoIter = slice::Iter<'a, T>;
@ -1194,7 +1265,7 @@ impl<'a, T, S: Storage> IntoIterator for &'a VecInner<T, S> {
} }
} }
impl<'a, T, S: Storage> IntoIterator for &'a mut VecInner<T, S> { impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a mut VecInner<T, S> {
type Item = &'a mut T; type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>; type IntoIter = slice::IterMut<'a, T>;
@ -1228,7 +1299,14 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T; type Item = T;
fn next(&mut self) -> Option<Self::Item> { 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.get_unchecked_mut(self.next).as_ptr().read() }; let item = unsafe {
self.vec
.buffer
.buffer
.get_unchecked_mut(self.next)
.as_ptr()
.read()
};
self.next += 1; self.next += 1;
Some(item) Some(item)
} else { } else {
@ -1247,7 +1325,7 @@ where
if self.next < self.vec.len() { if self.next < self.vec.len() {
let s = unsafe { let s = unsafe {
slice::from_raw_parts( slice::from_raw_parts(
(self.vec.buffer.as_ptr() as *const T).add(self.next), (self.vec.buffer.buffer.as_ptr() as *const T).add(self.next),
self.vec.len() - self.next, self.vec.len() - self.next,
) )
}; };
@ -1278,7 +1356,8 @@ impl<T, const N: usize> IntoIterator for Vec<T, N> {
} }
} }
impl<A, B, SA: Storage, SB: Storage> PartialEq<VecInner<B, SB>> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>>
for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1287,7 +1366,7 @@ where
} }
} }
impl<A, B, const M: usize, SB: Storage> PartialEq<VecInner<B, SB>> for [A; M] impl<A, B, const M: usize, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for [A; M]
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1296,7 +1375,7 @@ where
} }
} }
impl<A, B, SB: Storage, const M: usize> PartialEq<VecInner<B, SB>> for &[A; M] impl<A, B, SB: VecStorage<B> + ?Sized, const M: usize> PartialEq<VecInner<B, SB>> for &[A; M]
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1305,7 +1384,7 @@ where
} }
} }
impl<A, B, SB: Storage> PartialEq<VecInner<B, SB>> for [A] impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for [A]
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1314,7 +1393,7 @@ where
} }
} }
impl<A, B, SB: Storage> PartialEq<VecInner<B, SB>> for &[A] impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for &[A]
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1323,7 +1402,7 @@ where
} }
} }
impl<A, B, SB: Storage> PartialEq<VecInner<B, SB>> for &mut [A] impl<A, B, SB: VecStorage<B> + ?Sized> PartialEq<VecInner<B, SB>> for &mut [A]
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1332,7 +1411,7 @@ where
} }
} }
impl<A, B, SA: Storage, const N: usize> PartialEq<[B; N]> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized, const N: usize> PartialEq<[B; N]> for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1342,7 +1421,7 @@ where
} }
} }
impl<A, B, SA: Storage, const N: usize> PartialEq<&[B; N]> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized, const N: usize> PartialEq<&[B; N]> for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1352,7 +1431,7 @@ where
} }
} }
impl<A, B, SA: Storage> PartialEq<[B]> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<[B]> for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1362,7 +1441,7 @@ where
} }
} }
impl<A, B, SA: Storage> PartialEq<&[B]> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<&[B]> for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1372,7 +1451,7 @@ where
} }
} }
impl<A, B, SA: Storage> PartialEq<&mut [B]> for VecInner<A, SA> impl<A, B, SA: VecStorage<A> + ?Sized> PartialEq<&mut [B]> for VecInner<A, SA>
where where
A: PartialEq<B>, A: PartialEq<B>,
{ {
@ -1383,9 +1462,10 @@ where
} }
// Implements Eq if underlying data is Eq // Implements Eq if underlying data is Eq
impl<T, S: Storage> Eq for VecInner<T, S> where T: Eq {} impl<T, S: VecStorage<T> + ?Sized> Eq for VecInner<T, S> where T: Eq {}
impl<T, SA: Storage, SB: Storage> PartialOrd<VecInner<T, SA>> for VecInner<T, SB> impl<T, SA: VecStorage<T> + ?Sized, SB: VecStorage<T> + ?Sized> PartialOrd<VecInner<T, SA>>
for VecInner<T, SB>
where where
T: PartialOrd, T: PartialOrd,
{ {
@ -1394,7 +1474,7 @@ where
} }
} }
impl<T, S: Storage> Ord for VecInner<T, S> impl<T, S: VecStorage<T> + ?Sized> Ord for VecInner<T, S>
where where
T: Ord, T: Ord,
{ {
@ -1404,7 +1484,7 @@ where
} }
} }
impl<T, S: Storage> ops::Deref for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> ops::Deref for VecInner<T, S> {
type Target = [T]; type Target = [T];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -1412,45 +1492,45 @@ impl<T, S: Storage> ops::Deref for VecInner<T, S> {
} }
} }
impl<T, S: Storage> ops::DerefMut for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> ops::DerefMut for VecInner<T, S> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice() self.as_mut_slice()
} }
} }
impl<T, S: Storage> borrow::Borrow<[T]> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> borrow::Borrow<[T]> for VecInner<T, S> {
fn borrow(&self) -> &[T] { fn borrow(&self) -> &[T] {
self.as_slice() self.as_slice()
} }
} }
impl<T, S: Storage> borrow::BorrowMut<[T]> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> borrow::BorrowMut<[T]> for VecInner<T, S> {
fn borrow_mut(&mut self) -> &mut [T] { fn borrow_mut(&mut self) -> &mut [T] {
self.as_mut_slice() self.as_mut_slice()
} }
} }
impl<T, S: Storage> AsRef<VecInner<T, S>> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> AsRef<VecInner<T, S>> for VecInner<T, S> {
#[inline] #[inline]
fn as_ref(&self) -> &Self { fn as_ref(&self) -> &Self {
self self
} }
} }
impl<T, S: Storage> AsMut<VecInner<T, S>> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> AsMut<VecInner<T, S>> for VecInner<T, S> {
#[inline] #[inline]
fn as_mut(&mut self) -> &mut Self { fn as_mut(&mut self) -> &mut Self {
self self
} }
} }
impl<T, S: Storage> AsRef<[T]> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> AsRef<[T]> for VecInner<T, S> {
#[inline] #[inline]
fn as_ref(&self) -> &[T] { fn as_ref(&self) -> &[T] {
self self
} }
} }
impl<T, S: Storage> AsMut<[T]> for VecInner<T, S> { impl<T, S: VecStorage<T> + ?Sized> AsMut<[T]> for VecInner<T, S> {
#[inline] #[inline]
fn as_mut(&mut self) -> &mut [T] { fn as_mut(&mut self) -> &mut [T] {
self self
@ -1959,4 +2039,11 @@ mod tests {
assert!(v.spare_capacity_mut().is_empty()); assert!(v.spare_capacity_mut().is_empty());
} }
fn _test_variance<'a: 'b, 'b>(x: Vec<&'a (), 42>) -> Vec<&'b (), 42> {
x
}
fn _test_variance_view<'a: 'b, 'b, 'c>(x: &'c VecView<&'a ()>) -> &'c VecView<&'b ()> {
x
}
} }