contiguous_mem/
types.rs

1//! Module re-exporting used types any polyfill to help with feature support.
2
3#[cfg(not(feature = "no_std"))]
4mod std_imports {
5    pub use std::rc::Rc;
6    pub use std::sync::Arc;
7    pub use std::sync::Mutex;
8    pub use std::sync::MutexGuard;
9    pub use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
10
11    pub use std::alloc as allocator;
12}
13
14#[cfg(not(feature = "no_std"))]
15pub use std_imports::*;
16
17#[cfg(feature = "no_std")]
18mod nostd_imports {
19    pub use spin::Mutex;
20    pub use spin::MutexGuard;
21    pub use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};
22
23    pub use alloc::alloc as allocator;
24
25    pub use ::alloc::vec;
26    pub use ::alloc::vec::Vec;
27
28    pub use ::alloc::rc::Rc;
29    pub use ::alloc::sync::Arc;
30}
31#[cfg(feature = "no_std")]
32pub use nostd_imports::*;
33
34use crate::error::{LockSource, LockingError};
35
36/// Trait that adds a method which mimics std `Result::map_err` on a Lock in
37/// order to unify no_std and std environments.
38///
39/// This is necessary as [spin::Mutex::lock] doesn't return a Result but a
40/// [MutexGuard] directly.
41pub(crate) trait MutexTypesafe<T: ?Sized> {
42    fn lock_named(&self, source: LockSource) -> Result<MutexGuard<T>, crate::error::LockingError>;
43    fn try_lock_named(
44        &self,
45        source: LockSource,
46    ) -> Result<MutexGuard<T>, crate::error::LockingError>;
47}
48#[cfg(not(feature = "no_std"))]
49impl<T: ?Sized> MutexTypesafe<T> for Mutex<T> {
50    fn lock_named(&self, source: LockSource) -> Result<MutexGuard<T>, crate::error::LockingError> {
51        match self.lock() {
52            Ok(it) => Ok(it),
53            Err(_) => Err(LockingError::Poisoned { source }),
54        }
55    }
56    fn try_lock_named(
57        &self,
58        source: LockSource,
59    ) -> Result<MutexGuard<T>, crate::error::LockingError> {
60        match self.try_lock() {
61            Ok(it) => Ok(it),
62            Err(std::sync::TryLockError::Poisoned(_)) => Err(LockingError::Poisoned { source }),
63            Err(std::sync::TryLockError::WouldBlock) => Err(LockingError::WouldBlock { source }),
64        }
65    }
66}
67#[cfg(feature = "no_std")]
68impl<T: ?Sized> MutexTypesafe<T> for Mutex<T> {
69    fn lock_named(&self, _source: LockSource) -> Result<MutexGuard<T>, LockingError> {
70        Ok(self.lock())
71    }
72    fn try_lock_named(
73        &self,
74        source: LockSource,
75    ) -> Result<MutexGuard<T>, crate::error::LockingError> {
76        match self.try_lock() {
77            Some(it) => Ok(it),
78            None => Err(LockingError::WouldBlock { source }),
79        }
80    }
81}
82
83pub(crate) trait RwLockTypesafe<T: ?Sized> {
84    fn read_named(&self, source: LockSource) -> Result<RwLockReadGuard<T>, LockingError>;
85    fn try_read_named(&self, source: LockSource) -> Result<RwLockReadGuard<T>, LockingError>;
86    fn write_named(&self, source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError>;
87    fn try_write_named(&self, source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError>;
88}
89#[cfg(not(feature = "no_std"))]
90impl<T: ?Sized> RwLockTypesafe<T> for RwLock<T> {
91    fn read_named(&self, source: LockSource) -> Result<RwLockReadGuard<T>, LockingError> {
92        match self.read() {
93            Ok(guard) => Ok(guard),
94            Err(_) => Err(LockingError::Poisoned { source }),
95        }
96    }
97
98    fn try_read_named(&self, source: LockSource) -> Result<RwLockReadGuard<T>, LockingError> {
99        match self.try_read() {
100            Ok(guard) => Ok(guard),
101            Err(std::sync::TryLockError::WouldBlock) => Err(LockingError::WouldBlock { source }),
102            Err(std::sync::TryLockError::Poisoned(_)) => Err(LockingError::Poisoned { source }),
103        }
104    }
105
106    fn write_named(&self, source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError> {
107        match self.write() {
108            Ok(guard) => Ok(guard),
109            Err(_) => Err(LockingError::Poisoned { source }),
110        }
111    }
112
113    fn try_write_named(&self, source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError> {
114        match self.try_write() {
115            Ok(guard) => Ok(guard),
116            Err(std::sync::TryLockError::WouldBlock) => Err(LockingError::WouldBlock { source }),
117            Err(std::sync::TryLockError::Poisoned(_)) => Err(LockingError::Poisoned { source }),
118        }
119    }
120}
121#[cfg(feature = "no_std")]
122impl<T: ?Sized> RwLockTypesafe<T> for RwLock<T> {
123    fn read_named(&self, _source: LockSource) -> Result<RwLockReadGuard<T>, LockingError> {
124        Ok(self.read())
125    }
126
127    fn try_read_named(&self, source: LockSource) -> Result<RwLockReadGuard<T>, LockingError> {
128        match self.try_read() {
129            Some(guard) => Ok(guard),
130            None => Err(LockingError::WouldBlock { source }),
131        }
132    }
133
134    fn write_named(&self, _source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError> {
135        Ok(self.write())
136    }
137
138    fn try_write_named(&self, source: LockSource) -> Result<RwLockWriteGuard<T>, LockingError> {
139        match self.try_write() {
140            Some(guard) => Ok(guard),
141            None => Err(LockingError::WouldBlock { source }),
142        }
143    }
144}
145
146#[cfg(not(feature = "debug"))]
147pub trait DebugReq {}
148#[cfg(not(feature = "debug"))]
149impl<T: ?Sized> DebugReq for T {}
150
151#[cfg(feature = "debug")]
152pub trait DebugReq: core::fmt::Debug {}
153#[cfg(feature = "debug")]
154impl<T: ?Sized + core::fmt::Debug> DebugReq for T {}
155
156/// Size requirements for types pointed to by references
157#[cfg(feature = "ptr_metadata")]
158pub trait RefSizeReq {}
159#[cfg(feature = "ptr_metadata")]
160impl<T: ?Sized> RefSizeReq for T {}
161
162/// Size requirements for types pointed to by references
163#[cfg(not(feature = "ptr_metadata"))]
164pub trait RefSizeReq: Sized {}
165#[cfg(not(feature = "ptr_metadata"))]
166impl<T: Sized> RefSizeReq for T {}
167
168/// Type requirements for values that can be stored.
169pub trait StoreRequirements: 'static {}
170impl<T: 'static> StoreRequirements for T {}
171
172#[cfg(feature = "ptr_metadata")]
173pub use core::marker::Unsize;
174#[cfg(feature = "ptr_metadata")]
175pub use core::ptr::{DynMetadata, Pointee};
176
177/// Returns [`Pointee`] metadata for provided pair of struct `S` and some
178/// unsized type (e.g. a trait) `T`.
179///
180/// This metadata is usually a pointer to vtable of `T` implementation for
181/// `S`, but can be something else and the value is considered internal to
182/// the compiler.
183#[cfg(feature = "ptr_metadata")]
184pub const fn static_metadata<S, T: ?Sized>() -> <T as Pointee>::Metadata
185where
186    S: Unsize<T>,
187{
188    let (_, metadata) = (core::ptr::NonNull::<S>::dangling().as_ptr() as *const T).to_raw_parts();
189    metadata
190}
191
192pub(crate) type DropFn = fn(*mut ());
193pub(crate) const fn drop_fn<T>() -> fn(*mut ()) {
194    if core::mem::needs_drop::<T>() {
195        |ptr: *mut ()| unsafe { core::ptr::drop_in_place(ptr as *mut T) }
196    } else {
197        |_: *mut ()| {}
198    }
199}