heapless/
storage.rs

1//! `Storage` trait defining how data is stored in a container.
2
3use core::borrow::{Borrow, BorrowMut};
4
5#[cfg(any(
6    feature = "portable-atomic",
7    target_has_atomic = "ptr",
8    has_atomic_load_store
9))]
10use crate::spsc;
11
12#[cfg(any(
13    feature = "portable-atomic",
14    all(feature = "mpmc_large", target_has_atomic = "ptr"),
15    all(not(feature = "mpmc_large"), target_has_atomic = "8")
16))]
17use crate::mpmc;
18
19pub(crate) trait SealedStorage {
20    type Buffer<T>: ?Sized + Borrow<[T]> + BorrowMut<[T]>;
21    /// Obtain the length of the buffer
22    #[allow(unused)]
23    fn len<T>(this: *const Self::Buffer<T>) -> usize;
24    /// Obtain access to the first element of the buffer
25    #[allow(unused)]
26    fn as_ptr<T>(this: *mut Self::Buffer<T>) -> *mut T;
27
28    #[cfg(any(
29        feature = "portable-atomic",
30        all(feature = "mpmc_large", target_has_atomic = "ptr"),
31        all(not(feature = "mpmc_large"), target_has_atomic = "8")
32    ))]
33    fn as_mpmc_view<T>(this: &mpmc::QueueInner<T, Self>) -> &mpmc::QueueView<T>
34    where
35        Self: Storage + Sized;
36    #[cfg(any(
37        feature = "portable-atomic",
38        all(feature = "mpmc_large", target_has_atomic = "ptr"),
39        all(not(feature = "mpmc_large"), target_has_atomic = "8")
40    ))]
41    fn as_mpmc_mut_view<T>(this: &mut mpmc::QueueInner<T, Self>) -> &mut mpmc::QueueView<T>
42    where
43        Self: Storage + Sized;
44
45    #[cfg(any(
46        feature = "portable-atomic",
47        target_has_atomic = "ptr",
48        has_atomic_load_store
49    ))]
50    /// Convert a `Queue` to a `QueueView`
51    fn as_queue_view<T>(this: &spsc::QueueInner<T, Self>) -> &spsc::QueueView<T>
52    where
53        Self: Storage + Sized;
54    #[cfg(any(
55        feature = "portable-atomic",
56        target_has_atomic = "ptr",
57        has_atomic_load_store
58    ))]
59    /// Convert a `Queue` to a `QueueView`
60    fn as_mut_queue_view<T>(this: &mut spsc::QueueInner<T, Self>) -> &mut spsc::QueueView<T>
61    where
62        Self: Storage + Sized;
63}
64
65/// Trait defining how data for a container is stored.
66///
67/// There's two implementations available:
68///
69/// - [`OwnedStorage`]: stores the data in an array `[T; N]` whose size is known at compile time.
70/// - [`ViewStorage`]: stores the data in an unsized `[T]`.
71///
72/// This allows containers to be generic over either sized or unsized storage. For example,
73/// the [`vec`](crate::vec) module contains a [`VecInner`](crate::vec::VecInner) struct
74/// that's generic on [`Storage`], and two type aliases for convenience:
75///
76/// - [`Vec<T, N>`](crate::vec::Vec) = `VecInner<T, OwnedStorage<N>>`
77/// - [`VecView<T>`](crate::vec::VecView) = `VecInner<T, ViewStorage>`
78///
79/// `Vec` can be unsized into `VecView`, either by unsizing coercions such as `&mut Vec -> &mut VecView` or
80/// `Box<Vec> -> Box<VecView>`, or explicitly with [`.as_view()`](crate::vec::Vec::as_view) or [`.as_mut_view()`](crate::vec::Vec::as_mut_view).
81///
82/// This trait is sealed, so you cannot implement it for your own types. You can only use
83/// the implementations provided by this crate.
84#[allow(private_bounds)]
85pub trait Storage: SealedStorage {}
86
87/// Implementation of [`Storage`] that stores the data in an array `[T; N]` whose size is known at compile time.
88pub enum OwnedStorage<const N: usize> {}
89impl<const N: usize> Storage for OwnedStorage<N> {}
90impl<const N: usize> SealedStorage for OwnedStorage<N> {
91    type Buffer<T> = [T; N];
92    fn len<T>(_: *const Self::Buffer<T>) -> usize {
93        N
94    }
95    fn as_ptr<T>(this: *mut Self::Buffer<T>) -> *mut T {
96        this.cast()
97    }
98    #[cfg(any(
99        feature = "portable-atomic",
100        all(feature = "mpmc_large", target_has_atomic = "ptr"),
101        all(not(feature = "mpmc_large"), target_has_atomic = "8")
102    ))]
103    fn as_mpmc_view<T>(this: &mpmc::Queue<T, N>) -> &mpmc::QueueView<T>
104    where
105        Self: Storage + Sized,
106    {
107        // Fails to compile without the indirection
108        this.as_view_private()
109    }
110    #[cfg(any(
111        feature = "portable-atomic",
112        all(feature = "mpmc_large", target_has_atomic = "ptr"),
113        all(not(feature = "mpmc_large"), target_has_atomic = "8")
114    ))]
115    fn as_mpmc_mut_view<T>(this: &mut mpmc::Queue<T, N>) -> &mut mpmc::QueueView<T>
116    where
117        Self: Storage + Sized,
118    {
119        // Fails to compile without the indirection
120        this.as_view_mut_private()
121    }
122    #[cfg(any(
123        feature = "portable-atomic",
124        target_has_atomic = "ptr",
125        has_atomic_load_store
126    ))]
127    /// Convert a `Queue` to a `QueueView`
128    fn as_queue_view<T>(this: &spsc::QueueInner<T, Self>) -> &spsc::QueueView<T>
129    where
130        Self: Storage + Sized,
131    {
132        // Fails to compile without the indirection
133        this.as_view_private()
134    }
135    #[cfg(any(
136        feature = "portable-atomic",
137        target_has_atomic = "ptr",
138        has_atomic_load_store
139    ))]
140    /// Convert a `Queue` to a `QueueView`
141    fn as_mut_queue_view<T>(this: &mut spsc::QueueInner<T, Self>) -> &mut spsc::QueueView<T>
142    where
143        Self: Storage + Sized,
144    {
145        // Fails to compile without the indirection
146        this.as_mut_view_private()
147    }
148}
149
150/// Implementation of [`Storage`] that stores the data in an unsized `[T]`.
151pub enum ViewStorage {}
152impl Storage for ViewStorage {}
153impl SealedStorage for ViewStorage {
154    type Buffer<T> = [T];
155    fn len<T>(this: *const Self::Buffer<T>) -> usize {
156        this.len()
157    }
158
159    fn as_ptr<T>(this: *mut Self::Buffer<T>) -> *mut T {
160        this.cast()
161    }
162
163    #[cfg(any(
164        feature = "portable-atomic",
165        all(feature = "mpmc_large", target_has_atomic = "ptr"),
166        all(not(feature = "mpmc_large"), target_has_atomic = "8")
167    ))]
168    fn as_mpmc_view<T>(this: &mpmc::QueueInner<T, Self>) -> &mpmc::QueueView<T>
169    where
170        Self: Storage + Sized,
171    {
172        this
173    }
174
175    #[cfg(any(
176        feature = "portable-atomic",
177        all(feature = "mpmc_large", target_has_atomic = "ptr"),
178        all(not(feature = "mpmc_large"), target_has_atomic = "8")
179    ))]
180    fn as_mpmc_mut_view<T>(this: &mut mpmc::QueueInner<T, Self>) -> &mut mpmc::QueueView<T>
181    where
182        Self: Storage + Sized,
183    {
184        this
185    }
186
187    #[cfg(any(
188        feature = "portable-atomic",
189        target_has_atomic = "ptr",
190        has_atomic_load_store
191    ))]
192    /// Convert a `Queue` to a `QueueView`
193    fn as_queue_view<T>(this: &spsc::QueueInner<T, Self>) -> &spsc::QueueView<T>
194    where
195        Self: Storage + Sized,
196    {
197        this
198    }
199    #[cfg(any(
200        feature = "portable-atomic",
201        target_has_atomic = "ptr",
202        has_atomic_load_store
203    ))]
204    /// Convert a `Queue` to a `QueueView`
205    fn as_mut_queue_view<T>(this: &mut spsc::QueueInner<T, Self>) -> &mut spsc::QueueView<T>
206    where
207        Self: Storage + Sized,
208    {
209        this
210    }
211}