Skip to content

Commit

Permalink
Merge pull request #486 from Dirbaio/vecview-dedup
Browse files Browse the repository at this point in the history
vec: remove code duplication due to VecView.
  • Loading branch information
Dirbaio authored Jun 30, 2024
2 parents 1f25e65 + bd03035 commit d1c47c3
Show file tree
Hide file tree
Showing 6 changed files with 477 additions and 1,052 deletions.
4 changes: 2 additions & 2 deletions src/defmt.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Defmt implementations for heapless types
use crate::Vec;
use crate::{storage::Storage, vec::VecInner};
use defmt::Formatter;

impl<T, const N: usize> defmt::Format for Vec<T, N>
impl<T, S: Storage> defmt::Format for VecInner<T, S>
where
T: defmt::Format,
{
Expand Down
10 changes: 2 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,6 @@ pub use indexmap::{
pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter};
pub use linear_map::LinearMap;
pub use string::String;

// Workaround https://github.com/rust-lang/rust/issues/119015. This is required so that the methods on `VecView` and `Vec` are properly documented.
// cfg(doc) prevents `VecInner` being part of the public API.
// doc(hidden) prevents the `pub use vec::VecInner` from being visible in the documentation.
#[cfg(doc)]
#[doc(hidden)]
pub use vec::VecInner as _;
pub use vec::{Vec, VecView};

#[macro_use]
Expand All @@ -114,8 +107,9 @@ mod histbuf;
mod indexmap;
mod indexset;
mod linear_map;
pub mod storage;
pub mod string;
mod vec;
pub mod vec;

#[cfg(feature = "serde")]
mod de;
Expand Down
6 changes: 3 additions & 3 deletions src/ser.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use core::hash::{BuildHasher, Hash};

use crate::{
binary_heap::Kind as BinaryHeapKind, BinaryHeap, Deque, IndexMap, IndexSet, LinearMap, String,
Vec,
binary_heap::Kind as BinaryHeapKind, storage::Storage, vec::VecInner, BinaryHeap, Deque,
IndexMap, IndexSet, LinearMap, String,
};
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};

Expand Down Expand Up @@ -42,7 +42,7 @@ where
}
}

impl<T, const N: usize> Serialize for Vec<T, N>
impl<T, St: Storage> Serialize for VecInner<T, St>
where
T: Serialize,
{
Expand Down
43 changes: 43 additions & 0 deletions src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! `Storage` trait defining how data is stored in a container.
use core::borrow::{Borrow, BorrowMut};

pub(crate) trait SealedStorage {
type Buffer<T>: ?Sized + Borrow<[T]> + BorrowMut<[T]>;
}

/// Trait defining how data for a container is stored.
///
/// There's two implementations available:
///
/// - [`OwnedStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
/// - [`ViewStorage`]: stores the data in an unsized `[T]`.
///
/// This allows containers to be generic over either sized or unsized storage. For example,
/// the [`vec`](crate::vec) module contains a [`VecInner`](crate::vec::VecInner) struct
/// that's generic on [`Storage`], and two type aliases for convenience:
///
/// - [`Vec<T, N>`](crate::vec::Vec) = `VecInner<T, OwnedStorage<N>>`
/// - [`VecView<T>`](crate::vec::VecView) = `VecInner<T, ViewStorage>`
///
/// `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.
#[allow(private_bounds)]
pub trait Storage: SealedStorage {}

/// Implementation of [`Storage`] that stores the data in an array `[T; N]` whose size is known at compile time.
pub enum OwnedStorage<const N: usize> {}
impl<const N: usize> Storage for OwnedStorage<N> {}
impl<const N: usize> SealedStorage for OwnedStorage<N> {
type Buffer<T> = [T; N];
}

/// Implementation of [`Storage`] that stores the data in an unsized `[T]`.
pub enum ViewStorage {}
impl Storage for ViewStorage {}
impl SealedStorage for ViewStorage {
type Buffer<T> = [T];
}
6 changes: 3 additions & 3 deletions src/ufmt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{string::String, vec::Vec};
use crate::{storage::Storage, string::String, vec::VecInner};
use ufmt_write::uWrite;

impl<const N: usize> uWrite for String<N> {
Expand All @@ -8,7 +8,7 @@ impl<const N: usize> uWrite for String<N> {
}
}

impl<const N: usize> uWrite for Vec<u8, N> {
impl<S: Storage> uWrite for VecInner<u8, S> {
type Error = ();
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
self.extend_from_slice(s.as_bytes())
Expand All @@ -17,7 +17,7 @@ impl<const N: usize> uWrite for Vec<u8, N> {

#[cfg(test)]
mod tests {
use super::*;
use crate::{String, Vec};

use ufmt::{derive::uDebug, uwrite};

Expand Down
Loading

0 comments on commit d1c47c3

Please sign in to comment.