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}