hecs_schedule/borrow/
cell_borrow.rs

1use std::{
2    any::type_name,
3    marker::PhantomData,
4    ops::{Deref, DerefMut},
5    ptr::NonNull,
6};
7
8/// Type alias for list of borrows
9pub type Borrows = SmallVec<[Access; 8]>;
10
11use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
12use smallvec::{smallvec, SmallVec};
13
14use crate::{Access, Context, Error, Result};
15
16use super::ComponentBorrow;
17
18/// Wrapper type for an immutably borrowed value from schedule context
19#[repr(transparent)]
20#[derive(Debug)]
21pub struct Read<'a, T>(pub(crate) AtomicRef<'a, T>);
22
23impl<'a, T> Clone for Read<'a, T> {
24    fn clone(&self) -> Self {
25        Self(AtomicRef::<'a, T>::clone(&self.0))
26    }
27}
28
29impl<'a, T> Deref for Read<'a, T> {
30    type Target = T;
31
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl<'a, T> Read<'a, T> {
38    /// Creates a new Read borrow from an atomic ref
39    pub fn new(borrow: AtomicRef<'a, T>) -> Self {
40        Self(borrow)
41    }
42}
43
44impl<'a, T: 'static> Read<'a, T> {
45    pub(crate) fn try_from_untyped(cell: &'a AtomicRefCell<NonNull<u8>>) -> Result<Self> {
46        cell.try_borrow()
47            .map_err(|_| Error::Borrow(type_name::<T>()))
48            .map(|cell| Self(AtomicRef::map(cell, |val| unsafe { val.cast().as_ref() })))
49    }
50}
51
52#[repr(transparent)]
53/// Wrapper type for an exclusively borrowed value
54pub struct Write<'a, T>(pub(crate) AtomicRefMut<'a, T>);
55
56impl<'a, T> Write<'a, T> {
57    /// Creates a new Write borrow from an atomic ref
58    pub fn new(borrow: AtomicRefMut<'a, T>) -> Self {
59        Self(borrow)
60    }
61}
62
63impl<'a, T: 'static> Write<'a, T> {
64    pub(crate) fn try_from_untyped(cell: &'a AtomicRefCell<NonNull<u8>>) -> Result<Self> {
65        cell.try_borrow_mut()
66            .map_err(|_| Error::BorrowMut(type_name::<T>()))
67            .map(|cell| {
68                Self(AtomicRefMut::map(cell, |val| unsafe {
69                    val.cast().as_mut()
70                }))
71            })
72    }
73}
74
75impl<'a, T> Deref for Write<'a, T> {
76    type Target = T;
77
78    fn deref(&self) -> &Self::Target {
79        &self.0
80    }
81}
82
83impl<'a, T> DerefMut for Write<'a, T> {
84    fn deref_mut(&mut self) -> &mut Self::Target {
85        &mut self.0
86    }
87}
88
89struct BorrowMarker<T> {
90    marker: PhantomData<T>,
91}
92
93/// Helper trait for borrowing either immutably or mutably from context
94pub trait ContextBorrow<'a> {
95    /// The resulting type after borrowing from context
96    type Target;
97
98    /// Borrow type from context
99    fn borrow(context: &'a Context) -> Result<Self::Target>;
100}
101
102impl<'a, T: 'static> ContextBorrow<'a> for &'a T {
103    type Target = Read<'a, T>;
104
105    fn borrow(context: &'a Context) -> Result<Self::Target> {
106        Read::try_from_untyped(context.cell::<&T>()?)
107    }
108}
109
110impl<'a, T: 'static> ContextBorrow<'a> for &'a mut T {
111    type Target = Write<'a, T>;
112
113    fn borrow(context: &'a Context) -> Result<Self::Target> {
114        Write::try_from_untyped(context.cell::<&mut T>()?)
115    }
116}
117
118impl<'a, T: 'static> ContextBorrow<'a> for Read<'a, T> {
119    type Target = Self;
120
121    fn borrow(context: &'a Context) -> Result<Self::Target> {
122        Read::try_from_untyped(context.cell::<&T>()?)
123    }
124}
125
126impl<'a, T: 'static> ContextBorrow<'a> for Write<'a, T> {
127    type Target = Self;
128
129    fn borrow(context: &'a Context) -> Result<Self::Target> {
130        Write::try_from_untyped(context.cell::<&mut T>()?)
131    }
132}
133
134impl<'a, T: 'static> ComponentBorrow for Read<'a, T> {
135    fn borrows() -> Borrows {
136        smallvec![Access::of::<&BorrowMarker<T>>()]
137    }
138
139    fn has<U: crate::IntoAccess>() -> bool {
140        Access::of::<&T>() == U::access()
141    }
142
143    fn has_dynamic(id: std::any::TypeId, exclusive: bool) -> bool {
144        let l = Access::of::<&T>();
145
146        l.id == id && !exclusive
147    }
148}
149
150impl<'a, T: 'static> ComponentBorrow for Write<'a, T> {
151    fn borrows() -> Borrows {
152        smallvec![Access::of::<&mut BorrowMarker<T>>()]
153    }
154
155    fn has<U: crate::IntoAccess>() -> bool {
156        Access::of::<&mut T>().id == U::access().id
157    }
158
159    fn has_dynamic(id: std::any::TypeId, _: bool) -> bool {
160        let l = Access::of::<&mut T>();
161
162        l.id == id
163    }
164}