async_fifo/fifo/
storage.rs

1use alloc::vec::Vec;
2
3/// Dyn-Compatible subset of [`Storage`] trait
4///
5/// Automatically derived for every Storage implementor.
6pub trait InternalStorageApi<T> {
7    fn bounds(&self) -> (Option<usize>, Option<usize>);
8    fn insert(&mut self, index: usize, item: T);
9    fn reserve(&mut self, len: usize);
10}
11
12/// Backing storage for pull operations
13pub trait Storage<T>: Sized {
14    type Output;
15
16    /// Insert an item into a storage slot
17    ///
18    /// `index` is the index of this push operation
19    /// since the call to `Consumer::try_recv_*`.
20    fn insert(&mut self, index: usize, item: T);
21
22    /// Called to seal the storage after all negociated
23    /// items have been received
24    ///
25    /// The negociated number of items is available as `pushed`.
26    fn finish(self, pushed: usize) -> Result<Self::Output, Self>;
27
28    #[allow(unused_variables)]
29    /// Pre-allocate space for `len` additional items
30    fn reserve(&mut self, len: usize) {}
31
32    /// Specify the number of items that this storage
33    /// can handle
34    ///
35    /// The value must be returned as (minimum, maximum).
36    fn bounds(&self) -> (Option<usize>, Option<usize>) {
37        (None, None)
38    }
39}
40
41impl<T, S: Storage<T>> InternalStorageApi<T> for S {
42    fn bounds(&self) -> (Option<usize>, Option<usize>) {
43        S::bounds(self)
44    }
45
46    fn insert(&mut self, index: usize, item: T) {
47        S::insert(self, index, item)
48    }
49
50    fn reserve(&mut self, len: usize) {
51        S::reserve(self, len)
52    }
53}
54
55impl<T> Storage<T> for &mut Vec<T> {
56    type Output = usize;
57
58    fn reserve(&mut self, len: usize) {
59        Vec::reserve(self, len);
60    }
61
62    fn insert(&mut self, _index: usize, item: T) {
63        Vec::push(self, item);
64    }
65
66    fn finish(self, pushed: usize) -> Result<Self::Output, Self> {
67        match pushed {
68            0 => Err(self),
69            _ => Ok(pushed),
70        }
71    }
72}
73
74impl<T> Storage<T> for &mut [T] {
75    type Output = ();
76
77    fn insert(&mut self, index: usize, item: T) {
78        self[index] = item;
79    }
80
81    fn bounds(&self) -> (Option<usize>, Option<usize>) {
82        (Some(self.len()), Some(self.len()))
83    }
84
85    fn finish(self, pushed: usize) -> Result<Self::Output, Self> {
86        match pushed {
87            0 => Err(self),
88            _ => Ok(()),
89        }
90    }
91}
92
93#[doc(hidden)]
94pub struct TmpArray<const N: usize, T> {
95    pub inner: [Option<T>; N],
96}
97
98impl<const N: usize, T> Default for TmpArray<N, T> {
99    fn default() -> Self {
100        Self { 
101            inner: core::array::from_fn(|_| None),
102        }
103    }
104}
105
106impl<const N: usize, T> Storage<T> for TmpArray<N, T> {
107    type Output = [T; N];
108
109    fn insert(&mut self, index: usize, item: T) {
110        self.inner[index] = Some(item);
111    }
112
113    fn bounds(&self) -> (Option<usize>, Option<usize>) {
114        (Some(N), Some(N))
115    }
116
117    fn finish(self, pushed: usize) -> Result<Self::Output, Self> {
118        match pushed {
119            0 => Err(self),
120            _ => Ok(self.inner.map(Option::unwrap)),
121        }
122    }
123}
124
125impl<T> Storage<T> for Option<T> {
126    type Output = T;
127
128    fn insert(&mut self, _index: usize, item: T) {
129        *self = Some(item);
130    }
131
132    fn bounds(&self) -> (Option<usize>, Option<usize>) {
133        (Some(1), Some(1))
134    }
135
136    fn finish(self, _pushed: usize) -> Result<Self::Output, Self> {
137        self.ok_or(None)
138    }
139}