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}