Skip to content

Commit d1c47c3

Browse files
authored
Merge pull request #486 from Dirbaio/vecview-dedup
vec: remove code duplication due to VecView.
2 parents 1f25e65 + bd03035 commit d1c47c3

File tree

6 files changed

+477
-1052
lines changed

6 files changed

+477
-1052
lines changed

src/defmt.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Defmt implementations for heapless types
22
3-
use crate::Vec;
3+
use crate::{storage::Storage, vec::VecInner};
44
use defmt::Formatter;
55

6-
impl<T, const N: usize> defmt::Format for Vec<T, N>
6+
impl<T, S: Storage> defmt::Format for VecInner<T, S>
77
where
88
T: defmt::Format,
99
{

src/lib.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,6 @@ pub use indexmap::{
9696
pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter};
9797
pub use linear_map::LinearMap;
9898
pub use string::String;
99-
100-
// Workaround https://github.com/rust-lang/rust/issues/119015. This is required so that the methods on `VecView` and `Vec` are properly documented.
101-
// cfg(doc) prevents `VecInner` being part of the public API.
102-
// doc(hidden) prevents the `pub use vec::VecInner` from being visible in the documentation.
103-
#[cfg(doc)]
104-
#[doc(hidden)]
105-
pub use vec::VecInner as _;
10699
pub use vec::{Vec, VecView};
107100

108101
#[macro_use]
@@ -114,8 +107,9 @@ mod histbuf;
114107
mod indexmap;
115108
mod indexset;
116109
mod linear_map;
110+
pub mod storage;
117111
pub mod string;
118-
mod vec;
112+
pub mod vec;
119113

120114
#[cfg(feature = "serde")]
121115
mod de;

src/ser.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use core::hash::{BuildHasher, Hash};
22

33
use crate::{
4-
binary_heap::Kind as BinaryHeapKind, BinaryHeap, Deque, IndexMap, IndexSet, LinearMap, String,
5-
Vec,
4+
binary_heap::Kind as BinaryHeapKind, storage::Storage, vec::VecInner, BinaryHeap, Deque,
5+
IndexMap, IndexSet, LinearMap, String,
66
};
77
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
88

@@ -42,7 +42,7 @@ where
4242
}
4343
}
4444

45-
impl<T, const N: usize> Serialize for Vec<T, N>
45+
impl<T, St: Storage> Serialize for VecInner<T, St>
4646
where
4747
T: Serialize,
4848
{

src/storage.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! `Storage` trait defining how data is stored in a container.
2+
3+
use core::borrow::{Borrow, BorrowMut};
4+
5+
pub(crate) trait SealedStorage {
6+
type Buffer<T>: ?Sized + Borrow<[T]> + BorrowMut<[T]>;
7+
}
8+
9+
/// Trait defining how data for a container is stored.
10+
///
11+
/// There's two implementations available:
12+
///
13+
/// - [`OwnedStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
14+
/// - [`ViewStorage`]: stores the data in an unsized `[T]`.
15+
///
16+
/// This allows containers to be generic over either sized or unsized storage. For example,
17+
/// the [`vec`](crate::vec) module contains a [`VecInner`](crate::vec::VecInner) struct
18+
/// that's generic on [`Storage`], and two type aliases for convenience:
19+
///
20+
/// - [`Vec<T, N>`](crate::vec::Vec) = `VecInner<T, OwnedStorage<N>>`
21+
/// - [`VecView<T>`](crate::vec::VecView) = `VecInner<T, ViewStorage>`
22+
///
23+
/// `Vec` can be unsized into `VecView`, either by unsizing coercions such as `&mut Vec -> &mut VecView` or
24+
/// `Box<Vec> -> Box<VecView>`, or explicitly with [`.as_view()`](crate::vec::Vec::as_view) or [`.as_mut_view()`](crate::vec::Vec::as_mut_view).
25+
///
26+
/// This trait is sealed, so you cannot implement it for your own types. You can only use
27+
/// the implementations provided by this crate.
28+
#[allow(private_bounds)]
29+
pub trait Storage: SealedStorage {}
30+
31+
/// Implementation of [`Storage`] that stores the data in an array `[T; N]` whose size is known at compile time.
32+
pub enum OwnedStorage<const N: usize> {}
33+
impl<const N: usize> Storage for OwnedStorage<N> {}
34+
impl<const N: usize> SealedStorage for OwnedStorage<N> {
35+
type Buffer<T> = [T; N];
36+
}
37+
38+
/// Implementation of [`Storage`] that stores the data in an unsized `[T]`.
39+
pub enum ViewStorage {}
40+
impl Storage for ViewStorage {}
41+
impl SealedStorage for ViewStorage {
42+
type Buffer<T> = [T];
43+
}

src/ufmt.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{string::String, vec::Vec};
1+
use crate::{storage::Storage, string::String, vec::VecInner};
22
use ufmt_write::uWrite;
33

44
impl<const N: usize> uWrite for String<N> {
@@ -8,7 +8,7 @@ impl<const N: usize> uWrite for String<N> {
88
}
99
}
1010

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

1818
#[cfg(test)]
1919
mod tests {
20-
use super::*;
20+
use crate::{String, Vec};
2121

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

0 commit comments

Comments
 (0)