token_ref_cell/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![forbid(clippy::semicolon_if_nothing_returned)]
3#![deny(missing_docs)]
4#![deny(missing_debug_implementations)]
5#![forbid(unsafe_op_in_unsafe_fn)]
6#![forbid(clippy::undocumented_unsafe_blocks)]
7//! This library provides [`TokenRefCell`], an interior mutability cell which uses an
8//! external [`Token`] reference to synchronize its accesses.
9//!
10//! Contrary to other standard cells like [`RefCell`](core::cell::RefCell),
11//! [`TokenRefCell`] is `Sync` as long as its token is `Send + Sync`;
12//! it can thus be used in multithreaded programs.
13//!
14//! Multiple token [implementations](token) are provided, the easiest to use being the
15//! smart-pointer-based ones: every `Box<T>` can indeed be used as a token (as long as `T`
16//! is not a ZST). The recommended token implementation is [`BoxToken`], and it's the
17//! default value of the generic parameter of [`TokenRefCell`].
18//!
19//! The runtime cost is very lightweight: only one pointer comparison for
20//! [`TokenRefCell::borrow`]/[`TokenRefCell::borrow_mut`] when using [`BoxToken`]
21//! (and zero-cost when using zero-sized tokens like [`singleton_token!`]).
22//! <br>
23//! Because one token can be used with multiple cells, it's possible for example to use
24//! a single rwlock wrapping a token to synchronize mutable access to multiple `Arc` data.
25//!
26//! # Examples
27//!
28//! ```rust
29//! # use std::sync::{Arc, RwLock};
30//! # use token_ref_cell::{TokenRefCell, BoxToken};
31//! let mut token = RwLock::new(BoxToken::new());
32//! // Initialize a vector of arcs
33//! let token_ref = token.read().unwrap();
34//! let arc_vec = vec![Arc::new(TokenRefCell::new(0, &*token_ref)); 42];
35//! drop(token_ref);
36//! // Use only one rwlock to write to all the arcs
37//! let mut token_mut = token.write().unwrap();
38//! for cell in &arc_vec {
39//!     *cell.borrow_mut(&mut *token_mut) += 1;
40//! }
41//! drop(token_mut)
42//! ```
43
44use core::{
45    cell::UnsafeCell,
46    fmt,
47    marker::PhantomData,
48    ops::{Deref, DerefMut},
49};
50
51use crate::{
52    error::{BorrowError, BorrowMutError},
53    token::Token,
54};
55
56pub mod error;
57mod repr_hack;
58pub mod token;
59
60#[cfg(feature = "alloc")]
61pub use token::BoxToken;
62
63macro_rules! repr {
64    ($Tk:ident::$name:ident $($tt:tt)*) => {
65        <<<$Tk as Token>::Id as crate::repr_hack::TokenId>::CellRepr as crate::repr_hack::CellRepr<$Tk::Id>>::$name$($tt)*
66    };
67}
68
69// Outline panic formatting, see `RefCell` implementation
70macro_rules! unwrap {
71    ($expr:expr) => {
72        match $expr {
73            Ok(ok) => ok,
74            Err(err) => err.panic(),
75        }
76    };
77}
78
79struct Invariant<T: ?Sized>(PhantomData<fn(T) -> T>);
80impl<T: ?Sized> Invariant<T> {
81    fn new() -> Self {
82        Self(PhantomData)
83    }
84}
85
86/// Interior mutability cell using an external [`Token`] reference to synchronize accesses.
87///
88/// Contrary to other standard cells like [`RefCell`](core::cell::RefCell),
89/// `TokenRefCell` is `Sync` as long as its token is `Send + Sync`.
90///
91/// # Memory layout
92///
93/// `TokenRefCell<T>` has the same in-memory representation as its inner type `T`
94/// when [`Token::Id`] is `()`.
95#[repr(transparent)]
96pub struct TokenRefCell<
97    T: ?Sized,
98    #[cfg(not(feature = "alloc"))] Tk: Token + ?Sized,
99    #[cfg(feature = "alloc")] Tk: Token + ?Sized = BoxToken,
100> {
101    _invariant: Invariant<Tk>,
102    cell: repr!(Tk::Cell<T>),
103}
104
105impl<T: ?Sized, Tk: Token + ?Sized> AsRef<TokenRefCell<T, Tk>> for &TokenRefCell<T, Tk> {
106    fn as_ref(&self) -> &TokenRefCell<T, Tk> {
107        self
108    }
109}
110
111// SAFETY: Inner `UnsafeCell` access is synchronized using `Token` uniqueness guarantee,
112// for which cross-threads behavior requires the token type to implement `Send + Sync`.
113unsafe impl<T: ?Sized + Sync, Tk: Token + ?Sized> Sync for TokenRefCell<T, Tk> where Tk: Send + Sync {}
114
115impl<T, Tk: Token + ?Sized> TokenRefCell<T, Tk> {
116    /// Creates a new `TokenRefCell` containing a `value`, synchronized by the given `token`.
117    #[inline]
118    pub fn new(value: T, token: &Tk) -> Self
119    where
120        repr!(Tk::Cell<T>): Sized,
121    {
122        Self::with_token_id(value, token.id())
123    }
124
125    /// Creates a new `TokenRefCell` containing a `value`, synchronized by a const token.
126    #[inline]
127    pub fn new_const(value: T) -> Self
128    where
129        Tk: Token<Id = ()>,
130    {
131        Self {
132            _invariant: Invariant::new(),
133            cell: UnsafeCell::new(value),
134        }
135    }
136
137    /// Creates a new `TokenRefCell` containing a `value`, synchronized by a token with the given id.
138    ///
139    /// It allows creating `TokenRefCell` when token is already borrowed.
140    #[inline]
141    pub fn with_token_id(value: T, token_id: Tk::Id) -> Self
142    where
143        repr!(Tk::Cell<T>): Sized,
144    {
145        Self {
146            _invariant: Invariant::new(),
147            cell: repr!(Tk::new)(value, token_id),
148        }
149    }
150
151    /// Consumes the `TokenRefCell`, returning the wrapped value.
152    #[inline]
153    pub fn into_inner(self) -> T
154    where
155        repr!(Tk::Cell<T>): Sized,
156    {
157        repr!(Tk::inner(self.cell))
158    }
159}
160
161impl<T: ?Sized, Tk: Token + ?Sized> TokenRefCell<T, Tk> {
162    #[inline]
163    fn get_ref(&self, token_id: Tk::Id) -> Result<Ref<T, Tk>, BorrowError> {
164        if *repr!(Tk::token_id)(&self.cell) == token_id {
165            Ok(Ref {
166                // SAFETY: `Token` trait guarantees that there can be only one token
167                // able to borrow the cell. Having a shared reference to this token
168                // ensures that the cell cannot be borrowed mutably.
169                inner: unsafe { &*repr!(Tk::get(&self.cell)) },
170                token_id,
171                _invariant: Invariant::new(),
172                _token_ref: PhantomData,
173            })
174        } else {
175            Err(BorrowError)
176        }
177    }
178
179    /// Immutably borrows the wrapped value using a shared reference to the token.
180    ///
181    /// The token reference is reborrowed in the returned `Ref`, preventing any aliasing
182    /// mutable borrow. Multiple immutable borrows can be taken out at the same time.
183    ///
184    /// The check runtime cost is only a token id comparison (when the token is not a
185    /// [`singleton_token!`]); there is no write, contrary to [`RefCell`](core::cell::RefCell)
186    /// or locks.
187    ///
188    /// # Panics
189    ///
190    /// Panics if the token doesn't match the one used at cell initialization (or set with
191    /// [`set_token`](Self::set_token)). For a non-panicking variant, use
192    /// [`try_borrow`](Self::try_borrow).
193    #[inline]
194    pub fn borrow<'a>(&'a self, token: &'a Tk) -> Ref<'a, T, Tk> {
195        unwrap!(self.try_borrow(token))
196    }
197
198    /// Tries to immutably borrow the wrapped value using a shared reference to the token.
199    ///
200    /// Returns an error if the token doesn't match the one used at cell initialization
201    /// (or set with [`set_token`](Self::set_token)). This is the non-panicking variant of
202    /// [`borrow`](Self::borrow).
203    ///
204    /// The token reference is reborrowed in the returned `Ref`, preventing any aliasing
205    /// mutable borrow. Multiple immutable borrows can be taken out at the same time.
206    ///
207    /// The check runtime cost is only a token id comparison (when the token is not a
208    /// [`singleton_token!`]); there is no write, contrary to [`RefCell`](core::cell::RefCell)
209    /// or locks.
210    #[inline]
211    pub fn try_borrow<'a>(&'a self, token: &'a Tk) -> Result<Ref<'a, T, Tk>, BorrowError> {
212        self.get_ref(token.id())
213    }
214
215    /// # Safety
216    ///
217    /// Token id must be retrieved from a unique token.
218    #[inline]
219    unsafe fn get_ref_mut(&self, token_id: Tk::Id) -> Result<RefMut<T, Tk>, BorrowMutError> {
220        if *repr!(Tk::token_id(&self.cell)) == token_id {
221            Ok(RefMut {
222                // SAFETY: `Token` trait guarantees that there can be only one token
223                // able to borrow the cell. Having an exclusive reference to this token
224                // ensures that the cell is exclusively borrowed.
225                inner: unsafe { &mut *repr!(Tk::get(&self.cell)) },
226                token_id,
227                _invariant: Invariant::new(),
228                _token_mut: PhantomData,
229            })
230        } else {
231            Err(BorrowMutError::WrongToken)
232        }
233    }
234
235    /// Mutably borrows the wrapped value using an exclusive reference to the token.
236    ///
237    /// The token reference is reborrowed in the returned `RefMut`, preventing any aliasing
238    /// mutable/immutable borrow.
239    ///
240    /// The check runtime cost is only a token id comparison (when the token is not a
241    /// [`singleton_token!`]), as well as a token unicity check (mostly a noop for most
242    /// of the token implementations); there is no write, contrary to
243    /// [`RefCell`](core::cell::RefCell) or locks.
244    ///
245    /// # Panics
246    ///
247    /// Panics if the token doesn't match the one used at cell initialization (or set with
248    /// [`set_token`](Self::set_token)), or if the token is not [unique](Token#safety).
249    /// For a non-panicking variant, use [`try_borrow`](Self::try_borrow_mut).
250    #[inline]
251    pub fn borrow_mut<'a>(&'a self, token: &'a mut Tk) -> RefMut<'a, T, Tk> {
252        unwrap!(self.try_borrow_mut(token))
253    }
254
255    /// Mutably borrows the wrapped value using an exclusive reference to the token.
256    ///
257    /// Returns an error if the token doesn't match the one used at cell initialization
258    /// (or set with [`set_token`](Self::set_token)), or if the token is not
259    /// [unique](Token#safety). For a non-panicking variant, use
260    /// [`try_borrow`](Self::try_borrow_mut).
261    ///
262    /// The token reference is reborrowed in the returned `RefMut`, preventing any aliasing
263    /// mutable/immutable borrow.
264    ///
265    /// The check runtime cost is only a token id comparison (when the token is not a
266    /// [`singleton_token!`]), as well as a token unicity check (mostly a noop for most
267    /// of the token implementations); there is no write, contrary to
268    /// [`RefCell`](core::cell::RefCell) or locks.
269    #[inline]
270    pub fn try_borrow_mut<'a>(
271        &'a self,
272        token: &'a mut Tk,
273    ) -> Result<RefMut<'a, T, Tk>, BorrowMutError> {
274        if !token.is_unique() {
275            return Err(BorrowMutError::NotUniqueToken);
276        }
277        // SAFETY: uniqueness is checked above
278        unsafe { self.get_ref_mut(token.id()) }
279    }
280
281    /// Gets a mutable pointer to the wrapped value.
282    #[inline]
283    pub fn as_ptr(&self) -> *mut T {
284        repr!(Tk::get(&self.cell))
285    }
286
287    /// Returns a mutable reference to the underlying data.
288    #[inline]
289    pub fn get_mut(&mut self) -> &mut T {
290        repr!(Tk::get_mut(&mut self.cell))
291    }
292
293    /// Returns a `&TokenRefCell<T, Tk>` from a `&mut T`
294    #[inline]
295    pub fn from_ref(t: &mut T) -> &Self
296    where
297        Tk: Token<Id = ()>,
298    {
299        // SAFETY: `&mut` ensures unique access, and `TokenRefCell<T>` has the same
300        // memory layout as `T`.
301        unsafe { &*(t as *mut T as *const TokenRefCell<T, Tk>) }
302    }
303
304    /// Set a new token to synchronize the cell.
305    #[inline]
306    pub fn set_token(&mut self, token: &Tk) {
307        self.set_token_id(token.id());
308    }
309
310    /// Get the id of the token by which the cell is synchronized.
311    #[inline]
312    pub fn token_id(&self) -> Tk::Id {
313        repr!(Tk::token_id(&self.cell)).clone()
314    }
315
316    /// Set a new token_id to synchronize the cell.
317    #[inline]
318    pub fn set_token_id(&mut self, token_id: Tk::Id) {
319        repr!(Tk::set_token_id(&mut self.cell, token_id));
320    }
321}
322
323impl<T, Tk: Token<Id = ()> + ?Sized> TokenRefCell<[T], Tk> {
324    /// Returns a `&[TokenRefCell<T>]` from a `&TokenRefCell<[T]>`
325    #[inline]
326    pub fn as_slice_of_cells(&self) -> &[TokenRefCell<T, Tk>]
327    where
328        Tk: Token<Id = ()>,
329    {
330        // SAFETY: `TokenRefCell<T>` has the same memory layout as `T`.
331        unsafe { &*(self as *const TokenRefCell<[T], Tk> as *const [TokenRefCell<T, Tk>]) }
332    }
333}
334
335impl<T: ?Sized + fmt::Debug, Tk: Token + ?Sized> fmt::Debug for TokenRefCell<T, Tk>
336where
337    Tk::Id: fmt::Debug,
338{
339    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340        f.debug_struct("TokenRefCell")
341            .field("token", repr!(Tk::token_id(&self.cell)))
342            .finish_non_exhaustive()
343    }
344}
345
346/// A wrapper type for an immutably borrowed value from a [`TokenRefCell`].
347///
348/// The token used for borrowing synchronization is also borrowed.
349/// Dedicated methods allows reusing the token for further borrowing.
350pub struct Ref<
351    'b,
352    T: ?Sized,
353    #[cfg(not(feature = "alloc"))] Tk: Token + ?Sized,
354    #[cfg(feature = "alloc")] Tk: Token + ?Sized = BoxToken,
355> {
356    inner: &'b T,
357    token_id: Tk::Id,
358    _invariant: Invariant<Tk>,
359    _token_ref: PhantomData<&'b Tk>,
360}
361
362impl<'b, T: ?Sized, Tk: Token + ?Sized> Ref<'b, T, Tk> {
363    /// Unwraps the inner reference.
364    pub fn into_ref(self) -> &'b T {
365        self.inner
366    }
367
368    /// Copies a `Ref`.
369    ///
370    /// This is an associated function that needs to be used as
371    /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere
372    /// with the widespread use of `cell.borrow(&token).clone()` to clone the contents of
373    /// a `TokenRefCell`.
374    #[allow(clippy::should_implement_trait)]
375    #[must_use]
376    #[inline]
377    pub fn clone(this: &Self) -> Self {
378        Self {
379            inner: this.inner,
380            token_id: this.token_id.clone(),
381            _invariant: Invariant::new(),
382            _token_ref: PhantomData,
383        }
384    }
385
386    /// Uses borrowed token shared reference to reborrow a [`TokenRefCell`].
387    ///
388    /// # Panics
389    ///
390    /// See [`TokenRefCell::borrow`].
391    #[inline]
392    pub fn reborrow<U: ?Sized>(&self, cell: impl FnOnce(&T) -> &TokenRefCell<U, Tk>) -> Ref<U, Tk> {
393        unwrap!(self.try_reborrow(cell))
394    }
395
396    /// Uses borrowed token shared reference to reborrow a `TokenRefCell`.
397    ///
398    /// See [`TokenRefCell::try_borrow`].
399    #[inline]
400    pub fn try_reborrow<U: ?Sized>(
401        &self,
402        cell: impl FnOnce(&T) -> &TokenRefCell<U, Tk>,
403    ) -> Result<Ref<U, Tk>, BorrowError> {
404        cell(self.inner).get_ref(self.token_id.clone())
405    }
406
407    /// Uses borrowed token shared reference to optionally reborrow a [`TokenRefCell`].
408    ///
409    /// # Panics
410    ///
411    /// See [`TokenRefCell::borrow`].
412    #[inline]
413    pub fn reborrow_opt<U: ?Sized>(
414        &self,
415        cell: impl FnOnce(&T) -> Option<&TokenRefCell<U, Tk>>,
416    ) -> Option<Ref<U, Tk>> {
417        Some(unwrap!(self.try_reborrow_opt(cell)?))
418    }
419
420    /// Uses borrowed token shared reference to optionally reborrow a [`TokenRefCell`].
421    ///
422    /// See [`TokenRefCell::try_borrow`].
423    #[inline]
424    pub fn try_reborrow_opt<U: ?Sized>(
425        &self,
426        cell: impl FnOnce(&T) -> Option<&TokenRefCell<U, Tk>>,
427    ) -> Option<Result<Ref<U, Tk>, BorrowError>> {
428        Some(cell(self.inner)?.get_ref(self.token_id.clone()))
429    }
430
431    /// Wraps the borrowed token shared reference into a stateful [`Reborrow`] instance.
432    ///
433    /// It can be used for example to reborrow cells from an iterator.
434    #[inline]
435    pub fn reborrow_stateful<'a, S>(
436        &'a self,
437        state: impl FnOnce(&'a T) -> S,
438    ) -> Reborrow<'a, S, Tk> {
439        Reborrow {
440            token_id: self.token_id.clone(),
441            _invariant: Invariant::new(),
442            _phantom: PhantomData,
443            state: state(self.inner),
444        }
445    }
446
447    /// Get the id of the borrowed token.
448    #[inline]
449    pub fn token_id(&self) -> Tk::Id {
450        self.token_id.clone()
451    }
452}
453
454impl<T: ?Sized, Tk: Token + ?Sized> Deref for Ref<'_, T, Tk> {
455    type Target = T;
456
457    #[inline]
458    fn deref(&self) -> &Self::Target {
459        self.inner
460    }
461}
462
463impl<T: ?Sized + fmt::Debug, Tk: Token + ?Sized> fmt::Debug for Ref<'_, T, Tk>
464where
465    Tk::Id: fmt::Debug,
466{
467    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468        f.debug_struct("Ref")
469            .field("inner", &self.inner)
470            .field("token_id", &self.token_id)
471            .finish()
472    }
473}
474
475impl<T: ?Sized + fmt::Display, Tk: Token + ?Sized> fmt::Display for Ref<'_, T, Tk> {
476    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
477        write!(f, "{}", &**self)
478    }
479}
480
481/// Stateful wrapper around a borrowed token shared reference.
482pub struct Reborrow<'b, S: ?Sized, Tk: Token + ?Sized> {
483    token_id: Tk::Id,
484    _invariant: Invariant<Tk>,
485    _phantom: PhantomData<&'b Tk>,
486    state: S,
487}
488
489impl<'b, S: ?Sized, Tk: Token + ?Sized> Reborrow<'b, S, Tk> {
490    /// Uses borrowed token shared reference to reborrow a [`TokenRefCell`].
491    ///
492    /// # Panics
493    ///
494    /// See [`TokenRefCell::borrow`].
495    pub fn reborrow<U: ?Sized>(
496        &mut self,
497        cell: impl FnOnce(&mut S) -> &TokenRefCell<U, Tk>,
498    ) -> Ref<U, Tk> {
499        unwrap!(self.try_reborrow(cell))
500    }
501
502    /// Uses borrowed token shared reference to reborrow a `TokenRefCell`.
503    ///
504    /// See [`TokenRefCell::try_borrow`].
505    pub fn try_reborrow<U: ?Sized>(
506        &mut self,
507        cell: impl FnOnce(&mut S) -> &TokenRefCell<U, Tk>,
508    ) -> Result<Ref<U, Tk>, BorrowError> {
509        cell(&mut self.state).get_ref(self.token_id.clone())
510    }
511
512    /// Uses borrowed token shared reference to optionally reborrow a [`TokenRefCell`].
513    ///
514    /// # Panics
515    ///
516    /// See [`TokenRefCell::borrow`].
517    pub fn reborrow_opt<U: ?Sized>(
518        &mut self,
519        cell: impl FnOnce(&mut S) -> Option<&TokenRefCell<U, Tk>>,
520    ) -> Option<Ref<U, Tk>> {
521        Some(unwrap!(self.try_reborrow_opt(cell)?))
522    }
523
524    /// Uses borrowed token shared reference to optionally reborrow a [`TokenRefCell`].
525    ///
526    /// See [`TokenRefCell::try_borrow`].
527    pub fn try_reborrow_opt<U: ?Sized>(
528        &mut self,
529        cell: impl FnOnce(&mut S) -> Option<&TokenRefCell<U, Tk>>,
530    ) -> Option<Result<Ref<U, Tk>, BorrowError>> {
531        Some(cell(&mut self.state)?.get_ref(self.token_id.clone()))
532    }
533
534    /// Get the id of the borrowed token.
535    #[inline]
536    pub fn token_id(&self) -> Tk::Id {
537        self.token_id.clone()
538    }
539}
540
541impl<S: ?Sized, Tk: Token + ?Sized> Deref for Reborrow<'_, S, Tk> {
542    type Target = S;
543
544    #[inline]
545    fn deref(&self) -> &Self::Target {
546        &self.state
547    }
548}
549
550impl<S: ?Sized, Tk: Token + ?Sized> DerefMut for Reborrow<'_, S, Tk> {
551    #[inline]
552    fn deref_mut(&mut self) -> &mut Self::Target {
553        &mut self.state
554    }
555}
556
557impl<S: ?Sized + fmt::Debug, Tk: Token + ?Sized> fmt::Debug for Reborrow<'_, S, Tk>
558where
559    Tk::Id: fmt::Debug,
560{
561    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562        f.debug_struct("Reborrow")
563            .field("state", &&self.state)
564            .field("token_id", &self.token_id)
565            .finish()
566    }
567}
568
569/// A wrapper type for a mutably borrowed value from a [`TokenRefCell`].
570///
571/// The token can be reused for further borrowing.
572pub struct RefMut<
573    'b,
574    T: ?Sized,
575    #[cfg(not(feature = "alloc"))] Tk: Token + ?Sized,
576    #[cfg(feature = "alloc")] Tk: Token + ?Sized = BoxToken,
577> {
578    inner: &'b mut T,
579    token_id: Tk::Id,
580    _invariant: Invariant<Tk>,
581    _token_mut: PhantomData<&'b mut Tk>,
582}
583
584impl<'b, T: ?Sized, Tk: Token + ?Sized> RefMut<'b, T, Tk> {
585    /// Unwraps the inner reference.
586    pub fn into_mut(self) -> &'b mut T {
587        self.inner
588    }
589
590    /// Borrows a `RefMut` as a [`Ref`].
591    pub fn as_ref(&self) -> Ref<T, Tk> {
592        Ref {
593            inner: self.inner,
594            token_id: self.token_id.clone(),
595            _invariant: Invariant::new(),
596            _token_ref: PhantomData,
597        }
598    }
599
600    /// Uses borrowed token exclusive reference to reborrow a [`TokenRefCell`].
601    ///
602    /// # Panics
603    ///
604    /// See [`TokenRefCell::borrow_mut`].
605    #[inline]
606    pub fn reborrow_mut<U: ?Sized>(
607        &mut self,
608        cell: impl FnOnce(&mut T) -> &TokenRefCell<U, Tk>,
609    ) -> RefMut<U, Tk> {
610        unwrap!(self.try_reborrow_mut(cell))
611    }
612
613    /// Uses borrowed token exclusive reference to reborrow a `TokenRefCell`.
614    ///
615    /// See [`TokenRefCell::try_borrow_mut`].
616    #[inline]
617    pub fn try_reborrow_mut<U: ?Sized>(
618        &mut self,
619        cell: impl FnOnce(&mut T) -> &TokenRefCell<U, Tk>,
620    ) -> Result<RefMut<U, Tk>, BorrowMutError> {
621        // SAFETY: token uniqueness has been checked to build the `RefMut`
622        unsafe { cell(self.inner).get_ref_mut(self.token_id.clone()) }
623    }
624
625    /// Uses borrowed token exclusive reference to optionally  reborrow a [`TokenRefCell`].
626    ///
627    /// # Panics
628    ///
629    /// See [`TokenRefCell::borrow_mut`].
630    #[inline]
631    pub fn reborrow_opt_mut<U: ?Sized>(
632        &mut self,
633        cell: impl FnOnce(&mut T) -> Option<&TokenRefCell<U, Tk>>,
634    ) -> Option<RefMut<U, Tk>> {
635        Some(unwrap!(self.try_reborrow_opt_mut(cell)?))
636    }
637
638    /// Uses borrowed token exclusive reference to optionally reborrow a `TokenRefCell`.
639    ///
640    /// See [`TokenRefCell::try_borrow_mut`].
641    #[inline]
642    pub fn try_reborrow_opt_mut<U: ?Sized>(
643        &mut self,
644        cell: impl FnOnce(&mut T) -> Option<&TokenRefCell<U, Tk>>,
645    ) -> Option<Result<RefMut<U, Tk>, BorrowMutError>> {
646        // SAFETY: token uniqueness has been checked to build the `RefMut`
647        Some(unsafe { cell(self.inner)?.get_ref_mut(self.token_id.clone()) })
648    }
649
650    /// Wraps the borrowed token exclusive reference into a stateful [`ReborrowMut`] instance.
651    ///
652    /// It can be used for example to reborrow cells from an iterator.
653    #[inline]
654    pub fn reborrow_stateful_mut<'a, S>(
655        &'a mut self,
656        state: impl FnOnce(&'a mut T) -> S,
657    ) -> ReborrowMut<'a, S, Tk> {
658        ReborrowMut {
659            state: state(self.inner),
660            token_id: self.token_id.clone(),
661            _invariant: Invariant::new(),
662            _phantom: PhantomData,
663        }
664    }
665
666    /// Get the id of the borrowed token.
667    #[inline]
668    pub fn token_id(&self) -> Tk::Id {
669        self.token_id.clone()
670    }
671}
672
673impl<T: ?Sized, Tk: Token + ?Sized> Deref for RefMut<'_, T, Tk> {
674    type Target = T;
675
676    #[inline]
677    fn deref(&self) -> &Self::Target {
678        self.inner
679    }
680}
681
682impl<T: ?Sized, Tk: Token + ?Sized> DerefMut for RefMut<'_, T, Tk> {
683    #[inline]
684    fn deref_mut(&mut self) -> &mut Self::Target {
685        self.inner
686    }
687}
688
689impl<T: ?Sized + fmt::Debug, Tk: Token + ?Sized> fmt::Debug for RefMut<'_, T, Tk>
690where
691    Tk::Id: fmt::Debug,
692{
693    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
694        f.debug_struct("RefMut")
695            .field("inner", &self.inner)
696            .field("token_id", &self.token_id)
697            .finish()
698    }
699}
700
701impl<T: ?Sized + fmt::Display, Tk: Token + ?Sized> fmt::Display for RefMut<'_, T, Tk> {
702    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
703        write!(f, "{}", &**self)
704    }
705}
706
707/// Stateful wrapper around a borrowed token exclusive reference.
708pub struct ReborrowMut<'b, S: ?Sized, Tk: Token + ?Sized> {
709    token_id: Tk::Id,
710    _invariant: Invariant<Tk>,
711    _phantom: PhantomData<&'b mut Tk>,
712    state: S,
713}
714
715impl<S: ?Sized, Tk: Token + ?Sized> ReborrowMut<'_, S, Tk> {
716    /// Uses borrowed token exclusive reference to reborrow a [`TokenRefCell`].
717    ///
718    /// # Panics
719    ///
720    /// See [`TokenRefCell::borrow_mut`].
721    pub fn reborrow_mut<U: ?Sized>(
722        &mut self,
723        cell: impl FnOnce(&mut S) -> &TokenRefCell<U, Tk>,
724    ) -> RefMut<U, Tk> {
725        unwrap!(self.try_reborrow_mut(cell))
726    }
727
728    /// Uses borrowed token exclusive reference to reborrow a `TokenRefCell`.
729    ///
730    /// See [`TokenRefCell::try_borrow_mut`].
731    pub fn try_reborrow_mut<U: ?Sized>(
732        &mut self,
733        cell: impl FnOnce(&mut S) -> &TokenRefCell<U, Tk>,
734    ) -> Result<RefMut<U, Tk>, BorrowMutError> {
735        // SAFETY: token uniqueness has been checked to build the `RefMut` and then `ReborrowMut`.
736        unsafe { cell(&mut self.state).get_ref_mut(self.token_id.clone()) }
737    }
738
739    /// Uses borrowed token exclusive reference to optionally  reborrow a [`TokenRefCell`].
740    ///
741    /// # Panics
742    ///
743    /// See [`TokenRefCell::borrow_mut`].
744    pub fn reborrow_opt_mut<U: ?Sized>(
745        &mut self,
746        cell: impl FnOnce(&mut S) -> Option<&TokenRefCell<U, Tk>>,
747    ) -> Option<RefMut<U, Tk>> {
748        Some(unwrap!(self.try_reborrow_opt_mut(cell)?))
749    }
750
751    /// Uses borrowed token exclusive reference to optionally reborrow a `TokenRefCell`.
752    ///
753    /// See [`TokenRefCell::try_borrow_mut`].
754    pub fn try_reborrow_opt_mut<U: ?Sized>(
755        &mut self,
756        cell: impl FnOnce(&mut S) -> Option<&TokenRefCell<U, Tk>>,
757    ) -> Option<Result<RefMut<U, Tk>, BorrowMutError>> {
758        // SAFETY: token uniqueness has been checked to build the `RefMut` and then `ReborrowMut`.
759        Some(unsafe { cell(&mut self.state)?.get_ref_mut(self.token_id.clone()) })
760    }
761
762    /// Get the id of the borrowed token.
763    #[inline]
764    pub fn token_id(&self) -> Tk::Id {
765        self.token_id.clone()
766    }
767}
768
769impl<S: ?Sized, Tk: Token + ?Sized> Deref for ReborrowMut<'_, S, Tk> {
770    type Target = S;
771
772    #[inline]
773    fn deref(&self) -> &Self::Target {
774        &self.state
775    }
776}
777
778impl<S: ?Sized, Tk: Token + ?Sized> DerefMut for ReborrowMut<'_, S, Tk> {
779    #[inline]
780    fn deref_mut(&mut self) -> &mut Self::Target {
781        &mut self.state
782    }
783}
784
785impl<S: ?Sized + fmt::Debug, Tk: Token + ?Sized> fmt::Debug for ReborrowMut<'_, S, Tk>
786where
787    Tk::Id: fmt::Debug,
788{
789    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790        f.debug_struct("ReborrowMut")
791            .field("state", &&self.state)
792            .field("token_id", &self.token_id)
793            .finish()
794    }
795}