1use crate::event::*;
4use crate::prelude_lib::*;
5use std::hint::unreachable_unchecked;
6use crate::linkage::LiftColumn;
7
8#[derive(Debug)]
9#[derive(serde::Serialize, serde::Deserialize)]
10#[serde(transparent)]
11pub struct Column<M: TableMarker, T> {
12 #[serde(skip)]
13 pub table_marker: M,
14 #[doc(hidden)]
16 pub data: Vec<T>,
17}
18impl<M: TableMarker, T> Default for Column<M, T> {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23impl<M: TableMarker, T> Column<M, T> {
24 pub fn new() -> Self {
25 Column {
26 table_marker: Default::default(),
27 data: vec![],
28 }
29 }
30 #[inline(always)] pub fn data(&self) -> &Vec<T> { &self.data }
31 #[inline(always)] pub unsafe fn data_mut(&mut self) -> &mut Vec<T> { &mut self.data }
32 #[inline(always)] pub fn set_data(&mut self, d: Vec<T>) { self.data = d }
33}
34
35pub type FastEdit<'a, C> = FastEditColumn<
36 'a,
37 <C as LiftColumn>::M,
38 <C as LiftColumn>::T,
39>;
40
41pub struct ReadColumn<'a, M: TableMarker, T> {
42 pub col: &'a Column<M, T>,
43}
44pub struct FastEditColumn<'a, M: TableMarker, T> {
45 col: &'a mut Column<M, T>,
46}
47pub struct EditColumn<'a, M: TableMarker, T>
52where
53 T: Clone,
54{
55 #[doc(hidden)]
56 pub col: &'a mut Column<M, T>,
57 must_log: bool,
58 log: &'a mut Vec<(Id<M>, T)>,
59}
60pub struct WriteColumn<'a, M: TableMarker, T> {
61 pub col: MutButRef<'a, Column<M, T>>,
62}
63
64#[cold]
65fn disordered_column_access() -> ! {
66 panic!("disordered column access")
67}
68impl<'a, 'b, I, M: TableMarker, T> Index<I> for ReadColumn<'a, M, T>
69where
70 I: 'b + Check<M = M>,
71{
72 type Output = T;
73 fn index(&self, i: I) -> &T {
74 unsafe {
75 let i = i.check_from_len(PhantomData, self.col.data.len());
76 self.col.data.get_unchecked(i.to_usize())
77 }
78 }
79}
80impl<'a, 'b, I, M: TableMarker, T> Index<I> for FastEditColumn<'a, M, T>
81where
82 I: 'b + Check<M = M>,
83{
84 type Output = T;
85 fn index(&self, i: I) -> &T {
86 unsafe {
87 let i = i.check_from_len(PhantomData, self.col.data.len());
88 self.col.data.get_unchecked(i.to_usize())
89 }
90 }
91}
92impl<'a, 'b, I, M: TableMarker, T> IndexMut<I> for FastEditColumn<'a, M, T>
93where
94 I: 'b + Check<M = M>,
95{
96 fn index_mut(&mut self, i: I) -> &mut T {
97 unsafe {
98 let i = i.check_from_len(PhantomData, self.col.data.len());
99 self.col.data.get_unchecked_mut(i.to_usize())
100 }
101 }
102}
103impl<'a, 'b, I, M: TableMarker, T> Index<I> for EditColumn<'a, M, T>
104where
105 T: Clone,
106 I: 'b + Check<M = M>,
107{
108 type Output = T;
109 fn index(&self, i: I) -> &T {
110 unsafe {
111 let i = i.check_from_len(PhantomData, self.col.data.len());
112 if let Some((prev, dude)) = self.log.last() {
113 match i.uncheck().cmp(prev) {
114 Ordering::Less => disordered_column_access(),
115 Ordering::Equal => dude,
116 Ordering::Greater => self.col.data.get_unchecked(i.to_usize()),
117 }
118 } else {
119 self.col.data.get_unchecked(i.to_usize())
120 }
121 }
122 }
123}
124impl<'a, 'b, I, M: TableMarker, T> IndexMut<I> for EditColumn<'a, M, T>
125where
126 T: Clone,
127 I: 'b + Check<M = M>,
128{
129 fn index_mut(&mut self, i: I) -> &mut T {
130 unsafe {
131 let i = i.check_from_len(PhantomData, self.col.data.len());
132 let i = i.uncheck();
133 if !self.must_log {
134 return self.col.data.get_unchecked_mut(i.to_usize());
135 }
136 let prev = self.log.last().map(|(i, _)| i);
137 let prev = prev.map(|prev| i.cmp(prev));
138 let prev = prev.unwrap_or(Ordering::Greater);
139 match prev {
140 Ordering::Less => disordered_column_access(),
141 Ordering::Equal => (),
142 Ordering::Greater => {
143 let val = self.col.data.get_unchecked(i.to_usize()).clone();
144 self.log.push((i, val))
145 }
146 }
147 if let Some((_i, v)) = self.log.last_mut() {
148 v
149 } else {
150 unreachable_unchecked()
151 }
152 }
153 }
154}
155impl<'a, 'b, M: TableMarker, T, I> Index<I> for WriteColumn<'a, M, T>
156where
157 I: 'b + Check<M = M>,
158{
159 type Output = T;
160 fn index(&self, i: I) -> &T {
161 unsafe {
162 let i = i.check_from_len(PhantomData, self.col.data.len());
163 self.col.data.get_unchecked(i.to_usize())
164 }
165 }
166}
167impl<'a, M: TableMarker, T> WriteColumn<'a, M, T> {
170 pub fn borrow(&self) -> ReadColumn<M, T> {
171 ReadColumn { col: &*self.col }
172 }
173}
174impl<'a, M: TableMarker, T> EditColumn<'a, M, T>
175where
176 T: Clone,
177{
178 pub fn borrow(&self) -> ReadColumn<M, T> {
179 assert!(self.log.is_empty());
180 ReadColumn { col: &*self.col }
181 }
182}
183
184unsafe impl<'a, M, T: Send + Sync> ExtractOwned for ReadColumn<'a, M, T>
185where
186 M: TableMarker,
187 T: 'static,
188{
189 type Ty = Column<M, T>;
190 const ACC: Access = Access::Read;
191 unsafe fn extract(_universe: &Universe, rez: &mut Rez) -> Self {
192 let obj: &'static dyn Any = rez.take_ref();
193 ReadColumn {
194 col: obj.downcast_ref().unwrap(),
195 }
196 }
197}
198unsafe impl<'a, M, T: Send + Sync> ExtractOwned for FastEditColumn<'a, M, T>
199where
200 M: TableMarker,
201 T: 'static,
202{
203 type Ty = Column<M, T>;
204 const ACC: Access = Access::Write;
205 unsafe fn extract(universe: &Universe, rez: &mut Rez) -> Self {
206 let obj: &'static mut dyn Any = rez.take_mut();
207 assert!(!universe.is_tracked::<Edited<M, T>>(), "FastEditColumn used on a tracked column");
208 FastEditColumn {
209 col: obj.downcast_mut().unwrap(),
210 }
211 }
212}
213#[doc(hidden)]
214pub struct EditColumnOwned<'a, M, T>
215where
216 M: TableMarker,
217{
218 col: &'a mut Column<M, T>,
219 must_log: bool,
220 log: Vec<(Id<M>, T)>,
221}
222unsafe impl<'a, M, T> Extract for EditColumn<'a, M, T>
223where
224 M: TableMarker,
225 T: 'static + Send + Sync,
226 T: Clone,
227{
228 fn each_resource(f: &mut dyn FnMut(TypeId, Access)) {
229 f(TypeId::of::<Column<M, T>>(), Access::Write)
230 }
231 type Owned = EditColumnOwned<'a, M, T>;
232 unsafe fn extract(universe: &Universe, rez: &mut Rez) -> Self::Owned {
233 let col: &mut Column<M, T> = rez.take_mut_downcast();
234 let must_log = universe.is_tracked::<Edited<M, T>>();
235 let log = vec![];
236 EditColumnOwned { col, must_log, log }
237 }
238 unsafe fn convert(_universe: &Universe, owned: *mut Self::Owned) -> Self {
239 let EditColumnOwned { col, must_log, log } = &mut *owned;
240 EditColumn { col, must_log: *must_log, log }
241 }
242 type Cleanup = EditColumnCleanup<M, T>;
243}
244#[doc(hidden)]
245pub struct EditColumnCleanup<M: TableMarker, T> {
246 must_log: bool,
247 log: Vec<(Id<M>, T)>,
248}
249unsafe impl<'a, M, T> Cleaner<EditColumn<'a, M, T>> for EditColumnCleanup<M, T>
250where
251 M: TableMarker,
252 T: 'static + Send + Sync,
253 T: Clone,
254 {
256 fn pre_cleanup(eco: EditColumnOwned<'a, M, T>, _universe: &Universe) -> Self {
257 Self {
258 must_log: eco.must_log,
259 log: eco.log,
260 }
261 }
262 fn post_cleanup(self, universe: &Universe) {
263 if !self.must_log || self.log.is_empty() {
264 return;
265 }
266 let log = universe.with(move |col: &Column<M, T>| {
267 let col = col as *const _;
268 let mut ev = Edited { col, new: self.log };
269 universe.submit_event(&mut ev);
270 ev.new
271 });
272 universe.with_mut(move |col: &mut Column<M, T>| {
273 for (id, new) in log.into_iter() {
274 col.data[id.0.to_usize()] = new;
275 }
276 });
277 }
278}
279unsafe impl<'a, M, T> ExtractOwned for WriteColumn<'a, M, T>
280where
281 M: TableMarker,
282 T: 'static + Send + Sync,
283{
284 type Ty = Column<M, T>;
285 const ACC: Access = Access::Write;
286 unsafe fn extract(_universe: &Universe, rez: &mut Rez) -> Self {
287 WriteColumn {
288 col: MutButRef::new(rez.take_mut_downcast()),
289 }
290 }
291}
292
293pub unsafe trait ColumnInfo<M: TableMarker> {
294 fn len(&self) -> usize;
295 fn is_empty(&self) -> bool {
296 self.len() == 0
297 }
298}
299unsafe impl<M: TableMarker, T> ColumnInfo<M> for Column<M, T> {
300 fn len(&self) -> usize {
301 self.data.len()
302 }
303}
304unsafe impl<'a, M: TableMarker, T> ColumnInfo<M> for ReadColumn<'a, M, T> {
305 fn len(&self) -> usize {
306 self.col.data.len()
307 }
308}
309unsafe impl<'a, M: TableMarker, T: Clone> ColumnInfo<M> for EditColumn<'a, M, T> {
310 fn len(&self) -> usize {
311 self.col.data.len()
312 }
313}
314unsafe impl<'a, M: TableMarker, T> ColumnInfo<M> for WriteColumn<'a, M, T> {
315 fn len(&self) -> usize {
316 self.col.data.len()
317 }
318}