hecs_schedule/borrow/
cell_borrow.rs1use std::{
2 any::type_name,
3 marker::PhantomData,
4 ops::{Deref, DerefMut},
5 ptr::NonNull,
6};
7
8pub 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#[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 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)]
53pub struct Write<'a, T>(pub(crate) AtomicRefMut<'a, T>);
55
56impl<'a, T> Write<'a, T> {
57 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
93pub trait ContextBorrow<'a> {
95 type Target;
97
98 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}