duat_core/data.rs
1//! Duat's way of sharing and updating state
2//!
3//! This module consists primarily of the [`RwData`] struct, which
4//! holds state that can be [read] or [written to]. When it is
5//! modified, other holders of a clone of [`RwData`] will know that
6//! the data within has been modified.
7//!
8//! This is used in many places, for example, [`Widget`]s can read
9//! from [`File`]s, and Duat can know when a [`File`] has been
10//! altered, so these [`Widget`]s may be [updated] automatically.
11//!
12//! Another struct from this module is [`DataMap`]. This is
13//! essentially a mapping for a [`RwData`]. It is created via
14//! [`RwData::map`], and both it and [`RwData`] can be very useful in,
15//! for example, a [`StatusLine`], since it will be updated
16//! automatically whenever the [`RwData`] is altered.
17//!
18//! One thing to note is that these structs are only meant to exist
19//! and be used in the main thread of execution in Duat. In fact, it
20//! should be impossible to acquire them outside of this main thread
21//! without use of unsafe code. If it is still possible, report that
22//! as a bug.
23//!
24//! The reason why these structs should only be valid in the main
25//! thread is because, internally, they use non [`Send`]/[`Sync`]
26//! structs, specifically [`Rc`] and [`RefCell`]. These are often
27//! considered "crutches" by a lot of the Rust community, but in an
28//! environment where most of the code is supposed to be able to
29//! access most of the state, it is impossible to go without using
30//! them.
31//!
32//! As well as not having the problem of deadlocks that [`Mutex`]es
33//! would have, [`Rc<RefCell>`] is way faster to clone and lock than
34//! its [`Sync`] equivalents [`Arc<Mutex>`] or [`Arc<RwLock>`].
35//!
36//! [read]: RwData::read
37//! [written to]: RwData::write
38//! [`Widget`]: crate::ui::Widget
39//! [`File`]: crate::file::File
40//! [updated]: crate::ui::Widget::update
41//! [`Text`]: crate::text::Text
42//! [`StatusLine`]: https://docs.rs/duat-utils/latest/duat_utils/widgets/struct.StatusLine.html
43//! [`context`]: crate::context
44//! [`Mutex`]: std::sync::Mutex
45//! [`Arc<Mutex>`]: std::sync::Arc
46//! [`Arc<RwLock>`]: std::sync::Arc
47use std::{
48 self,
49 any::TypeId,
50 cell::{Cell, RefCell},
51 marker::PhantomData,
52 rc::Rc,
53 sync::{
54 Arc,
55 atomic::{AtomicBool, Ordering},
56 },
57 time::Duration,
58};
59
60use crate::{
61 cfg::PrintCfg,
62 text::Text,
63 ui::{Ui, Widget},
64};
65
66/// A container for shared read/write state
67///
68/// This is the struct used internally (and externally) to allow for
69/// massively shareable state in duat's API. Its main purpose is to
70/// hold all of the [`Widget`]s in Duat, making them available for
71/// usage from any function with access to a [`Pass`].
72///
73/// # [`Pass`]es
74///
75/// The [`Pass`] is a sort of "key" for accessing the value within an
76/// [`RwData`], it's purpose is to maintain Rust's number one rule,
77/// i.e. one exclusive reference or multiple shared references, and
78/// that is done by borrowing the [`Pass`] mutably or non mutably.
79/// That comes with some limitations, of course, mainly that you can't
80/// really mutate two [`RwData`]s at the same time, even if it is
81/// known that they don't point to the same data.
82///
83/// There are some common exceptions to this, where Duat provides some
84/// safe way to do that when it is known that the two types are not
85/// the same.
86///
87/// # Not [`Send`]/[`Sync`]
88///
89/// Internally, the [`RwData`] makes use of an [`Rc<RefCell>`]. The
90/// usage of an [`Rc<RefCell>`] over an [`Arc<Mutex>`] is, i've
91/// assumed, a necessary evil in order to preserve the aforementioned
92/// rule. But the lack of [`Send`]/[`Sync`] does confer the [`RwData`]
93/// some advantages:
94///
95/// * Deadlocks are impossible, being replaced by much easier to debug
96/// panics.
97/// * The order in which data is accessed doesn't matter, unlike with
98/// [`Mutex`]es.
99/// * Performance of unlocking and cloning should generally be better,
100/// since no atomic operations are done (I actually managed to
101/// observe this, where in my rudimentary benchmarks against neovim,
102/// the [`Arc<Mutex>`] version was very frequently losing to a
103/// comparable neovim build.
104///
105/// However, I admit that there are also some drawbacks, the most
106/// notable being the difficulty of reading or writing to [`Text`]
107/// from outside of the main thread. But for the most common usecase
108/// where that will be needed ([`Reader`]s), a [`Send`]/[`Sync`]
109/// solution will be provided soon.
110///
111/// [`Arc<Mutex>`]: std::sync::Arc
112/// [`Mutex`]: std::sync::Mutex
113/// [`Reader`]: crate::file::Reader
114#[derive(Debug)]
115pub struct RwData<T: ?Sized> {
116 value: Rc<RefCell<T>>,
117 cur_state: Rc<Cell<usize>>,
118 read_state: Rc<Cell<usize>>,
119 ty: TypeId,
120}
121
122impl<T: 'static> RwData<T> {
123 /// Returns a new [`RwData<T>`]
124 ///
125 /// Note that this is only for sized types. For unsized types, the
126 /// process is a little more convoluted, and you need to use
127 /// [`RwData::new_unsized`].
128 pub fn new(value: T) -> Self {
129 Self {
130 value: Rc::new(RefCell::new(value)),
131 ty: TypeId::of::<T>(),
132 cur_state: Rc::new(Cell::new(1)),
133 read_state: Rc::new(Cell::new(0)),
134 }
135 }
136
137 /// Replaces the value within using a [`Pass`]
138 ///
139 /// The consistent use of a [`Pass`] for the purposes of
140 /// reading/writing to the values of [`RwData`]s ensures that no
141 /// panic or invalid borrow happens at runtime, even while working
142 /// with untrusted code. More importantly, Duat uses these
143 /// guarantees in order to give the end user a ridiculous amount
144 /// of freedom in where they can do things, whilst keeping Rust's
145 /// number one rule and ensuring thread safety, even with a
146 /// relatively large amount of shareable state.
147 ///
148 /// # Panics
149 ///
150 /// Panics if there is any type of borrow of this struct
151 /// somewhere, which could happen if you use [`read_unsafe`]
152 /// or [`write_unsafe`], for example.
153 ///
154 /// [`read_unsafe`]: Self::read_unsafe
155 /// [`write_unsafe`]: Self::write_unsafe
156 pub fn replace(&self, pa: &mut Pass, new: T) -> T {
157 self.write(pa, |value| std::mem::replace(value, new))
158 }
159
160 /// Gets the value within using a [`Pass`]
161 ///
162 /// The consistent use of a [`Pass`] for the purposes of
163 /// reading/writing to the values of [`RwData`]s ensures that no
164 /// panic or invalid borrow happens at runtime, even while working
165 /// with untrusted code. More importantly, Duat uses these
166 /// guarantees in order to give the end user a ridiculous amount
167 /// of freedom in where they can do things, whilst keeping Rust's
168 /// number one rule and ensuring thread safety, even with a
169 /// relatively large amount of shareable state.
170 ///
171 /// # Panics
172 ///
173 /// Panics if there is a mutable borrow of this struct somewhere,
174 /// which could happen if you use [`write_unsafe`] or
175 /// [`write_unsafe_as`]
176 ///
177 /// [`write_unsafe`]: Self::write_unsafe
178 /// [`write_unsafe_as`]: Self::write_unsafe_as
179 pub fn get(&self, pa: &Pass) -> T
180 where
181 T: Clone,
182 {
183 self.read(pa, |value| value.clone())
184 }
185}
186
187impl<T: ?Sized> RwData<T> {
188 /// Returns an unsized [`RwData`], such as [`RwData<dyn Trait>`]
189 ///
190 /// # Safety
191 ///
192 /// There is a type argument `SizedT` which _must_ be the exact
193 /// type you are passing to this constructor, i.e., if you are
194 /// creating an [`RwData<dyn Display>`] from a [`String`], you'd
195 /// do this:
196 ///
197 /// ```rust
198 /// use std::{cell::RefCell, fmt::Display, rc::Rc};
199 ///
200 /// use duat_core::{data::RwData, prelude::*};
201 /// let rw_data: RwData<dyn Display> =
202 /// unsafe { RwData::new_unsized::<String>(Rc::new(RefCell::new("testing".to_string()))) };
203 /// ```
204 ///
205 /// This ensures that methods such as [`read_as`] and [`write_as`]
206 /// will correctly identify such [`RwData<dyn Display>`] as a
207 /// [`String`].
208 ///
209 /// [`read_as`]: Self::read_as
210 /// [`write_as`]: Self::write_as
211 pub unsafe fn new_unsized<SizedT: 'static>(value: Rc<RefCell<T>>) -> Self {
212 Self {
213 value,
214 ty: TypeId::of::<SizedT>(),
215 cur_state: Rc::new(Cell::new(1)),
216 read_state: Rc::new(Cell::new(0)),
217 }
218 }
219
220 ////////// Reading functions
221
222 /// Reads the value within using a [`Pass`]
223 ///
224 /// The consistent use of a [`Pass`] for the purposes of
225 /// reading/writing to the values of [`RwData`]s ensures that no
226 /// panic or invalid borrow happens at runtime, even while working
227 /// with untrusted code. More importantly, Duat uses these
228 /// guarantees in order to give the end user a ridiculous amount
229 /// of freedom in where they can do things, whilst keeping Rust's
230 /// number one rule and ensuring thread safety, even with a
231 /// relatively large amount of shareable state.
232 ///
233 /// # Panics
234 ///
235 /// Panics if there is a mutable borrow of this struct somewhere,
236 /// which could happen if you use [`write_unsafe`] or
237 /// [`write_unsafe_as`]
238 ///
239 /// [`write_unsafe`]: Self::write_unsafe
240 /// [`write_unsafe_as`]: Self::write_unsafe_as
241 pub fn read<Ret>(&self, _: &Pass, f: impl FnOnce(&T) -> Ret) -> Ret {
242 update_read_state(&self.read_state, &self.cur_state);
243 f(&*self.value.borrow())
244 }
245
246 /// Reads the value within as `U` using a [`Pass`]
247 ///
248 /// The consistent use of a [`Pass`] for the purposes of
249 /// reading/writing to the values of [`RwData`]s ensures that no
250 /// panic or invalid borrow happens at runtime, even while working
251 /// with untrusted code. More importantly, Duat uses these
252 /// guarantees in order to give the end user a ridiculous amount
253 /// of freedom in where they can do things, whilst keeping Rust's
254 /// number one rule and ensuring thread safety, even with a
255 /// relatively large amount of shareable state.
256 ///
257 /// # Panics
258 ///
259 /// Panics if there is a mutable borrow of this struct somewhere,
260 /// which could happen if you use [`write_unsafe`] or
261 /// [`write_unsafe_as`]
262 ///
263 /// [`write_unsafe`]: Self::write_unsafe
264 /// [`write_unsafe_as`]: Self::write_unsafe_as
265 pub fn read_as<Ret, U: 'static>(&self, _: &Pass, f: impl FnOnce(&U) -> Ret) -> Option<Ret> {
266 fn prepare<T: ?Sized, U: 'static>(data: &RwData<T>) -> Option<std::cell::Ref<U>> {
267 if TypeId::of::<U>() != data.ty {
268 return None;
269 }
270
271 data.read_state.set(data.cur_state.get());
272 let ptr = Rc::as_ptr(&data.value);
273 Some(unsafe { (ptr as *const RefCell<U>).as_ref().unwrap().borrow() })
274 }
275
276 prepare(self).map(|mapped| f(&*mapped))
277 }
278
279 /// Reads the value within, without a [`Pass`]
280 ///
281 /// While a lack of [`Pass`]es grants you more freedom, it may
282 /// also cause panics if not handled carefully, since you could be
283 /// breaking the number one rule of Rust.
284 ///
285 /// # Panics
286 ///
287 /// Panics if there is a mutable borrow of this struct somewhere
288 ///
289 /// # Safety
290 ///
291 /// In order to safely use this function without panicking, there
292 /// are some useful guidelines that you should follow:
293 ///
294 /// - The value being read does not have any [`RwData`] within;
295 /// - You know that this value is not being shared anywhere else;
296 ///
297 /// Essentially, in order to use this safely, you should treat it
298 /// like a glorified [`RefCell`]
299 pub unsafe fn read_unsafe<Ret>(&self, f: impl FnOnce(&T) -> Ret) -> Ret {
300 update_read_state(&self.read_state, &self.cur_state);
301 f(&*self.value.borrow())
302 }
303
304 /// Reads the value within as `U`, without a [`Pass`]
305 ///
306 /// While a lack of [`Pass`]es grants you more freedom, it may
307 /// also cause panics if not handled carefully, since you could be
308 /// breaking the number one rule of Rust.
309 ///
310 /// # Panics
311 ///
312 /// Panics if there is a mutable borrow of this struct somewhere
313 ///
314 /// # Safety
315 ///
316 /// In order to safely use this function without panicking, there
317 /// are some useful guidelines that you should follow:
318 ///
319 /// - The value being read does not have any [`RwData`] within;
320 /// - You know that this value is not being shared anywhere else;
321 ///
322 /// Essentially, in order to use this safely, you should treat it
323 /// like a glorified [`RefCell`]
324 pub unsafe fn read_unsafe_as<Ret, U: 'static>(&self, f: impl FnOnce(&U) -> Ret) -> Option<Ret> {
325 if TypeId::of::<U>() != self.ty {
326 return None;
327 }
328
329 self.read_state.set(self.cur_state.get());
330 let ptr = Rc::as_ptr(&self.value);
331 let value = unsafe { (ptr as *const RefCell<U>).as_ref().unwrap() };
332 Some(f(&*value.borrow()))
333 }
334
335 /// Simulates a [`read`] without actually reading
336 ///
337 /// This is useful if you want to tell Duat that you don't want
338 /// [`has_changed`] to return `true`, but you don't have a
339 /// [`Pass`] available to [`read`] the value.
340 ///
341 /// [`read`]: Self::read
342 /// [`has_changed`]: Self::has_changed
343 pub fn declare_as_read(&self) {
344 self.read_state.set(self.cur_state.get());
345 }
346
347 /// Reads the data without updating its read state, might be
348 /// removed, idk
349 pub(crate) fn read_raw<Ret>(&self, f: impl FnOnce(&T) -> Ret) -> Ret {
350 f(&*self.value.borrow())
351 }
352
353 /// Acquires the value within, meant for improving compile times
354 /// internally.
355 pub(crate) fn acquire(&self, _: &Pass) -> std::cell::RefMut<'_, T> {
356 update_read_state(&self.read_state, &self.cur_state);
357 self.value.borrow_mut()
358 }
359
360 ////////// Writing functions
361
362 /// Writes to the value within using a [`Pass`]
363 ///
364 /// The consistent use of a [`Pass`] for the purposes of
365 /// reading/writing to the values of [`RwData`]s ensures that no
366 /// panic or invalid borrow happens at runtime, even while working
367 /// with untrusted code. More importantly, Duat uses these
368 /// guarantees in order to give the end user a ridiculous amount
369 /// of freedom in where they can do things, whilst keeping Rust's
370 /// number one rule and ensuring thread safety, even with a
371 /// relatively large amount of shareable state.
372 ///
373 /// # Panics
374 ///
375 /// Panics if there is any type of borrow of this struct
376 /// somewhere, which could happen if you use [`read_unsafe`]
377 /// or [`write_unsafe`], for example.
378 ///
379 /// [`read_unsafe`]: Self::read_unsafe
380 /// [`write_unsafe`]: Self::write_unsafe
381 #[track_caller]
382 pub fn write<Ret>(&self, _: &mut Pass, f: impl FnOnce(&mut T) -> Ret) -> Ret {
383 update_cur_state(&self.read_state, &self.cur_state);
384 f(&mut *self.value.borrow_mut())
385 }
386
387 /// Writes to the value within as `U` using a [`Pass`]
388 ///
389 /// The consistent use of a [`Pass`] for the purposes of
390 /// reading/writing to the values of [`RwData`]s ensures that no
391 /// panic or invalid borrow happens at runtime, even while working
392 /// with untrusted code. More importantly, Duat uses these
393 /// guarantees in order to give the end user a ridiculous amount
394 /// of freedom in where they can do things, whilst keeping Rust's
395 /// number one rule and ensuring thread safety, even with a
396 /// relatively large amount of shareable state.
397 ///
398 /// # Panics
399 ///
400 /// Panics if there is any type of borrow of this struct
401 /// somewhere, which could happen if you use [`read_unsafe`]
402 /// or [`write_unsafe`], for example.
403 ///
404 /// [`read_unsafe`]: Self::read_unsafe
405 /// [`write_unsafe`]: Self::write_unsafe
406 pub fn write_as<Ret, U: 'static>(
407 &self,
408 _: &mut Pass,
409 f: impl FnOnce(&mut U) -> Ret,
410 ) -> Option<Ret> {
411 fn prepare<T: ?Sized, U: 'static>(data: &RwData<T>) -> Option<std::cell::RefMut<U>> {
412 if TypeId::of::<U>() != data.ty {
413 return None;
414 }
415
416 data.cur_state.set(data.cur_state.get() + 1);
417 data.read_state.set(data.cur_state.get());
418 let ptr = Rc::as_ptr(&data.value);
419 Some(unsafe { (ptr as *const RefCell<U>).as_ref().unwrap().borrow_mut() })
420 }
421
422 prepare(self).map(|mut mapped| f(&mut *mapped))
423 }
424
425 /// Writes to the value within as `U`, without a [`Pass`]
426 ///
427 /// While a lack of [`Pass`]es grants you more freedom, it may
428 /// also cause panics if not handled carefully, since you could be
429 /// breaking the number one rule of Rust.
430 ///
431 /// # Panics
432 ///
433 /// Will panic if there are any types of borrows of the value
434 /// within somewhere else.
435 ///
436 /// # Safety
437 ///
438 /// In order to safely use this function without panicking, there
439 /// are some useful guidelines that you should follow:
440 ///
441 /// - The value being read does not have any [`RwData`] within;
442 /// - You know that this value is not being shared anywhere else;
443 ///
444 /// Essentially, in order to use this safely, you should treat it
445 /// like a glorified [`RefCell`]
446 pub unsafe fn write_unsafe<Ret>(&self, f: impl FnOnce(&mut T) -> Ret) -> Ret {
447 update_cur_state(&self.read_state, &self.cur_state);
448 f(&mut *self.value.borrow_mut())
449 }
450
451 /// Writes to the value within, without a [`Pass`]
452 ///
453 /// While a lack of [`Pass`]es grants you more freedom, it may
454 /// also cause panics if not handled carefully, since you could be
455 /// breaking the number one rule of Rust.
456 ///
457 /// # Panics
458 ///
459 /// Will panic if there are any types of borrows of the value
460 /// within somewhere else.
461 ///
462 /// # Safety
463 ///
464 /// In order to safely use this function without panicking, there
465 /// are some useful guidelines that you should follow:
466 ///
467 /// - The value being read does not have any [`RwData`] within;
468 /// - You know that this value is not being shared anywhere else;
469 ///
470 /// Essentially, in order to use this safely, you should treat it
471 /// like a glorified [`RefCell`]
472 pub unsafe fn write_unsafe_as<Ret, U: 'static>(
473 &self,
474 f: impl FnOnce(&mut U) -> Ret,
475 ) -> Option<Ret> {
476 fn prepare<T: ?Sized, U: 'static>(data: &RwData<T>) -> Option<std::cell::RefMut<U>> {
477 if TypeId::of::<U>() != data.ty {
478 return None;
479 }
480
481 data.cur_state.set(data.cur_state.get() + 1);
482 data.read_state.set(data.cur_state.get());
483 let ptr = Rc::as_ptr(&data.value);
484 Some(unsafe { (ptr as *const RefCell<U>).as_ref().unwrap().borrow_mut() })
485 }
486
487 prepare(self).map(|mut mapped| f(&mut *mapped))
488 }
489
490 /// Simulates a [`write`] without actually reading
491 ///
492 /// This is useful if you want to tell Duat that you want
493 /// [`has_changed`] to return `true`, but you don't have a
494 /// [`Pass`] available to [`write`] the value with.
495 ///
496 /// [`write`]: Self::write
497 /// [`has_changed`]: Self::has_changed
498 pub fn declare_written(&self) {
499 update_cur_state(&self.read_state, &self.cur_state);
500 }
501
502 /// Acquires a mutable reference to the value within, for
503 /// compilation time improvements inside Duat
504 pub(crate) fn acquire_mut(&self, _: &mut Pass) -> std::cell::RefMut<'_, T> {
505 update_cur_state(&self.read_state, &self.cur_state);
506 self.value.borrow_mut()
507 }
508
509 ////////// Mapping of the inner value
510
511 /// Maps the value to another value with a function
512 ///
513 /// This function will return a struct that acts like a "read
514 /// only" version of [`RwData`], which also maps the value to
515 /// a return type.
516 pub fn map<Ret: 'static>(&self, map: impl FnMut(&T) -> Ret + 'static) -> DataMap<T, Ret> {
517 let RwData { value, cur_state, read_state, .. } = self.clone();
518 let data = RwData {
519 value,
520 cur_state,
521 read_state,
522 ty: TypeId::of::<T>(),
523 };
524
525 DataMap { data, map: Rc::new(RefCell::new(map)) }
526 }
527
528 /// Attempts to downcast an [`RwData`] to a concrete type
529 ///
530 /// Returns [`Some(RwData<U>)`] if the value within was of type
531 /// `U`, i.e., for unsized types, `U` was the type parameter
532 /// passed when calling [`RwData::new_unsized`].
533 ///
534 /// [`Some(RwData<U>)`]: Some
535 pub fn try_downcast<U: 'static>(&self) -> Option<RwData<U>> {
536 if TypeId::of::<U>() != self.ty {
537 return None;
538 }
539
540 let ptr = Rc::into_raw(self.value.clone());
541 let value = unsafe { Rc::from_raw(ptr as *const RefCell<U>) };
542 Some(RwData {
543 value,
544 cur_state: self.cur_state.clone(),
545 read_state: Rc::new(Cell::new(self.cur_state.get())),
546 ty: TypeId::of::<U>(),
547 })
548 }
549
550 ////////// Querying functions
551
552 /// Wether this [`RwData`] and another point to the same value
553 pub fn ptr_eq<U: ?Sized>(&self, other: &RwData<U>) -> bool {
554 self.value.as_ptr().addr() == other.value.as_ptr().addr()
555 }
556
557 /// The [`TypeId`] of the concrete type within
558 pub fn type_id(&self) -> TypeId {
559 self.ty
560 }
561
562 /// Wether the concrete [`TypeId`] matches that of `U`
563 pub fn data_is<U: 'static>(&self) -> bool {
564 self.ty == TypeId::of::<U>()
565 }
566
567 /// Wether someone else called [`write`] or [`write_as`] since the
568 /// last [`read`] or [`write`]
569 ///
570 /// Do note that this *DOES NOT* mean that the value inside has
571 /// actually been changed, it just means a mutable reference was
572 /// acquired after the last call to [`has_changed`].
573 ///
574 /// Some types like [`Text`], and traits like [`Widget`] offer
575 /// [`has_changed`](crate::ui::Widget::needs_update) methods,
576 /// you should try to determine what parts to look for changes.
577 ///
578 /// Generally though, you can use this method to gauge that.
579 ///
580 /// [`write`]: Self::write
581 /// [`write_as`]: Self::write_as
582 /// [`read`]: Self::read
583 /// [`has_changed`]: Self::has_changed
584 /// [`Text`]: crate::text::Text
585 /// [`Widget`]: crate::ui::Widget
586 pub fn has_changed(&self) -> bool {
587 self.read_state.get() < self.cur_state.get()
588 }
589
590 /// A function that checks if the data has been updated
591 ///
592 /// Do note that this function will check for the specific
593 /// [`RwData`] that was used in its creation, so if you call
594 /// [`read`] on that specific [`RwData`] for example, this
595 /// function will start returning `false`.
596 ///
597 /// [`read`]: Self::read
598 pub fn checker(&self) -> impl Fn() -> bool + 'static {
599 let (cur, read) = (self.cur_state.clone(), self.read_state.clone());
600 move || read.get() < cur.get()
601 }
602
603 ////////// Widget Functions
604
605 /// Clones the [`Text`] of the [`Widget`]
606 pub fn clone_text<U>(&self, pa: &Pass) -> Text
607 where
608 T: Widget<U>,
609 U: Ui,
610 {
611 self.acquire(pa).text().clone()
612 }
613
614 /// Takes the [`Text`] from the [`Widget`], replacing it with the
615 /// [`Default`]
616 pub fn take_text<U>(&self, pa: &mut Pass) -> Text
617 where
618 T: Widget<U>,
619 U: Ui,
620 {
621 std::mem::take(self.acquire_mut(pa).text_mut())
622 }
623
624 /// Replaces the [`Text`] of the [`Widget`], returning the
625 /// previous value
626 pub fn replace_text<U>(&self, pa: &mut Pass, text: impl Into<Text>) -> Text
627 where
628 T: Widget<U>,
629 U: Ui,
630 {
631 std::mem::replace(self.acquire_mut(pa).text_mut(), text.into())
632 }
633
634 /// The [`PrintCfg`] of the [`Widget`]
635 pub fn print_cfg<U>(&self, pa: &Pass) -> PrintCfg
636 where
637 T: Widget<U>,
638 U: Ui,
639 {
640 self.acquire(pa).print_cfg()
641 }
642
643 /// Whether the [`Widget`] needs to be updated
644 pub fn needs_update<U>(&self, pa: &Pass) -> bool
645 where
646 T: Widget<U>,
647 U: Ui,
648 {
649 self.acquire(pa).needs_update()
650 }
651}
652
653impl<T: ?Sized + 'static> RwData<T> {}
654
655impl<T: ?Sized> Clone for RwData<T> {
656 fn clone(&self) -> Self {
657 Self {
658 value: self.value.clone(),
659 ty: self.ty,
660 cur_state: self.cur_state.clone(),
661 read_state: Rc::new(Cell::new(self.cur_state.get())),
662 }
663 }
664}
665
666impl<T: Default + 'static> Default for RwData<T> {
667 fn default() -> Self {
668 Self {
669 value: Rc::default(),
670 cur_state: Rc::new(Cell::new(1)),
671 read_state: Rc::default(),
672 ty: TypeId::of::<T>(),
673 }
674 }
675}
676
677/// A mapping of an [`RwData`]
678pub struct DataMap<I: ?Sized + 'static, O: 'static> {
679 data: RwData<I>,
680 map: Rc<RefCell<dyn FnMut(&I) -> O>>,
681}
682
683impl<I: ?Sized, O> DataMap<I, O> {
684 /// Maps the value within, works just like [`RwData::map`]
685 pub fn map<O2>(&self, mut f: impl FnMut(O) -> O2 + 'static) -> DataMap<I, O2> {
686 let data_map = self.clone();
687 data_map
688 .data
689 .clone()
690 .map(move |input| f(data_map.map.borrow_mut()(input)))
691 }
692
693 /// Wether someone else called [`write`] or [`write_as`] since the
694 /// last [`read`] or [`write`]
695 ///
696 /// Do note that this *DOES NOT* mean that the value inside has
697 /// actually been changed, it just means a mutable reference was
698 /// acquired after the last call to [`has_changed`].
699 ///
700 /// Some types like [`Text`], and traits like [`Widget`] offer
701 /// [`needs_update`] methods, you should try to determine what
702 /// parts to look for changes.
703 ///
704 /// Generally though, you can use this method to gauge that.
705 ///
706 /// [`write`]: RwData::write
707 /// [`write_as`]: RwData::write_as
708 /// [`read`]: RwData::read
709 /// [`has_changed`]: RwData::has_changed
710 /// [`Text`]: crate::text::Text
711 /// [`Widget`]: crate::ui::Widget
712 /// [`needs_update`]: crate::ui::Widget::needs_update
713 pub fn has_changed(&self) -> bool {
714 self.data.has_changed()
715 }
716
717 /// A function that checks if the data has been updated
718 ///
719 /// Do note that this function will check for the specific
720 /// [`RwData`] that was used in its creation, so if you call
721 /// [`read`] on that specific [`RwData`] for example, this
722 /// function will start returning `false`.
723 ///
724 /// [`read`]: RwData::read
725 pub fn checker(&self) -> impl Fn() -> bool + 'static {
726 self.data.checker()
727 }
728}
729
730impl<I: ?Sized + 'static, O> Clone for DataMap<I, O> {
731 fn clone(&self) -> Self {
732 Self {
733 data: self.data.clone(),
734 map: self.map.clone(),
735 }
736 }
737}
738
739impl<I: ?Sized + 'static, O: 'static> DataMap<I, O> {}
740
741impl<I: ?Sized + 'static, O: 'static> FnOnce<(&Pass<'_>,)> for DataMap<I, O> {
742 type Output = O;
743
744 extern "rust-call" fn call_once(self, (key,): (&Pass,)) -> Self::Output {
745 self.data.read(key, |input| self.map.borrow_mut()(input))
746 }
747}
748
749impl<I: ?Sized + 'static, O: 'static> FnMut<(&Pass<'_>,)> for DataMap<I, O> {
750 extern "rust-call" fn call_mut(&mut self, (key,): (&Pass,)) -> Self::Output {
751 self.data.read(key, |input| self.map.borrow_mut()(input))
752 }
753}
754
755impl<I: ?Sized + 'static, O: 'static> Fn<(&Pass<'_>,)> for DataMap<I, O> {
756 extern "rust-call" fn call(&self, (key,): (&Pass,)) -> Self::Output {
757 self.data.read(key, |input| self.map.borrow_mut()(input))
758 }
759}
760
761/// A checking struct that periodically returns `true`
762pub struct PeriodicChecker(Arc<AtomicBool>);
763
764impl PeriodicChecker {
765 /// Returns a new [`PeriodicChecker`]
766 pub fn new(duration: Duration) -> Self {
767 let has_elapsed = Arc::new(AtomicBool::new(false));
768 std::thread::spawn({
769 let has_elapsed = has_elapsed.clone();
770 move || {
771 while !crate::context::will_reload_or_quit() {
772 std::thread::sleep(duration);
773 has_elapsed.store(true, Ordering::Relaxed);
774 }
775 }
776 });
777
778 Self(has_elapsed)
779 }
780
781 /// Checks if the requested [`Duration`] has elapsed
782 pub fn check(&self) -> bool {
783 self.0.fetch_and(false, Ordering::Relaxed)
784 }
785}
786
787/// A key for reading/writing to [`RwData`]
788///
789/// This key is necessary in order to prevent breakage of the number
790/// one rule of Rust: any number of shared references, or one
791/// exclusive reference.
792///
793/// When you call [`RwData::read`], any call to [`RwData::write`] may
794/// end up breaking this rule, and vice-versa, which is why this
795/// struct is necessary.
796///
797/// One downside of this approach is that it is even more restrictive
798/// than Rust's rule of thumb, since that one is enforced on
799/// individual instances, while this one is enforced on all
800/// [`RwData`]s. This (as far as i know) cannot be circumvented, as a
801/// more advanced compile time checker (that distinguishes
802/// [`RwData<T>`]s of different `T`s, for example) does not seem
803/// feasible without the use of unfinished features, which I am not
804/// willing to use.
805///
806/// Do note that you can still ignore this if you want, by use of
807/// [`read_unsafe`] and [`write_unsafe`], but this might cause a panic
808/// in Duat because of the [`RefCell`]s under the hood.
809///
810/// [`read_unsafe`]: RwData::read_unsafe
811/// [`write_unsafe`]: RwData::write_unsafe
812pub struct Pass<'a>(PhantomData<&'a Rc<RefCell<()>>>);
813
814impl Pass<'_> {
815 /// Returns a new instance of [`Pass`]
816 ///
817 /// Be careful when using this!
818 pub(crate) unsafe fn new() -> Self {
819 Pass(PhantomData)
820 }
821}
822
823fn update_read_state(read_state: &Rc<Cell<usize>>, cur_state: &Rc<Cell<usize>>) {
824 read_state.set(cur_state.get());
825}
826
827fn update_cur_state(read_state: &Rc<Cell<usize>>, cur_state: &Rc<Cell<usize>>) {
828 cur_state.set(cur_state.get() + 1);
829 read_state.set(cur_state.get());
830}