mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-10-03 07:14:45 +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,
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
{
|
{
|
||||||
|
33
src/deque.rs
33
src/deque.rs
@ -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>;
|
||||||
|
|
||||||
|
157
src/histbuf.rs
157
src/histbuf.rs
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
17
src/ser.rs
17
src/ser.rs
@ -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,
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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())
|
||||||
|
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).
|
//! 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 vector’s buffer.
|
/// Returns a raw pointer to the vector’s 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user