mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-09-30 05:50:29 +00:00
Merge pull request #502 from Nitrokey/vec-covariance
Re-introduce covariance for containers
This commit is contained in:
commit
3c97d2f035
@ -17,10 +17,7 @@ use core::{
|
||||
ptr, slice,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
storage::{OwnedStorage, Storage, ViewStorage},
|
||||
vec::{Vec, VecInner},
|
||||
};
|
||||
use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
|
||||
|
||||
/// Min-heap
|
||||
pub enum Min {}
|
||||
@ -54,11 +51,11 @@ mod private {
|
||||
impl private::Sealed for Max {}
|
||||
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
|
||||
/// 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) data: VecInner<T, S>,
|
||||
}
|
||||
@ -109,7 +106,7 @@ pub struct BinaryHeapInner<T, K, S: Storage> {
|
||||
/// // The heap should now be 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.
|
||||
///
|
||||
@ -158,7 +155,7 @@ pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N
|
||||
/// // The heap should now be 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> {
|
||||
/* 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
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
@ -539,7 +536,7 @@ pub struct PeekMutInner<'a, T, K, S>
|
||||
where
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
heap: &'a mut BinaryHeapInner<T, K, S>,
|
||||
sift: bool,
|
||||
@ -550,20 +547,20 @@ where
|
||||
///
|
||||
/// This `struct` is created by [`BinaryHeap::peek_mut`].
|
||||
/// 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
|
||||
/// `BinaryHeap`.
|
||||
///
|
||||
/// This `struct` is created by [`BinaryHeapView::peek_mut`].
|
||||
/// 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>
|
||||
where
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
if self.sift {
|
||||
@ -576,7 +573,7 @@ impl<T, K, S> Deref for PeekMutInner<'_, T, K, S>
|
||||
where
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
@ -590,7 +587,7 @@ impl<T, K, S> DerefMut for PeekMutInner<'_, T, K, S>
|
||||
where
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
debug_assert!(!self.heap.is_empty());
|
||||
@ -603,7 +600,7 @@ impl<'a, T, K, S> PeekMutInner<'a, T, K, S>
|
||||
where
|
||||
T: Ord,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
/// Removes the peeked value from the heap and returns it.
|
||||
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
|
||||
K: Kind,
|
||||
T: Ord + fmt::Debug,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter()).finish()
|
||||
@ -662,7 +659,7 @@ impl<'a, T, K, S> IntoIterator for &'a BinaryHeapInner<T, K, S>
|
||||
where
|
||||
K: Kind,
|
||||
T: Ord,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
type Item = &'a T;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
@ -676,7 +673,7 @@ where
|
||||
mod tests {
|
||||
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.
|
||||
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(), 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
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
//! Defmt implementations for heapless types
|
||||
|
||||
use crate::{storage::Storage, string::StringInner, vec::VecInner};
|
||||
use crate::{
|
||||
string::StringInner,
|
||||
vec::{VecInner, VecStorage},
|
||||
};
|
||||
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
|
||||
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
|
||||
u8: defmt::Format,
|
||||
{
|
||||
|
35
src/deque.rs
35
src/deque.rs
@ -33,20 +33,22 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::iter::FusedIterator;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
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
|
||||
/// 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: usize,
|
||||
/// 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`.
|
||||
/// May only be `true` if `front == back`, always `false` otherwise.
|
||||
full: bool,
|
||||
buffer: S::Buffer<MaybeUninit<T>>,
|
||||
buffer: S,
|
||||
}
|
||||
|
||||
/// A fixed capacity double-ended queue.
|
||||
@ -92,7 +94,7 @@ pub struct DequeInner<T, S: Storage> {
|
||||
/// 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.
|
||||
///
|
||||
@ -131,7 +133,7 @@ pub type Deque<T, const N: usize> = DequeInner<T, OwnedStorage<N>>;
|
||||
/// 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> {
|
||||
const INIT: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
@ -154,7 +156,10 @@ impl<T, const N: usize> Deque<T, N> {
|
||||
crate::sealed::greater_than_0::<N>();
|
||||
|
||||
Self {
|
||||
buffer: [Self::INIT; N],
|
||||
phantom: PhantomData,
|
||||
buffer: VecStorageInner {
|
||||
buffer: [Self::INIT; N],
|
||||
},
|
||||
front: 0,
|
||||
back: 0,
|
||||
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.
|
||||
pub fn storage_capacity(&self) -> usize {
|
||||
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) {
|
||||
// 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.
|
||||
@ -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 {
|
||||
f.debug_list().entries(self).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
for item in iter {
|
||||
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) {
|
||||
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 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 IntoIter = IterMut<'a, T>;
|
||||
|
||||
|
157
src/histbuf.rs
157
src/histbuf.rs
@ -31,8 +31,6 @@
|
||||
//! assert_eq!(avg, 4);
|
||||
//! ```
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::borrow::BorrowMut;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
@ -40,18 +38,89 @@ use core::ops::Deref;
|
||||
use core::ptr;
|
||||
use core::slice;
|
||||
|
||||
use crate::storage::OwnedStorage;
|
||||
use crate::storage::Storage;
|
||||
use crate::storage::ViewStorage;
|
||||
mod storage {
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
/// 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
|
||||
/// 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,
|
||||
filled: bool,
|
||||
data: S::Buffer<MaybeUninit<T>>,
|
||||
data: S,
|
||||
}
|
||||
|
||||
/// 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();
|
||||
/// 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`]
|
||||
///
|
||||
@ -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();
|
||||
/// 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> {
|
||||
const INIT: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
@ -143,11 +212,26 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
|
||||
crate::sealed::greater_than_0::<N>();
|
||||
|
||||
Self {
|
||||
data: [Self::INIT; N],
|
||||
phantom: PhantomData,
|
||||
data: HistBufStorageInner {
|
||||
buffer: [Self::INIT; N],
|
||||
},
|
||||
write_at: 0,
|
||||
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>
|
||||
@ -169,13 +253,16 @@ where
|
||||
#[inline]
|
||||
pub fn new_with(t: T) -> Self {
|
||||
Self {
|
||||
data: [MaybeUninit::new(t); N],
|
||||
phantom: PhantomData,
|
||||
data: HistBufStorageInner {
|
||||
buffer: [MaybeUninit::new(t); N],
|
||||
},
|
||||
write_at: 0,
|
||||
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.
|
||||
pub fn clear_with(&mut self, t: T) {
|
||||
// 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
|
||||
pub fn clear(&mut self) {
|
||||
// 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 {
|
||||
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)
|
||||
where
|
||||
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
|
||||
T: 'a + Clone,
|
||||
{
|
||||
@ -436,7 +523,7 @@ where
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
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());
|
||||
}
|
||||
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) {
|
||||
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];
|
||||
|
||||
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]
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: Storage> fmt::Debug for HistoryBufferInner<T, S>
|
||||
impl<T, S: HistBufStorage<T> + ?Sized> fmt::Debug for HistoryBufferInner<T, S>
|
||||
where
|
||||
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
|
||||
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
|
||||
/// 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>,
|
||||
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
|
||||
/// 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)
|
||||
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
|
||||
/// 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> {
|
||||
/// 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 {
|
||||
Self {
|
||||
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;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
@ -568,7 +656,7 @@ mod tests {
|
||||
|
||||
use static_assertions::assert_not_impl_any;
|
||||
|
||||
use super::HistoryBuffer;
|
||||
use super::{HistoryBuffer, HistoryBufferView};
|
||||
|
||||
// Ensure a `HistoryBuffer` containing `!Send` values stays `!Send` itself.
|
||||
assert_not_impl_any!(HistoryBuffer<*const (), 4>: Send);
|
||||
@ -855,4 +943,13 @@ mod tests {
|
||||
x.clear();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -4,26 +4,22 @@
|
||||
|
||||
use core::{borrow::Borrow, fmt, mem, ops, slice};
|
||||
|
||||
use crate::{
|
||||
storage::{OwnedStorage, Storage, ViewStorage},
|
||||
vec::VecInner,
|
||||
Vec,
|
||||
};
|
||||
use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
|
||||
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
/// 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).
|
||||
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.
|
||||
///
|
||||
/// 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> {
|
||||
/// 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
|
||||
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
|
||||
K: Borrow<Q> + Eq,
|
||||
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
|
||||
K: Borrow<Q> + Eq,
|
||||
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
|
||||
K: Eq + 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
|
||||
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>>
|
||||
for LinearMapInner<K, V, S1>
|
||||
impl<K, V, S1: VecStorage<(K, V)> + ?Sized, S2: VecStorage<(K, V)> + ?Sized>
|
||||
PartialEq<LinearMapInner<K, V, S2>> for LinearMapInner<K, V, S1>
|
||||
where
|
||||
K: Eq,
|
||||
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
|
||||
K: Eq,
|
||||
V: PartialEq,
|
||||
@ -565,7 +561,7 @@ where
|
||||
mod test {
|
||||
use static_assertions::assert_not_impl_any;
|
||||
|
||||
use super::LinearMap;
|
||||
use super::{LinearMap, LinearMapView};
|
||||
|
||||
// Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself.
|
||||
assert_not_impl_any!(LinearMap<*const (), (), 4>: Send);
|
||||
@ -640,4 +636,23 @@ mod test {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
17
src/ser.rs
17
src/ser.rs
@ -3,11 +3,10 @@ use core::hash::{BuildHasher, Hash};
|
||||
use crate::{
|
||||
binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind},
|
||||
deque::DequeInner,
|
||||
histbuf::HistoryBufferInner,
|
||||
histbuf::{HistBufStorage, HistoryBufferInner},
|
||||
linear_map::LinearMapInner,
|
||||
storage::Storage,
|
||||
string::StringInner,
|
||||
vec::VecInner,
|
||||
vec::{VecInner, VecStorage},
|
||||
IndexMap, IndexSet,
|
||||
};
|
||||
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||
@ -18,7 +17,7 @@ impl<T, KIND, S> Serialize for BinaryHeapInner<T, KIND, S>
|
||||
where
|
||||
T: Ord + Serialize,
|
||||
KIND: BinaryHeapKind,
|
||||
S: Storage,
|
||||
S: VecStorage<T> + ?Sized,
|
||||
{
|
||||
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
K: Eq + Serialize,
|
||||
V: Serialize,
|
||||
@ -136,7 +135,7 @@ where
|
||||
|
||||
// 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>
|
||||
where
|
||||
SER: Serializer,
|
||||
|
@ -26,7 +26,6 @@
|
||||
//!
|
||||
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
|
||||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
@ -34,7 +33,80 @@ use core::mem::MaybeUninit;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
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.
|
||||
pub trait SortedLinkedListIndex: Copy {
|
||||
@ -86,27 +158,28 @@ pub struct Node<T, 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
|
||||
/// struct if you want to write code that's generic over both.
|
||||
pub struct SortedLinkedListInner<T, Idx, K, S>
|
||||
where
|
||||
Idx: SortedLinkedListIndex,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
head: Idx,
|
||||
free: Idx,
|
||||
_kind: PhantomData<K>,
|
||||
list: S::Buffer<Node<T, Idx>>,
|
||||
phantom: PhantomData<(K, T)>,
|
||||
list: S,
|
||||
}
|
||||
|
||||
/// The linked list.
|
||||
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.
|
||||
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
|
||||
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>();
|
||||
|
||||
let mut list = SortedLinkedList {
|
||||
list: [Self::UNINIT; N],
|
||||
list: OwnedSortedLinkedListStorage {
|
||||
buffer: [Self::UNINIT; N],
|
||||
},
|
||||
head: $name::none(),
|
||||
free: unsafe { $name::new_unchecked(0) },
|
||||
_kind: PhantomData,
|
||||
phantom: PhantomData,
|
||||
};
|
||||
|
||||
if N == 0 {
|
||||
@ -183,7 +258,7 @@ macro_rules! impl_index_and_const_new {
|
||||
|
||||
// Initialize indexes
|
||||
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;
|
||||
}
|
||||
|
||||
@ -215,7 +290,7 @@ where
|
||||
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
|
||||
where
|
||||
Idx: SortedLinkedListIndex,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
/// Internal access helper
|
||||
#[inline(always)]
|
||||
@ -267,7 +342,7 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
/// 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
|
||||
/// struct if you want to write code that's generic over both.
|
||||
@ -554,23 +629,24 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
list: &'a SortedLinkedListInner<T, Idx, K, S>,
|
||||
index: Idx,
|
||||
}
|
||||
|
||||
/// 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.
|
||||
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>
|
||||
where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
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
|
||||
/// struct if you want to write code that's generic over both.
|
||||
@ -593,7 +669,7 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
list: &'a mut SortedLinkedListInner<T, Idx, K, S>,
|
||||
is_head: bool,
|
||||
@ -603,16 +679,18 @@ where
|
||||
}
|
||||
|
||||
/// 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`].
|
||||
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>
|
||||
where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
fn pop_internal(&mut self) -> T {
|
||||
if self.is_head {
|
||||
@ -701,7 +779,7 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// Only resort the list if the element has changed
|
||||
@ -717,7 +795,7 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
type Target = T;
|
||||
|
||||
@ -732,7 +810,7 @@ where
|
||||
T: Ord,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.maybe_changed = true;
|
||||
@ -771,7 +849,7 @@ where
|
||||
T: Ord + core::fmt::Debug,
|
||||
Idx: SortedLinkedListIndex,
|
||||
K: Kind,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter()).finish()
|
||||
@ -781,7 +859,7 @@ where
|
||||
impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S>
|
||||
where
|
||||
Idx: SortedLinkedListIndex,
|
||||
S: Storage,
|
||||
S: SortedLinkedListStorage<T, Idx> + ?Sized,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
let mut index = self.head;
|
||||
@ -927,4 +1005,15 @@ mod tests {
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,7 @@ use core::{
|
||||
str::{self, Utf8Error},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
storage::{OwnedStorage, Storage, ViewStorage},
|
||||
vec::VecInner,
|
||||
Vec,
|
||||
};
|
||||
use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
|
||||
|
||||
mod 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
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
/// 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).
|
||||
pub type StringView = StringInner<ViewStorage>;
|
||||
pub type StringView = StringInner<ViewVecStorage<u8>>;
|
||||
|
||||
impl StringView {
|
||||
/// 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.
|
||||
///
|
||||
/// # 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 {
|
||||
<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 {
|
||||
<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]
|
||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||
<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> {
|
||||
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;
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
self.as_mut_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Storage> AsRef<str> for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> AsRef<str> for StringInner<S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Storage> AsRef<[u8]> for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> AsRef<[u8]> for StringInner<S> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
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 {
|
||||
str::eq(&**self, &**rhs)
|
||||
}
|
||||
}
|
||||
|
||||
// String<N> == str
|
||||
impl<S: Storage> PartialEq<str> for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> PartialEq<str> for StringInner<S> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
str::eq(self, other)
|
||||
@ -773,7 +771,7 @@ impl<S: Storage> PartialEq<str> for StringInner<S> {
|
||||
}
|
||||
|
||||
// String<N> == &'str
|
||||
impl<S: Storage> PartialEq<&str> for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> PartialEq<&str> for StringInner<S> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
str::eq(self, &other[..])
|
||||
@ -781,7 +779,7 @@ impl<S: Storage> PartialEq<&str> for StringInner<S> {
|
||||
}
|
||||
|
||||
// str == String<N>
|
||||
impl<S: Storage> PartialEq<StringInner<S>> for str {
|
||||
impl<S: VecStorage<u8> + ?Sized> PartialEq<StringInner<S>> for str {
|
||||
#[inline]
|
||||
fn eq(&self, other: &StringInner<S>) -> bool {
|
||||
str::eq(self, &other[..])
|
||||
@ -789,23 +787,25 @@ impl<S: Storage> PartialEq<StringInner<S>> for str {
|
||||
}
|
||||
|
||||
// &'str == String<N>
|
||||
impl<S: Storage> PartialEq<StringInner<S>> for &str {
|
||||
impl<S: VecStorage<u8> + ?Sized> PartialEq<StringInner<S>> for &str {
|
||||
#[inline]
|
||||
fn eq(&self, other: &StringInner<S>) -> bool {
|
||||
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]
|
||||
fn partial_cmp(&self, other: &StringInner<S1>) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Storage> Ord for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> Ord for StringInner<S> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&**self, &**other)
|
||||
|
@ -1,14 +1,17 @@
|
||||
use crate::{storage::Storage, string::StringInner, vec::VecInner};
|
||||
use crate::{
|
||||
string::StringInner,
|
||||
vec::{VecInner, VecStorage},
|
||||
};
|
||||
use ufmt_write::uWrite;
|
||||
|
||||
impl<S: Storage> uWrite for StringInner<S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> uWrite for StringInner<S> {
|
||||
type Error = ();
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
|
||||
self.push_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Storage> uWrite for VecInner<u8, S> {
|
||||
impl<S: VecStorage<u8> + ?Sized> uWrite for VecInner<u8, S> {
|
||||
type Error = ();
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
|
||||
self.extend_from_slice(s.as_bytes())
|
||||
|
181
src/vec/mod.rs
181
src/vec/mod.rs
@ -1,8 +1,8 @@
|
||||
//! A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html).
|
||||
|
||||
use core::borrow;
|
||||
use core::marker::PhantomData;
|
||||
use core::{
|
||||
borrow::{Borrow, BorrowMut},
|
||||
cmp::Ordering,
|
||||
fmt, hash,
|
||||
mem::{self, ManuallyDrop, MaybeUninit},
|
||||
@ -11,18 +11,87 @@ use core::{
|
||||
slice,
|
||||
};
|
||||
|
||||
use crate::storage::{OwnedStorage, Storage, ViewStorage};
|
||||
|
||||
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;
|
||||
|
||||
/// 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
|
||||
/// 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,
|
||||
buffer: S::Buffer<MaybeUninit<T>>,
|
||||
buffer: S,
|
||||
}
|
||||
|
||||
/// 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 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
|
||||
///
|
||||
@ -85,7 +154,7 @@ pub type Vec<T, const N: usize> = VecInner<T, OwnedStorage<N>>;
|
||||
/// mut_view.push(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> {
|
||||
const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
|
||||
@ -106,8 +175,9 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
/// ```
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
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 {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
len: N,
|
||||
// NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit<T>; N]
|
||||
// have the same layout when N == M.
|
||||
@ -160,7 +231,7 @@ impl<T, const N: usize> Vec<T, N> {
|
||||
} else {
|
||||
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
|
||||
// is wrapped in a ManuallyDrop.
|
||||
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
|
||||
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 vector’s buffer.
|
||||
pub fn as_ptr(&self) -> *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.
|
||||
// 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: Storage> {
|
||||
struct BackshiftOnDrop<'a, T, S: VecStorage<T> + ?Sized> {
|
||||
v: &'a mut VecInner<T, S>,
|
||||
processed_len: usize,
|
||||
deleted_cnt: 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) {
|
||||
if self.deleted_cnt > 0 {
|
||||
// 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,
|
||||
};
|
||||
|
||||
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,
|
||||
f: &mut F,
|
||||
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
|
||||
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 {
|
||||
match self.extend_from_slice(s.as_bytes()) {
|
||||
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) {
|
||||
let mut_slice = self.as_mut_slice();
|
||||
// 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)
|
||||
where
|
||||
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
|
||||
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
|
||||
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 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 IntoIter = slice::IterMut<'a, T>;
|
||||
|
||||
@ -1228,7 +1299,14 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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;
|
||||
Some(item)
|
||||
} else {
|
||||
@ -1247,7 +1325,7 @@ where
|
||||
if self.next < self.vec.len() {
|
||||
let s = unsafe {
|
||||
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,
|
||||
)
|
||||
};
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
@ -1383,9 +1462,10 @@ where
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
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];
|
||||
|
||||
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 {
|
||||
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] {
|
||||
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] {
|
||||
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]
|
||||
fn as_ref(&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]
|
||||
fn as_mut(&mut self) -> &mut 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]
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S: Storage> AsMut<[T]> for VecInner<T, S> {
|
||||
impl<T, S: VecStorage<T> + ?Sized> AsMut<[T]> for VecInner<T, S> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
@ -1959,4 +2039,11 @@ mod tests {
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user