Skip to content

Implement Vec::drain, as_(mut_)view on the *Inner types, generic over Storage #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,16 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
pub fn into_vec(self) -> Vec<T, N> {
self.data
}
}

impl<T, K, S: VecStorage<T>> BinaryHeapInner<T, K, S> {
/// Get a reference to the `BinaryHeap`, erasing the `N` const-generic.
pub fn as_view(&self) -> &BinaryHeapView<T, K> {
self
S::as_binary_heap_view(self)
}
/// Get a mutable reference to the `BinaryHeap`, erasing the `N` const-generic.
pub fn as_mut_view(&mut self) -> &mut BinaryHeapView<T, K> {
self
S::as_binary_heap_mut_view(self)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/defmt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Defmt implementations for heapless types

use crate::{
string::StringInner,
string::{StringInner, StringStorage},
vec::{VecInner, VecStorage},
};
use defmt::Formatter;
Expand All @@ -15,7 +15,7 @@ where
}
}

impl<S: VecStorage<u8> + ?Sized> defmt::Format for StringInner<S>
impl<S: StringStorage + ?Sized> defmt::Format for StringInner<S>
where
u8: defmt::Format,
{
Expand Down
8 changes: 4 additions & 4 deletions src/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,19 +186,19 @@ impl<T, const N: usize> Deque<T, N> {
self.back - self.front
}
}
}

impl<T, S: VecStorage<T> + ?Sized> DequeInner<T, S> {
/// Get a reference to the `Deque`, erasing the `N` const-generic.
pub fn as_view(&self) -> &DequeView<T> {
self
S::as_deque_view(self)
}

/// Get a mutable reference to the `Deque`, erasing the `N` const-generic.
pub fn as_mut_view(&mut self) -> &mut DequeView<T> {
self
S::as_deque_mut_view(self)
}
}

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()
Expand Down
57 changes: 45 additions & 12 deletions src/histbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ use core::slice;
mod storage {
use core::mem::MaybeUninit;

use super::{HistoryBufferInner, HistoryBufferView};

/// Trait defining how data for a container is stored.
///
/// There's two implementations available:
Expand Down Expand Up @@ -72,6 +74,14 @@ mod storage {
// 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>];
fn as_hist_buf_view(this: &HistoryBufferInner<T, Self>) -> &HistoryBufferView<T>
where
Self: HistBufStorage<T>;
fn as_hist_buf_mut_view(
this: &mut HistoryBufferInner<T, Self>,
) -> &mut HistoryBufferView<T>
where
Self: HistBufStorage<T>;
}

// One sealed layer of indirection to hide the internal details (The MaybeUninit).
Expand All @@ -91,6 +101,18 @@ mod storage {
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
fn as_hist_buf_view(this: &HistoryBufferInner<T, Self>) -> &HistoryBufferView<T>
where
Self: HistBufStorage<T>,
{
this
}
fn as_hist_buf_mut_view(this: &mut HistoryBufferInner<T, Self>) -> &mut HistoryBufferView<T>
where
Self: HistBufStorage<T>,
{
this
}
}
impl<T, const N: usize> HistBufStorage<T> for OwnedHistBufStorage<T, N> {}

Expand All @@ -101,6 +123,18 @@ mod storage {
fn borrow_mut(&mut self) -> &mut [MaybeUninit<T>] {
&mut self.buffer
}
fn as_hist_buf_view(this: &HistoryBufferInner<T, Self>) -> &HistoryBufferView<T>
where
Self: HistBufStorage<T>,
{
this
}
fn as_hist_buf_mut_view(this: &mut HistoryBufferInner<T, Self>) -> &mut HistoryBufferView<T>
where
Self: HistBufStorage<T>,
{
this
}
}
impl<T> HistBufStorage<T> for ViewHistBufStorage<T> {}
}
Expand Down Expand Up @@ -221,18 +255,6 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
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>
Expand Down Expand Up @@ -264,6 +286,17 @@ where
}
}
impl<T: Copy, S: HistBufStorage<T> + ?Sized> HistoryBufferInner<T, S> {
/// Get a reference to the `HistoryBuffer`, erasing the `N` const-generic.
#[inline]
pub fn as_view(&self) -> &HistoryBufferView<T> {
S::as_hist_buf_view(self)
}

/// Get a mutable reference to the `HistoryBuffer`, erasing the `N` const-generic.
#[inline]
pub fn as_mut_view(&mut self) -> &mut HistoryBufferView<T> {
S::as_hist_buf_mut_view(self)
}
/// 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
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ pub mod storage;
pub mod string;
pub mod vec;

// Workaround a compiler ICE in rust 1.83 to 1.86
// https://github.com/rust-lang/rust/issues/138979#issuecomment-2760839948
#[expect(dead_code)]
fn dead_code_ice_workaround() {}

#[cfg(feature = "serde")]
mod de;
#[cfg(feature = "serde")]
Expand Down
115 changes: 98 additions & 17 deletions src/linear_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,103 @@

use core::{borrow::Borrow, fmt, mem, ops, slice};

use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage};
use crate::vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage};

