read_cell/
lib.rs

1//!
2//! Provides read-only counterpart to standard [`Cell`] type.
3//! Unlike [`Cell`], [`ReadCell`] cannot be used to mutate inner value, just like [`&T`],
4//! but similar to [`Cell`] it cannot be used to get [`&T`] to the inner value.
5//!
6//! While [`&Cell<T>`] references and [`&T`] references to the same value cannot coexist,
7//! [`&ReadCell<T>`] reference and [`&Cell<T>`] reference to the same value can coexist.
8//! As well as [`&ReadCell<T>`] reference and [`&T`] reference to the same value can coexist.
9//!
10//! [`&Cell<T>`]: `Cell`
11//! [`&ReadCell<T>`]: `ReadCell`
12//! [`&T`]: `reference`
13
14#![no_std]
15
16use core::{
17    cell::{Cell, UnsafeCell},
18    cmp::Ordering,
19};
20
21/// A possible mutable memory location.
22/// It provides only non-mutating subset of [`Cell`] API.
23/// This allows [`&ReadCell<T>`] share value with [`&Cell<T>`] and [`&T`] alike.
24///
25/// [`&ReadCell<T>`]: `ReadCell`
26/// [`&Cell<T>`]: `Cell`
27/// [`&T`]: `reference`
28///
29/// # Example
30///
31/// ```
32/// use std::cell::Cell;
33/// use read_cell::ReadCell;
34///
35/// struct SomeStruct {
36///     regular_field: u8,
37///     special_field: Cell<u8>,
38/// }
39///
40/// let my_struct = SomeStruct {
41///     regular_field: 0,
42///     special_field: Cell::new(1),
43/// };
44///
45/// let new_value = 100;
46///
47/// let regular_field_read = ReadCell::from_ref(&my_struct.regular_field);
48/// let special_field_read = ReadCell::from_cell(&my_struct.special_field);
49///
50/// assert_eq!(regular_field_read.get(), 0);
51/// assert_eq!(special_field_read.get(), 1);
52///
53/// my_struct.special_field.set(new_value);
54/// assert_eq!(special_field_read.get(), new_value);
55/// ```
56#[repr(transparent)]
57pub struct ReadCell<T: ?Sized> {
58    value: UnsafeCell<T>,
59}
60
61impl<T: Copy> Clone for ReadCell<T> {
62    #[inline]
63    fn clone(&self) -> ReadCell<T> {
64        ReadCell::new(self.get())
65    }
66}
67
68impl<T: Default> Default for ReadCell<T> {
69    /// Creates a `ReadCell<T>`, with the `Default` value for T.
70    #[inline]
71    fn default() -> ReadCell<T> {
72        ReadCell::new(Default::default())
73    }
74}
75
76impl<T: PartialEq + Copy> PartialEq for ReadCell<T> {
77    #[inline]
78    fn eq(&self, other: &ReadCell<T>) -> bool {
79        self.get() == other.get()
80    }
81}
82
83impl<T: Eq + Copy> Eq for ReadCell<T> {}
84
85impl<T: PartialOrd + Copy> PartialOrd for ReadCell<T> {
86    #[inline]
87    fn partial_cmp(&self, other: &ReadCell<T>) -> Option<Ordering> {
88        self.get().partial_cmp(&other.get())
89    }
90
91    #[inline]
92    fn lt(&self, other: &ReadCell<T>) -> bool {
93        self.get() < other.get()
94    }
95
96    #[inline]
97    fn le(&self, other: &ReadCell<T>) -> bool {
98        self.get() <= other.get()
99    }
100
101    #[inline]
102    fn gt(&self, other: &ReadCell<T>) -> bool {
103        self.get() > other.get()
104    }
105
106    #[inline]
107    fn ge(&self, other: &ReadCell<T>) -> bool {
108        self.get() >= other.get()
109    }
110}
111
112impl<T: Ord + Copy> Ord for ReadCell<T> {
113    #[inline]
114    fn cmp(&self, other: &ReadCell<T>) -> Ordering {
115        self.get().cmp(&other.get())
116    }
117}
118
119impl<T> From<T> for ReadCell<T> {
120    /// Creates a new `ReadCell<T>` containing the given value.
121    fn from(t: T) -> ReadCell<T> {
122        ReadCell::new(t)
123    }
124}
125
126impl<T> ReadCell<T> {
127    /// Creates a new `ReadCell` containing the given value.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use read_cell::ReadCell;
133    ///
134    /// let c = ReadCell::new(5);
135    /// ```
136    #[inline]
137    pub const fn new(value: T) -> ReadCell<T> {
138        ReadCell {
139            value: UnsafeCell::new(value),
140        }
141    }
142
143    /// Unwraps the value.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use read_cell::ReadCell;
149    ///
150    /// let c = ReadCell::new(5);
151    /// let five = c.into_inner();
152    ///
153    /// assert_eq!(five, 5);
154    /// ```
155    pub fn into_inner(self) -> T {
156        self.value.into_inner()
157    }
158}
159
160impl<T: Copy> ReadCell<T> {
161    /// Returns a copy of the contained value.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use read_cell::ReadCell;
167    ///
168    /// let c = ReadCell::new(5);
169    ///
170    /// let five = c.get();
171    /// ```
172    #[inline]
173    pub fn get(&self) -> T {
174        // SAFETY: This can cause data races if called from a separate thread,
175        // but `ReadCell` is `!Sync` so this won't happen.
176        unsafe { *self.value.get() }
177    }
178}
179
180impl<T: ?Sized> ReadCell<T> {
181    /// Returns a raw pointer to the underlying data in this cell.
182    ///
183    /// # Examples
184    ///
185    /// ```
186    /// use read_cell::ReadCell;
187    ///
188    /// let c = ReadCell::new(5);
189    ///
190    /// let ptr = c.as_ptr();
191    /// ```
192    #[inline]
193    pub const fn as_ptr(&self) -> *mut T {
194        self.value.get()
195    }
196
197    /// Returns a mutable reference to the underlying data.
198    ///
199    /// This call borrows `ReadCell` mutably (at compile-time) which guarantees
200    /// that we possess the only reference.
201    ///
202    /// However be cautious: this method expects `self` to be mutable, which is
203    /// generally not the case when using a [`ReadCell`]. If you require interior
204    /// mutability by reference, consider using [`RefCell`] which provides
205    /// run-time checked mutable borrows through its [`borrow_mut`] method.
206    ///
207    /// [`RefCell`]: `core::cell::RefCell`
208    /// [`borrow_mut`]: `core::cell::RefCell::borrow_mut`
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// use read_cell::ReadCell;
214    ///
215    /// let mut c = ReadCell::new(5);
216    /// *c.get_mut() += 1;
217    ///
218    /// assert_eq!(c.get(), 6);
219    /// ```
220    #[inline]
221    pub fn get_mut(&mut self) -> &mut T {
222        self.value.get_mut()
223    }
224
225    /// Returns a `&ReadCell<T>` from a `&T`
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// use read_cell::ReadCell;
231    ///
232    /// let slice: &[i32] = &[1, 2, 3];
233    /// let cell_slice: &ReadCell<[i32]> = ReadCell::from_ref(slice);
234    /// let slice_cell: &[ReadCell<i32>] = cell_slice.as_slice_of_cells();
235    ///
236    /// assert_eq!(slice_cell.len(), 3);
237    /// ```
238    #[inline]
239    pub fn from_ref(t: &T) -> &ReadCell<T> {
240        // SAFETY: `&ReadCell<T>` disallows mutations.
241        unsafe { &*(t as *const T as *const ReadCell<T>) }
242    }
243
244    /// Returns a `&ReadCell<T>` from a `&Cell<T>`
245    ///
246    /// # Examples
247    ///
248    /// ```
249    /// use std::cell::Cell;
250    /// use read_cell::ReadCell;
251    ///
252    /// let slice: &Cell<[i32]> = &Cell::new([1, 2, 3]);
253    /// let cell_slice: &ReadCell<[i32]> = ReadCell::from_cell(slice);
254    /// let slice_cell: &[ReadCell<i32>] = cell_slice.as_slice_of_cells();
255    ///
256    /// assert_eq!(slice_cell.len(), 3);
257    /// ```
258    #[inline]
259    pub fn from_cell(t: &Cell<T>) -> &ReadCell<T> {
260        // SAFETY: `&ReadCell<T>` is more restricted than `Cell`.
261        unsafe { &*(t.as_ptr() as *const ReadCell<T>) }
262    }
263}
264
265impl<T> ReadCell<[T]> {
266    /// Returns a `&[ReadCell<T>]` from a `&ReadCell<[T]>`
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use read_cell::ReadCell;
272    ///
273    /// let slice: &[i32] = &[1, 2, 3];
274    /// let cell_slice: &ReadCell<[i32]> = ReadCell::from_ref(slice);
275    /// let slice_cell: &[ReadCell<i32>] = cell_slice.as_slice_of_cells();
276    ///
277    /// assert_eq!(slice_cell.len(), 3);
278    /// ```
279    pub fn as_slice_of_cells(&self) -> &[ReadCell<T>] {
280        // SAFETY: `ReadCell<T>` has the same memory layout as `T`.
281        unsafe { &*(self as *const ReadCell<[T]> as *const [ReadCell<T>]) }
282    }
283}
284
285impl<T, const N: usize> ReadCell<[T; N]> {
286    /// Returns a `&[ReadCell<T>; N]` from a `&ReadCell<[T; N]>`
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// use read_cell::ReadCell;
292    ///
293    /// let mut array: [i32; 3] = [1, 2, 3];
294    /// let cell_array: &ReadCell<[i32; 3]> = ReadCell::from_ref(&array);
295    /// let array_cell: &[ReadCell<i32>; 3] = cell_array.as_array_of_cells();
296    /// ```
297    pub fn as_array_of_cells(&self) -> &[ReadCell<T>; N] {
298        // SAFETY: `ReadCell<T>` has the same memory layout as `T`.
299        unsafe { &*(self as *const ReadCell<[T; N]> as *const [ReadCell<T>; N]) }
300    }
301}