despero_hecs_schedule/borrow/
maybe_borrow.rs1use std::{
2 any::type_name,
3 marker::PhantomData,
4 ops::{Deref, DerefMut},
5 ptr::NonNull,
6};
7
8use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
9use smallvec::smallvec;
10
11use crate::{borrow::Borrows, Access, Context, Error, IntoAccess, Result};
12
13use super::{ComponentBorrow, ContextBorrow};
14
15#[repr(transparent)]
18#[derive(Debug)]
19pub struct MaybeRead<'a, T>(pub(crate) Option<AtomicRef<'a, T>>);
20
21impl<'a, T> Clone for MaybeRead<'a, T> {
25 fn clone(&self) -> Self {
26 match &self.0 {
27 Some(val) => Self(Some(AtomicRef::clone(val))),
28 None => Self(None),
29 }
30 }
31}
32
33impl<'a, T> Deref for MaybeRead<'a, T> {
34 type Target = Option<AtomicRef<'a, T>>;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39}
40
41impl<'a, T> MaybeRead<'a, T> {
42 pub fn new(borrow: Option<AtomicRef<'a, T>>) -> Self {
44 Self(borrow)
45 }
46
47 pub fn option(&self) -> Option<&AtomicRef<'a, T>> {
49 self.0.as_ref()
50 }
51}
52
53impl<'a, T: 'static> MaybeRead<'a, T> {
54 pub(crate) fn try_from_untyped(cell: Result<&'a AtomicRefCell<NonNull<u8>>>) -> Result<Self> {
55 match cell {
56 Ok(cell) => cell
57 .try_borrow()
58 .map_err(|_| Error::Borrow(type_name::<T>()))
59 .map(|cell| {
60 Self(Some(AtomicRef::map(cell, |val| unsafe {
61 val.cast().as_ref()
62 })))
63 }),
64 Err(Error::MissingData(_)) => Ok(Self(None)),
65 Err(e) => Err(e),
66 }
67 }
68}
69
70#[repr(transparent)]
72#[derive(Debug)]
73pub struct MaybeWrite<'a, T>(pub(crate) Option<AtomicRefMut<'a, T>>);
74
75impl<'a, T> Deref for MaybeWrite<'a, T> {
76 type Target = Option<AtomicRefMut<'a, T>>;
77
78 fn deref(&self) -> &Self::Target {
79 &self.0
80 }
81}
82
83impl<'a, T> DerefMut for MaybeWrite<'a, T> {
84 fn deref_mut(&mut self) -> &mut Self::Target {
85 &mut self.0
86 }
87}
88
89impl<'a, T> MaybeWrite<'a, T> {
90 pub fn new(borrow: Option<AtomicRefMut<'a, T>>) -> Self {
92 Self(borrow)
93 }
94
95 pub fn option(&self) -> Option<&AtomicRefMut<'a, T>> {
97 self.0.as_ref()
98 }
99
100 pub fn option_mut(&mut self) -> Option<&mut AtomicRefMut<'a, T>> {
102 self.0.as_mut()
103 }
104}
105
106impl<'a, T: 'static> MaybeWrite<'a, T> {
107 pub(crate) fn try_from_untyped(cell: Result<&'a AtomicRefCell<NonNull<u8>>>) -> Result<Self> {
108 match cell {
109 Ok(cell) => cell
110 .try_borrow_mut()
111 .map_err(|_| Error::BorrowMut(type_name::<T>()))
112 .map(|cell| {
113 Self(Some(AtomicRefMut::map(cell, |val| unsafe {
114 val.cast().as_mut()
115 })))
116 }),
117 Err(Error::MissingData(_)) => Ok(Self(None)),
118 Err(e) => Err(e),
119 }
120 }
121}
122
123struct BorrowMarker<T> {
124 marker: PhantomData<T>,
125}
126
127impl<T: IntoAccess> IntoAccess for BorrowMarker<T> {
128 fn access() -> Access {
129 Access::of::<T>()
130 }
131}
132
133impl<'a, T: 'static> ContextBorrow<'a> for MaybeRead<'a, T> {
134 type Target = Self;
135
136 fn borrow(context: &'a Context) -> Result<Self::Target> {
137 MaybeRead::try_from_untyped(context.cell::<&T>())
138 }
139}
140
141impl<'a, T: 'static> ContextBorrow<'a> for MaybeWrite<'a, T> {
142 type Target = Self;
143
144 fn borrow(context: &'a Context) -> Result<Self::Target> {
145 MaybeWrite::try_from_untyped(context.cell::<&mut T>())
146 }
147}
148
149impl<'a, T: 'static> ComponentBorrow for MaybeRead<'a, T> {
150 fn borrows() -> Borrows {
151 smallvec![BorrowMarker::<&T>::access()]
152 }
153
154 fn has<U: crate::IntoAccess>() -> bool {
155 Access::of::<&T>() == U::access()
156 }
157
158 fn has_dynamic(id: std::any::TypeId, exclusive: bool) -> bool {
159 let l = Access::of::<&T>();
160
161 l.id == id && !exclusive
162 }
163}
164
165impl<'a, T: 'static> ComponentBorrow for MaybeWrite<'a, T> {
166 fn borrows() -> Borrows {
167 smallvec![BorrowMarker::<&mut T>::access()]
168 }
169
170 fn has<U: crate::IntoAccess>() -> bool {
171 Access::of::<&T>().id == U::access().id
172 }
173
174 fn has_dynamic(id: std::any::TypeId, _: bool) -> bool {
175 let l = Access::of::<&T>();
176
177 l.id == id
178 }
179}