mod storage {
use crate::vec::{OwnedVecStorage, VecStorage, ViewVecStorage};

use super::{LinearMapInner, LinearMapView};

/// Trait defining how data for a [`LinearMap`](super::LinearMap) is stored.
///
/// There's two implementations available:
///
/// - [`OwnedStorage`]: stores the data in an array whose size is known at compile time.
/// - [`ViewStorage`]: stores the data in an unsized slice
///
/// This allows [`LinearMap`] to be generic over either sized or unsized storage. The [`linear_map`](super)
/// module contains a [`LinearMapInner`] struct that's generic on [`LinearMapStorage`],
/// and two type aliases for convenience:
///
/// - [`LinearMap<N>`](crate::linear_map::LinearMap) = `LinearMapInner<OwnedStorage<u8, N>>`
/// - [`LinearMapView<T>`](crate::linear_map::LinearMapView) = `LinearMapInner<ViewStorage<u8>>`
///
/// `LinearMap` can be unsized into `StrinsgView`, either by unsizing coercions such as `&mut LinearMap -> &mut LinearMapView` or
/// `Box<LinearMap> -> Box<LinearMapView>`, or explicitly with [`.as_view()`](crate::linear_map::LinearMap::as_view) or [`.as_mut_view()`](crate::linear_map::LinearMap::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.
///
/// [`LinearMapInner`]: super::LinearMapInner
/// [`LinearMap`]: super::LinearMap
/// [`OwnedStorage`]: super::OwnedStorage
/// [`ViewStorage`]: super::ViewStorage
pub trait LinearMapStorage<K, V>: LinearMapStorageSealed<K, V> {}
pub trait LinearMapStorageSealed<K, V>: VecStorage<(K, V)> {
fn as_linear_map_view(this: &LinearMapInner<K, V, Self>) -> &LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>;
fn as_linear_map_mut_view(
this: &mut LinearMapInner<K, V, Self>,
) -> &mut LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>;
}

impl<K, V, const N: usize> LinearMapStorage<K, V> for OwnedVecStorage<(K, V), N> {}
impl<K, V, const N: usize> LinearMapStorageSealed<K, V> for OwnedVecStorage<(K, V), N> {
fn as_linear_map_view(this: &LinearMapInner<K, V, Self>) -> &LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>,
{
this
}
fn as_linear_map_mut_view(this: &mut LinearMapInner<K, V, Self>) -> &mut LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>,
{
this
}
}

impl<K, V> LinearMapStorage<K, V> for ViewVecStorage<(K, V)> {}

impl<K, V> LinearMapStorageSealed<K, V> for ViewVecStorage<(K, V)> {
fn as_linear_map_view(this: &LinearMapInner<K, V, Self>) -> &LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>,
{
this
}
fn as_linear_map_mut_view(this: &mut LinearMapInner<K, V, Self>) -> &mut LinearMapView<K, V>
where
Self: LinearMapStorage<K, V>,
{
this
}
}
}

pub use storage::LinearMapStorage;
/// Implementation of [`LinearMapStorage`] that stores the data in an array whose size is known at compile time.
pub type OwnedStorage<K, V, const N: usize> = OwnedVecStorage<(K, V), N>;
/// Implementation of [`LinearMapStorage`] that stores the data in an unsized slice.
pub type ViewStorage<K, V> = ViewVecStorage<(K, V)>;

