zone_alloc/
element.rs

1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4#[cfg(feature = "std")]
5extern crate core;
6
7use core::{
8    cell::Cell,
9    fmt::Debug,
10    marker::PhantomData,
11    ops::{
12        Deref,
13        DerefMut,
14    },
15    ptr::NonNull,
16};
17
18/// The state of a borrowed element.
19#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
20pub(crate) enum BorrowState {
21    /// The element is not borrowed.
22    #[default]
23    NotBorrowed,
24    /// The element is borrowed with N readers.
25    Reading(usize),
26    /// The element is borrowed for writing.
27    Writing,
28}
29
30impl BorrowState {
31    #[inline]
32    fn add_reader(self) -> Option<Self> {
33        match self {
34            Self::NotBorrowed => Some(Self::Reading(1)),
35            Self::Reading(n) => Some(Self::Reading(n + 1)),
36            Self::Writing => None,
37        }
38    }
39
40    #[inline]
41    fn add_reader_unchecked(self) -> Self {
42        match self {
43            Self::Reading(n) => Self::Reading(n + 1),
44            _ => unreachable!(),
45        }
46    }
47
48    #[inline]
49    fn drop_reader(self) -> Self {
50        match self {
51            Self::Reading(n) if n > 1 => Self::Reading(n - 1),
52            _ => Self::NotBorrowed,
53        }
54    }
55
56    #[inline]
57    fn add_writer(self) -> Option<Self> {
58        match self {
59            Self::NotBorrowed => Some(Self::Writing),
60            _ => None,
61        }
62    }
63}
64
65/// A borrow reference, which is a shared reference to an element's borrow state.
66///
67/// This object is guaranteed to not own any state (all state is borrowed).
68#[derive(Debug)]
69pub(crate) struct BorrowRef<'borrow> {
70    state: &'borrow Cell<BorrowState>,
71}
72
73impl<'borrow> BorrowRef<'borrow> {
74    pub fn new(state: &'borrow Cell<BorrowState>) -> Option<Self> {
75        state.set(state.get().add_reader()?);
76        Some(Self { state })
77    }
78}
79
80impl Clone for BorrowRef<'_> {
81    fn clone(&self) -> Self {
82        self.state.set(self.state.get().add_reader_unchecked());
83        Self { state: self.state }
84    }
85}
86
87#[cfg(feature = "may-dangle")]
88unsafe impl<#[may_dangle] 'borrow> Drop for BorrowRef<'borrow> {
89    #[inline]
90    fn drop(&mut self) {
91        self.state.set(self.state.get().drop_reader());
92    }
93}
94
95#[cfg(not(feature = "may-dangle"))]
96impl Drop for BorrowRef<'_> {
97    #[inline]
98    fn drop(&mut self) {
99        self.state.set(self.state.get().drop_reader());
100    }
101}
102
103/// A mutable borrow reference, which is a reference to an element's borrow state.
104///
105/// This object is guaranteed to not own any state (all state is borrowed).
106#[derive(Debug)]
107pub(crate) struct BorrowRefMut<'borrow> {
108    state: &'borrow Cell<BorrowState>,
109}
110
111impl<'borrow> BorrowRefMut<'borrow> {
112    pub fn new(state: &'borrow Cell<BorrowState>) -> Option<Self> {
113        state.set(state.get().add_writer()?);
114        Some(Self { state })
115    }
116}
117
118#[cfg(feature = "may-dangle")]
119unsafe impl<#[may_dangle] 'borrow> Drop for BorrowRefMut<'borrow> {
120    #[inline]
121    fn drop(&mut self) {
122        self.state.set(BorrowState::NotBorrowed);
123    }
124}
125
126#[cfg(not(feature = "may-dangle"))]
127impl Drop for BorrowRefMut<'_> {
128    #[inline]
129    fn drop(&mut self) {
130        self.state.set(BorrowState::NotBorrowed);
131    }
132}
133
134/// An immutably borrowed element.
135///
136/// This object is guaranteed to not own any state (all state is borrowed).
137#[derive(Clone)]
138pub struct ElementRef<'borrow, T> {
139    value: NonNull<T>,
140    #[allow(unused)]
141    borrow_ref: BorrowRef<'borrow>,
142}
143
144impl<'borrow, T> ElementRef<'borrow, T>
145where
146    T: 'borrow,
147{
148    /// Creates a new immutable borrow.
149    pub(crate) fn new(value: NonNull<T>, borrow_ref: BorrowRef<'borrow>) -> Self {
150        Self { value, borrow_ref }
151    }
152}
153
154impl<T> Deref for ElementRef<'_, T> {
155    type Target = T;
156    #[inline]
157    fn deref(&self) -> &Self::Target {
158        unsafe { self.value.as_ref() }
159    }
160}
161
162impl<'borrow, T> AsRef<T> for ElementRef<'borrow, T> {
163    #[inline]
164    fn as_ref(&self) -> &T {
165        self.deref()
166    }
167}
168
169impl<T> Debug for ElementRef<'_, T>
170where
171    T: Debug,
172{
173    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174        write!(f, "{:?}", self.deref())
175    }
176}
177
178/// A mutably borrowed element.
179///
180/// This object is guaranteed to not own any state (all state is borrowed).
181pub struct ElementRefMut<'borrow, T> {
182    value: NonNull<T>,
183    #[allow(unused)]
184    borrow_ref: BorrowRefMut<'borrow>,
185    phantom: PhantomData<&'borrow mut T>,
186}
187
188impl<'borrow, T> ElementRefMut<'borrow, T>
189where
190    T: 'borrow,
191{
192    /// Creates a new mutable borrow.
193    pub(crate) fn new(value: NonNull<T>, borrow_ref: BorrowRefMut<'borrow>) -> Self {
194        Self {
195            value,
196            borrow_ref,
197            phantom: PhantomData,
198        }
199    }
200}
201
202impl<'borrow, T> Deref for ElementRefMut<'borrow, T> {
203    type Target = T;
204    #[inline]
205    fn deref(&self) -> &'borrow Self::Target {
206        unsafe { self.value.as_ref() }
207    }
208}
209
210impl<'borrow, T> DerefMut for ElementRefMut<'borrow, T> {
211    #[inline]
212    fn deref_mut(&mut self) -> &'borrow mut Self::Target {
213        unsafe { self.value.as_mut() }
214    }
215}
216
217impl<'borrow, T> AsRef<T> for ElementRefMut<'borrow, T> {
218    #[inline]
219    fn as_ref(&self) -> &T {
220        self.deref()
221    }
222}
223
224impl<'borrow, T> AsMut<T> for ElementRefMut<'borrow, T> {
225    #[inline]
226    fn as_mut(&mut self) -> &mut T {
227        self.deref_mut()
228    }
229}
230
231impl<T> Debug for ElementRefMut<'_, T>
232where
233    T: Debug,
234{
235    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
236        write!(f, "{:?}", self.deref())
237    }
238}