Skip to main content

reading_liner/stream/
alias.rs

1//! Helpers for aliasing mutable [Index] storage in the stream layer.
2//!
3//! [crate::Stream] must be able to update and query an index while reading bytes.
4//! Depending on the caller's ownership model, the index can be either:
5//!
6//! - `Direct(&mut Index)`: exclusive borrow, no runtime borrow checks.
7//! - `Shared(Rc<RefCell<Index>>)`: shared aliasing inside a single thread.
8//!
9//! The shared variant is intended for the case where multiple owners need to
10//! query the same index, while the direct variant is optimized for a single
11//! exclusive stream owner.
12use crate::Index;
13use std::{
14    cell::{Ref, RefCell, RefMut},
15    ops,
16    rc::Rc,
17};
18
19#[derive(Debug)]
20/// A mutable index reference used by [crate::Stream].
21///
22/// This enum abstracts over two index ownership patterns:
23///
24/// - `Direct(&mut Index)`: the stream owns an exclusive mutable borrow of the index.
25/// - `Shared(Rc<RefCell<Index>>)`: the stream borrows the index through runtime-checked
26///   interior mutability, allowing aliasing within a single thread.
27///
28/// Use `Direct` when the stream is the only owner of the index. Use `Shared`
29/// when the same index must be accessed from multiple aliasing locations.
30pub enum IndexRef<'idx> {
31    Direct(&'idx mut Index),
32    Shared(Rc<RefCell<Index>>),
33}
34
35/// A read-only index guard returned by [`IndexRef::get`].
36///
37/// This type abstracts over either a plain reference or a [`RefCell`] borrow.
38pub enum Guard<'a> {
39    Raw(&'a Index),
40    RefCell(Ref<'a, Index>),
41}
42
43impl<'a> ops::Deref for Guard<'a> {
44    type Target = Index;
45    fn deref(&self) -> &Self::Target {
46        match self {
47            Guard::Raw(r) => r,
48            Guard::RefCell(r) => r.deref(),
49        }
50    }
51}
52
53/// A mutable index guard returned by [`IndexRef::get_mut`].
54///
55/// This type abstracts over either a plain mutable reference or a mutable
56/// [`RefCell`] borrow.
57pub enum MutGuard<'a> {
58    Raw(&'a mut Index),
59    RefCell(RefMut<'a, Index>),
60}
61
62impl<'a> ops::Deref for MutGuard<'a> {
63    type Target = Index;
64    fn deref(&self) -> &Self::Target {
65        match self {
66            MutGuard::Raw(r) => r,
67            MutGuard::RefCell(r) => r.deref(),
68        }
69    }
70}
71
72impl<'a> ops::DerefMut for MutGuard<'a> {
73    fn deref_mut(&mut self) -> &mut Self::Target {
74        match self {
75            MutGuard::Raw(r) => r,
76            MutGuard::RefCell(r) => r.deref_mut(),
77        }
78    }
79}
80
81impl<'idx> IndexRef<'idx> {
82    /// Get a read-only view of the underlying index.
83    ///
84    /// For `Shared`, this performs a [`RefCell::borrow`] and will panic if a
85    /// mutable borrow is already active.
86    pub fn get(&self) -> Guard<'_> {
87        match self {
88            IndexRef::Direct(index) => Guard::Raw(&**index),
89            IndexRef::Shared(ref_cell) => {
90                let r = ref_cell.borrow();
91                Guard::RefCell(r)
92            }
93        }
94    }
95
96    /// Get a mutable view of the underlying index.
97    ///
98    /// For `Shared`, this performs a [`RefCell::borrow_mut`] and will panic if
99    /// any other borrow is active.
100    pub fn get_mut(&mut self) -> MutGuard<'_> {
101        match self {
102            IndexRef::Direct(index) => MutGuard::Raw(*index),
103            IndexRef::Shared(ref_cell) => {
104                let r = ref_cell.borrow_mut();
105                MutGuard::RefCell(r)
106            }
107        }
108    }
109}