/// Base struct for [`LinearMap`] and [`LinearMapView`]
pub struct LinearMapInner<K, V, S: VecStorage<(K, V)> + ?Sized> {
pub struct LinearMapInner<K, V, S: LinearMapStorage<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, OwnedVecStorage<(K, V), N>>;
pub type LinearMap<K, V, const N: usize> = LinearMapInner<K, V, OwnedStorage<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, ViewVecStorage<(K, V)>>;
pub type LinearMapView<K, V> = LinearMapInner<K, V, ViewStorage<K, V>>;

impl<K, V, const N: usize> LinearMap<K, V, N> {
/// Creates an empty `LinearMap`.
Expand All @@ -38,22 +119,22 @@ impl<K, V, const N: usize> LinearMap<K, V, N> {
pub const fn new() -> Self {
Self { buffer: Vec::new() }
}
}

impl<K, V, S: LinearMapStorage<K, V> + ?Sized> LinearMapInner<K, V, S>
where
K: Eq,
{
/// Get a reference to the `LinearMap`, erasing the `N` const-generic.
pub fn as_view(&self) -> &LinearMapView<K, V> {
self
S::as_linear_map_view(self)
}

/// Get a mutable reference to the `LinearMap`, erasing the `N` const-generic.
pub fn as_mut_view(&mut self) -> &mut LinearMapView<K, V> {
self
S::as_linear_map_mut_view(self)
}
}

impl<K, V, S: VecStorage<(K, V)> + ?Sized> LinearMapInner<K, V, S>
where
K: Eq,
{
/// Returns the number of elements that the map can hold.
///
/// Computes in *O*(1) time.
Expand Down Expand Up @@ -388,7 +469,7 @@ where
}
}

impl<K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::Index<&'_ Q> for LinearMapInner<K, V, S>
impl<K, V, Q, S: LinearMapStorage<K, V> + ?Sized> ops::Index<&'_ Q> for LinearMapInner<K, V, S>
where
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
Expand All @@ -400,7 +481,7 @@ where
}
}

impl<K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::IndexMut<&'_ Q> for LinearMapInner<K, V, S>
impl<K, V, Q, S: LinearMapStorage<K, V> + ?Sized> ops::IndexMut<&'_ Q> for LinearMapInner<K, V, S>
where
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
Expand Down Expand Up @@ -431,7 +512,7 @@ where
}
}

impl<K, V, S: VecStorage<(K, V)> + ?Sized> fmt::Debug for LinearMapInner<K, V, S>
impl<K, V, S: LinearMapStorage<K, V> + ?Sized> fmt::Debug for LinearMapInner<K, V, S>
where
K: Eq + fmt::Debug,
V: fmt::Debug,
Expand Down Expand Up @@ -489,7 +570,7 @@ where
}
}

impl<'a, K, V, S: VecStorage<(K, V)> + ?Sized> IntoIterator for &'a LinearMapInner<K, V, S>
impl<'a, K, V, S: LinearMapStorage<K, V> + ?Sized> IntoIterator for &'a LinearMapInner<K, V, S>
where
K: Eq,
{
Expand Down Expand Up @@ -533,7 +614,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
}
}

impl<K, V, S1: VecStorage<(K, V)> + ?Sized, S2: VecStorage<(K, V)> + ?Sized>
impl<K, V, S1: LinearMapStorage<K, V> + ?Sized, S2: LinearMapStorage<K, V> + ?Sized>
PartialEq<LinearMapInner<K, V, S2>> for LinearMapInner<K, V, S1>
where
K: Eq,
Expand All @@ -547,7 +628,7 @@ where
}
}

impl<K, V, S: VecStorage<(K, V)> + ?Sized> Eq for LinearMapInner<K, V, S>
impl<K, V, S: LinearMapStorage<K, V> + ?Sized> Eq for LinearMapInner<K, V, S>
where
K: Eq,
V: PartialEq,
Expand Down
Loading
Loading