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
80/// VecView` or `Box<Vec> -> Box<VecView>`, or explicitly with
81/// [`.as_view()`](crate::vec::Vec::as_view) or [`.as_mut_view()`](crate::vec::Vec::as_mut_view).
82///
83/// This trait is sealed, so you cannot implement it for your own types. You can only use
84/// the implementations provided by this crate.
85#[allow(private_bounds)]
86pub trait Storage: SealedStorage {}
87
88/// Implementation of [`Storage`] that stores the data in an array `[T; N]` whose size is known at
89/// compile time.
90pub enum OwnedStorage<const N: usize> {}
91impl<const N: usize> Storage for OwnedStorage<N> {}
92impl<const N: usize> SealedStorage for OwnedStorage<N> {
93    type Buffer<T> = [T; N];
94    fn len<T>(_: *const Self::Buffer<T>) -> usize {
95        N
96    }
97    fn as_ptr<T>(this: *mut Self::Buffer<T>) -> *mut T {
98        this.cast()
99    }
100    #[cfg(any(
101        feature = "portable-atomic",
102        all(feature = "mpmc_large", target_has_atomic = "ptr"),
103        all(not(feature = "mpmc_large"), target_has_atomic = "8")
104    ))]
105    fn as_mpmc_view<T>(this: &mpmc::Queue<T, N>) -> &mpmc::QueueView<T>
106    where
107        Self: Storage + Sized,
108    {
109        // Fails to compile without the indirection
110        this.as_view_private()
111    }
112    #[cfg(any(
113        feature = "portable-atomic",
114        all(feature = "mpmc_large", target_has_atomic = "ptr"),
115        all(not(feature = "mpmc_large"), target_has_atomic = "8")
116    ))]
117    fn as_mpmc_mut_view<T>(this: &mut mpmc::Queue<T, N>) -> &mut mpmc::QueueView<T>
118    where
119        Self: Storage + Sized,
120    {
121        // Fails to compile without the indirection
122        this.as_view_mut_private()
123    }
124    #[cfg(any(
125        feature = "portable-atomic",
126        target_has_atomic = "ptr",
127        has_atomic_load_store
128    ))]
129    /// Convert a `Queue` to a `QueueView`
130    fn as_queue_view<T>(this: &spsc::QueueInner<T, Self>) -> &spsc::QueueView<T>
131    where
132        Self: Storage + Sized,
133    {
134        // Fails to compile without the indirection
135        this.as_view_private()
136    }
137    #[cfg(any(
138        feature = "portable-atomic",
139        target_has_atomic = "ptr",
140        has_atomic_load_store
141    ))]
142    /// Convert a `Queue` to a `QueueView`
143    fn as_mut_queue_view<T>(this: &mut spsc::QueueInner<T, Self>) -> &mut spsc::QueueView<T>
144    where
145        Self: Storage + Sized,
146    {
147        // Fails to compile without the indirection
148        this.as_mut_view_private()
149    }
150}
151
152/// Implementation of [`Storage`] that stores the data in an unsized `[T]`.
153pub enum ViewStorage {}
154impl Storage for ViewStorage {}
155impl SealedStorage for ViewStorage {
156    type Buffer<T> = [T];
157    fn len<T>(this: *const Self::Buffer<T>) -> usize {
158        this.len()
159    }
160
161    fn as_ptr<T>(this: *mut Self::Buffer<T>) -> *mut T {
162        this.cast()
163    }
164
165    #[cfg(any(
166        feature = "portable-atomic",
167        all(feature = "mpmc_large", target_has_atomic = "ptr"),
168        all(not(feature = "mpmc_large"), target_has_atomic = "8")
169    ))]
170    fn as_mpmc_view<T>(this: &mpmc::QueueInner<T, Self>) -> &mpmc::QueueView<T>
171    where
172        Self: Storage + Sized,
173    {
174        this
175    }
176
177    #[cfg(any(
178        feature = "portable-atomic",
179        all(feature = "mpmc_large", target_has_atomic = "ptr"),
180        all(not(feature = "mpmc_large"), target_has_atomic = "8")
181    ))]
182    fn as_mpmc_mut_view<T>(this: &mut mpmc::QueueInner<T, Self>) -> &mut mpmc::QueueView<T>
183    where
184        Self: Storage + Sized,
185    {
186        this
187    }
188
189    #[cfg(any(
190        feature = "portable-atomic",
191        target_has_atomic = "ptr",
192        has_atomic_load_store
193    ))]
194    /// Convert a `Queue` to a `QueueView`
195    fn as_queue_view<T>(this: &spsc::QueueInner<T, Self>) -> &spsc::QueueView<T>
196    where
197        Self: Storage + Sized,
198    {
199        this
200    }
201    #[cfg(any(
202        feature = "portable-atomic",
203        target_has_atomic = "ptr",
204        has_atomic_load_store
205    ))]
206    /// Convert a `Queue` to a `QueueView`
207    fn as_mut_queue_view<T>(this: &mut spsc::QueueInner<T, Self>) -> &mut spsc::QueueView<T>
208    where
209        Self: Storage + Sized,
210    {
211        this
212    }
213}