Skip to main content

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 [`Buffer`]s, and Duat can know when a [`Buffer`] 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 [`RefCell`] and [`UnsafeCell`].
27//! These are often considered "crutches" by a lot of the Rust
28//! community, but in an environment where most of the code is
29//! supposed to be able to access most of the state, it is impossible
30//! to go without using them.
31//!
32//! The use of [`UnsafeCell`] internally also makes the [`read`] and
33//! [`write`] operations _basically_ 0 cost,
34//!
35//! [read]: RwData::read
36//! [written to]: RwData::write
37//! [`Widget`]: crate::ui::Widget
38//! [`Buffer`]: crate::buffer::Buffer
39//! [updated]: crate::ui::Widget::update
40//! [`Text`]: crate::text::Text
41//! [`StatusLine`]: https://docs.rs/duat/latest/duat/widgets/struct.StatusLine.html
42//! [`context`]: crate::context
43//! [`Mutex`]: std::sync::Mutex
44//! [`read`]: RwData::read
45//! [`write`]: RwData::write
46use std::{
47    self,
48    any::TypeId,
49    cell::{RefCell, UnsafeCell},
50    marker::PhantomData,
51    sync::{
52        Arc, LazyLock, Mutex,
53        atomic::{AtomicUsize, Ordering},
54    },
55};
56
57use crate::ui::Widget;
58
59/// A container for shared read/write state
60///
61/// This is the struct used internally (and externally) to allow for
62/// massively shareable state in duat's API. Its main purpose is to
63/// hold all of the [`Widget`]s in Duat, making them available for
64/// usage from any function with access to a [`Pass`]. However, it can
65/// also be used to hold any other type, and also has the ability to
66/// notify when changes have taken place.
67///
68/// # [`Pass`]es
69///
70/// The `Pass` is a sort of "key" for accessing the value within an
71/// `RwData`, its purpose is to maintain Rust's number one rule,
72/// i.e. one exclusive reference or multiple shared references
73/// (mutability XOR aliasing), and that is done by borrowing the
74/// `Pass` mutably or non mutably. That comes with some limitations
75/// on how they can be used, mostly the fact that you must mutably
76/// borrow all `RwData`s that will be used [_at the same time_] in
77/// order to get multiple mutable references at once.
78///
79/// The use of a `Pass` for reading/writing to `RwData`s confers
80/// various benefits:
81///
82/// - Aside from updating an internal update counter, it is truly
83///   _zero cost_, unlike in the case of a [`Mutex`] or [`RefCell`],
84///   which have to do checks at runtime. This happens because the
85///   `Pass` has zero size, i.e. it gets removed at compile time.
86/// - You can't run into deadlocks like you would be able to when
87///   using `Mutex`es. Neither can you run into panics from
88///   reborrowing, like with `RefCell`.
89/// - You don't have to drop a `Guard` type (like [`MutexGuard`]) in
90///   order to reborrow from the `RwData` since borrowing gives you a
91///   first class `&` or `&mut`, which are much easier to work with.
92/// - You can do sub borrowings, like `&mut data.write(pa).field`,
93///   given the `&mut` borrow.
94///
95/// However, there are also a few disadvantages:
96///
97/// - Sometimes, mutably borrowing multiple things in a single
98///   function _can_ be a challenge, although that is mostly mitigated
99///   by [`Pass::write_many`].
100/// - You _cannot_ access the data in a `RwData` from threads other
101///   than the main one, since the `Pass` is only accessible from it.
102///   This isn't _really_ a disadvantage, since it simplifies thought
103///   patterns and eases reasoning about the current state of things.
104///
105/// [`Mutex`]: std::sync::Mutex
106/// [`MutexGuard`]: std::sync::MutexGuard
107/// [parser]: crate::buffer::BufferTracker
108/// [`Text`]: crate::text::Text
109/// [_at the same time_]: Pass::write_many
110#[derive(Debug)]
111pub struct RwData<T: ?Sized> {
112    value: Arc<UnsafeCell<T>>,
113    cur_state: Arc<AtomicUsize>,
114    read_state: Arc<AtomicUsize>,
115    ty: TypeId,
116}
117
118impl<T: 'static> RwData<T> {
119    /// Returns a new [`RwData<T>`]
120    ///
121    /// Note that this is only for sized types. For unsized types, the
122    /// process is a little more convoluted, and you need to use
123    /// [`RwData::new_unsized`].
124    pub fn new(value: T) -> Self {
125        Self {
126            value: Arc::new(UnsafeCell::new(value)),
127            ty: TypeId::of::<T>(),
128            cur_state: Arc::new(AtomicUsize::new(1)),
129            read_state: Arc::new(AtomicUsize::new(0)),
130        }
131    }
132}
133
134impl<T: ?Sized> RwData<T> {
135    /// Returns an unsized [`RwData`], such as [`RwData<dyn Trait>`]
136    ///
137    /// # Safety
138    ///
139    /// There is a type argument `SizedT` which _must_ be the exact
140    /// type you are passing to this constructor, i.e., if you are
141    /// creating an [`RwData<dyn Display>`] from a [`String`], you'd
142    /// do this:
143    ///
144    /// ```rust
145    /// # duat_core::doc_duat!(duat);
146    /// use std::{cell::UnsafeCell, fmt::Display, sync::Arc};
147    ///
148    /// use duat::{data::RwData, prelude::*};
149    /// let rw_data: RwData<dyn Display> =
150    ///     unsafe { RwData::new_unsized::<String>(Arc::new(UnsafeCell::new("test".to_string()))) };
151    /// ```
152    ///
153    /// This ensures that methods such as [`read_as`] and [`write_as`]
154    /// will correctly identify such [`RwData<dyn Display>`] as a
155    /// [`String`].
156    ///
157    /// [`read_as`]: Self::read_as
158    /// [`write_as`]: Self::write_as
159    #[doc(hidden)]
160    pub unsafe fn new_unsized<SizedT: 'static>(value: Arc<UnsafeCell<T>>) -> Self {
161        Self {
162            value,
163            ty: TypeId::of::<SizedT>(),
164            cur_state: Arc::new(AtomicUsize::new(1)),
165            read_state: Arc::new(AtomicUsize::new(0)),
166        }
167    }
168
169    ////////// Reading functions
170
171    /// Reads the value within using a [`Pass`]
172    ///
173    /// The consistent use of a [`Pass`] for the purposes of
174    /// reading/writing to the values of [`RwData`]s ensures that no
175    /// panic or invalid borrow happens at runtime, even while working
176    /// with untrusted code. More importantly, Duat uses these
177    /// guarantees in order to give the end user a ridiculous amount
178    /// of freedom in where they can do things, whilst keeping Rust's
179    /// number one rule and ensuring thread safety, even with a
180    /// relatively large amount of shareable state.
181    pub fn read<'p>(&'p self, _: &'p Pass) -> &'p T {
182        self.read_state
183            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
184        // SAFETY: If one were to try and write to this value, this reference
185        // would instantly become invalid, and trying to read from it again
186        // would cause a compile error due to a Pass borrowing conflict.
187        unsafe { &*self.value.get() }
188    }
189
190    /// Reads the value within as `U` using a [`Pass`]
191    ///
192    /// The consistent use of a [`Pass`] for the purposes of
193    /// reading/writing to the values of [`RwData`]s ensures that no
194    /// panic or invalid borrow happens at runtime, even while working
195    /// with untrusted code. More importantly, Duat uses these
196    /// guarantees in order to give the end user a ridiculous amount
197    /// of freedom in where they can do things, whilst keeping Rust's
198    /// number one rule and ensuring thread safety, even with a
199    /// relatively large amount of shareable state.
200    pub fn read_as<'p, U: 'static>(&'p self, _: &'p Pass) -> Option<&'p U> {
201        if TypeId::of::<U>() != self.ty {
202            return None;
203        }
204
205        self.read_state
206            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
207
208        let ptr = Arc::as_ptr(&self.value) as *const UnsafeCell<U>;
209
210        // SAFETY: Same as above, but also, the TypeId in the Handle
211        // "guarantees" that this is the correct type.
212        Some(unsafe { &*(&*ptr).get() })
213    }
214
215    /// Simulates a [`read`] without actually reading
216    ///
217    /// This is useful if you want to tell Duat that you don't want
218    /// [`has_changed`] to return `true`, but you don't have a
219    /// [`Pass`] available to [`read`] the value.
220    ///
221    /// [`read`]: Self::read
222    /// [`has_changed`]: Self::has_changed
223    pub fn declare_as_read(&self) {
224        self.read_state
225            .store(self.cur_state.load(Ordering::Relaxed), Ordering::Relaxed);
226    }
227
228    ////////// Writing functions
229
230    /// Writes to the value within using a [`Pass`]
231    ///
232    /// The consistent use of a [`Pass`] for the purposes of
233    /// reading/writing to the values of [`RwData`]s ensures that no
234    /// panic or invalid borrow happens at runtime, even while working
235    /// with untrusted code. More importantly, Duat uses these
236    /// guarantees in order to give the end user a ridiculous amount
237    /// of freedom in where they can do things, whilst keeping Rust's
238    /// number one rule and ensuring thread safety, even with a
239    /// relatively large amount of shareable state.
240    pub fn write<'p>(&'p self, _: &'p mut Pass) -> &'p mut T {
241        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
242        self.read_state.store(prev + 1, Ordering::Relaxed);
243        // SAFETY: Again, the mutable reference to the Pass ensures that this
244        // is the only _valid_ mutable reference, if another reference,
245        // created prior to this one, were to be reused, that would be a
246        // compile error.
247        unsafe { &mut *self.value.get() }
248    }
249
250    /// Writes to the value within as `U` using a [`Pass`]
251    ///
252    /// The consistent use of a [`Pass`] for the purposes of
253    /// reading/writing to the values of [`RwData`]s ensures that no
254    /// panic or invalid borrow happens at runtime, even while working
255    /// with untrusted code. More importantly, Duat uses these
256    /// guarantees in order to give the end user a ridiculous amount
257    /// of freedom in where they can do things, whilst keeping Rust's
258    /// number one rule and ensuring thread safety, even with a
259    /// relatively large amount of shareable state.
260    pub fn write_as<'p, U: 'static>(&'p self, _: &'p mut Pass) -> Option<&'p mut U> {
261        if TypeId::of::<U>() != self.ty {
262            return None;
263        }
264
265        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
266        self.read_state.store(prev + 1, Ordering::Relaxed);
267
268        let ptr = Arc::as_ptr(&self.value) as *const UnsafeCell<U>;
269
270        // SAFETY: Same as above, but also, the TypeId in the Handle
271        // "guarantees" that this is the correct type.
272        Some(unsafe { &mut *(&*ptr).get() })
273    }
274
275    /// Writes to the value _and_ internal [`RwData`]-like structs
276    ///
277    /// This method takes a function that borrows a [`WriteableTuple`]
278    /// from `self`, letting you write to `self` and the data in the
279    /// tuple (or single element) at the same time.
280    ///
281    /// This is _really_ useful in a scenario where, for example, your
282    /// [`Handle<W>`] for some widget `W` holds a [`Handle<Buffer>`],
283    /// and you wish to access both at the same time, while writing to
284    /// the former:
285    ///
286    /// ```rust
287    /// # duat_core::doc_duat!(duat);
288    /// use duat::prelude::*;
289    ///
290    /// struct MyWidget {
291    ///     text: Text,
292    ///     buf: Handle,
293    /// }
294    ///
295    /// impl Widget for MyWidget {
296    ///     fn update(pa: &mut Pass, handle: &Handle<Self>) {
297    ///         let (wid, buf) = handle.write_then(pa, |wid| &wid.buf);
298    ///         // Updating the widget and reading/writing from the Buffer at the same time.
299    ///         // ...
300    ///     }
301    ///     // ..
302    ///     # fn text(&self) -> &Text { &self.text }
303    ///     # fn text_mut(&mut self) -> TextMut { self.text.as_mut() }
304    ///     # fn needs_update(&self, pa: &Pass) -> bool { false }
305    /// }
306    /// ```
307    ///
308    /// You can also return tuples from the function, allowing for
309    /// access to up to twelve different [`RwData`]-like structs:
310    ///
311    /// ```rust
312    /// # duat_core::doc_duat!(duat);
313    /// use duat::prelude::*;
314    ///
315    /// struct MyWidget {
316    ///     text: Text,
317    ///     buf1: Handle,
318    ///     buf2: Handle,
319    /// }
320    ///
321    /// impl Widget for MyWidget {
322    ///     fn update(pa: &mut Pass, handle: &Handle<Self>) {
323    ///         let (wid, (b1, b2)) = handle.write_then(pa, |wid| (&wid.buf1, &wid.buf2));
324    ///         // ...
325    ///     }
326    ///     // ..
327    ///     # fn text(&self) -> &Text { &self.text }
328    ///     # fn text_mut(&mut self) -> TextMut { self.text.as_mut() }
329    ///     # fn needs_update(&self, pa: &Pass) -> bool { false }
330    /// }
331    /// ```
332    ///
333    /// # Panics
334    ///
335    /// This function will panic if any of the elements of the tuple
336    /// point to the same data as any other element or `self`, see
337    /// [`Pass::write_many`] for more information.
338    ///
339    /// [`Handle<W>`]: crate::context::Handle
340    /// [`Handle<Buffer>`]: crate::context::Handle
341    #[track_caller]
342    #[allow(static_mut_refs)]
343    pub fn write_then<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
344        &'p self,
345        pa: &'p mut Pass,
346        tup_fn: impl FnOnce(&'p T) -> Tup,
347    ) -> (&'p mut T, Tup::Return) {
348        let tup = tup_fn(self.read(pa));
349        if tup
350            .state_ptrs()
351            .into_iter()
352            .any(|ptr| ptr == CurStatePtr(&self.cur_state))
353        {
354            panic!("Tried writing to the same data multiple times at the same time");
355        }
356
357        /// SAFETY: The ptrs are already verifiably not pointing to
358        /// the data of self.
359        static PASS: Pass = unsafe { Pass::new() };
360
361        let tup_ret = unsafe { (&raw const PASS as *mut Pass).as_mut() }
362            .unwrap()
363            .write_many(tup);
364
365        let value = self.write(unsafe { (&raw const PASS as *mut Pass).as_mut() }.unwrap());
366
367        (value, tup_ret)
368    }
369
370    /// Simulates a [`write`] without actually writing
371    ///
372    /// This is useful if you want to tell Duat that you want
373    /// [`has_changed`] to return `true`, but you don't have a
374    /// [`Pass`] available to [`write`] the value with.
375    ///
376    /// [`write`]: Self::write
377    /// [`has_changed`]: Self::has_changed
378    pub fn declare_written(&self) {
379        let prev = self.cur_state.fetch_add(1, Ordering::Relaxed);
380        self.read_state.store(prev + 1, Ordering::Relaxed);
381    }
382
383    /// Takes the value within, replacing it with the default
384    pub fn take(&self, pa: &mut Pass) -> T
385    where
386        T: Default,
387    {
388        std::mem::take(self.write(pa))
389    }
390
391    ////////// Mapping of the inner value
392
393    /// Maps the value to another value with a function
394    ///
395    /// This function will return a struct that acts like a "read
396    /// only" version of [`RwData`], which also maps the value to
397    /// a return type.
398    pub fn map<Ret: 'static>(&self, map: impl FnMut(&T) -> Ret + 'static) -> DataMap<T, Ret> {
399        let RwData { value, cur_state, .. } = self.clone();
400        let data = RwData {
401            value,
402            cur_state,
403            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed))),
404            ty: TypeId::of::<T>(),
405        };
406
407        DataMap { data, map: Arc::new(RefCell::new(map)) }
408    }
409
410    /// Maps the value to another value with a mutating function
411    ///
412    /// This is useful if you want to repeat a function over and over
413    /// again in order to get a new different result, whilst mutating
414    /// the data within.
415    pub fn map_mut<Ret: 'static>(
416        &self,
417        map: impl FnMut(&mut T) -> Ret + 'static,
418    ) -> MutDataMap<T, Ret> {
419        let RwData { value, cur_state, .. } = self.clone();
420        let data = RwData {
421            value,
422            cur_state,
423            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed))),
424            ty: TypeId::of::<T>(),
425        };
426
427        MutDataMap { data, map: Arc::new(RefCell::new(map)) }
428    }
429
430    /// Attempts to downcast an [`RwData`] to a concrete type
431    ///
432    /// Returns [`Some(RwData<U>)`] if the value within is of type
433    /// `U`. For unsized types, `U` is the type parameter
434    /// passed when calling [`RwData::new_unsized`].
435    ///
436    /// [`Some(RwData<U>)`]: Some
437    pub fn try_downcast<U: 'static>(&self) -> Option<RwData<U>> {
438        if TypeId::of::<U>() != self.ty {
439            return None;
440        }
441
442        let ptr = Arc::into_raw(self.value.clone());
443        // SAFETY: TypeId argument "guarantees" this
444        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<U>) };
445        Some(RwData {
446            value,
447            cur_state: self.cur_state.clone(),
448            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
449            ty: TypeId::of::<U>(),
450        })
451    }
452
453    ////////// Querying functions
454
455    /// Wether this [`RwData`] and another point to the same value
456    pub fn ptr_eq<U: ?Sized>(&self, other: &RwData<U>) -> bool {
457        Arc::ptr_eq(&self.cur_state, &other.cur_state)
458    }
459
460    /// The [`TypeId`] of the concrete type within
461    pub fn type_id(&self) -> TypeId {
462        self.ty
463    }
464
465    /// Wether the concrete [`TypeId`] matches that of `U`
466    pub fn is<U: 'static>(&self) -> bool {
467        self.ty == TypeId::of::<U>()
468    }
469
470    /// Wether someone else called [`write`] or [`write_as`] since the
471    /// last [`read`] or `write`
472    ///
473    /// Do note that this *DOES NOT* mean that the value inside has
474    /// actually been changed, it just means a mutable reference was
475    /// acquired after the last call to [`has_changed`].
476    ///
477    /// Some types like [`Text`], and traits like [`Widget`] offer
478    /// [`has_changed`](crate::ui::Widget::needs_update) methods,
479    /// you should try to determine what parts to look for changes.
480    ///
481    /// Generally though, you can use this method to gauge that.
482    ///
483    /// [`write`]: Self::write
484    /// [`write_as`]: Self::write_as
485    /// [`read`]: Self::read
486    /// [`has_changed`]: Self::has_changed
487    /// [`Text`]: crate::text::Text
488    /// [`Widget`]: crate::ui::Widget
489    pub fn has_changed(&self) -> bool {
490        self.read_state.load(Ordering::Relaxed) < self.cur_state.load(Ordering::Relaxed)
491    }
492
493    /// A function that checks if the data has been updated
494    ///
495    /// Do note that this function will check for the specific
496    /// [`RwData`] that was used in its creation, so if you call
497    /// [`read`] on that specific [`RwData`] for example, this
498    /// function will start returning `false`.
499    ///
500    /// [`read`]: Self::read
501    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
502        let (read, cur) = (self.read_state.clone(), self.cur_state.clone());
503        move || read.load(Ordering::Relaxed) < cur.load(Ordering::Relaxed)
504    }
505}
506
507impl<W: Widget> RwData<W> {
508    /// Downcasts [`RwData<impl Widget>`] to [`RwData<dyn Widget>`]
509    pub fn to_dyn_widget(&self) -> RwData<dyn Widget> {
510        let ptr = Arc::into_raw(self.value.clone());
511        // SAFETY: Implements Widget
512        let value = unsafe { Arc::from_raw(ptr as *const UnsafeCell<dyn Widget>) };
513        RwData {
514            value,
515            cur_state: self.cur_state.clone(),
516            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
517            ty: self.ty,
518        }
519    }
520}
521
522// SAFETY: The only parts that are accessible from other threads are
523// the atomic counters from the Arcs. Everything else can only be
524// acquired when there is a Pass, i.e., on the main thread.
525unsafe impl<T: ?Sized> Send for RwData<T> {}
526unsafe impl<T: ?Sized> Sync for RwData<T> {}
527
528impl<T: ?Sized> Clone for RwData<T> {
529    fn clone(&self) -> Self {
530        Self {
531            value: self.value.clone(),
532            ty: self.ty,
533            cur_state: self.cur_state.clone(),
534            read_state: Arc::new(AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1)),
535        }
536    }
537}
538
539impl<T: Default + 'static> Default for RwData<T> {
540    fn default() -> Self {
541        Self {
542            value: Arc::default(),
543            cur_state: Arc::new(AtomicUsize::new(1)),
544            read_state: Arc::new(AtomicUsize::new(0)),
545            ty: TypeId::of::<T>(),
546        }
547    }
548}
549
550/// A mapping of an [`RwData`]
551pub struct DataMap<I: ?Sized + 'static, O: 'static> {
552    data: RwData<I>,
553    map: Arc<RefCell<dyn FnMut(&I) -> O>>,
554}
555
556impl<I: ?Sized, O> DataMap<I, O> {
557    /// Call this `DataMap`'s mapping function, returning the output
558    pub fn call(&self, pa: &Pass) -> O {
559        self.map.borrow_mut()(self.data.read(pa))
560    }
561
562    /// Maps the value within, works just like [`RwData::map`]
563    pub fn map<O2>(self, mut f: impl FnMut(O) -> O2 + 'static) -> DataMap<I, O2> {
564        self.data.map(move |input| f(self.map.borrow_mut()(input)))
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    /// [`needs_update`] methods, you should try to determine what
576    /// parts to look for changes.
577    ///
578    /// Generally though, you can use this method to gauge that.
579    ///
580    /// [`write`]: RwData::write
581    /// [`write_as`]: RwData::write_as
582    /// [`read`]: RwData::read
583    /// [`has_changed`]: RwData::has_changed
584    /// [`Text`]: crate::text::Text
585    /// [`Widget`]: crate::ui::Widget
586    /// [`needs_update`]: crate::ui::Widget::needs_update
587    pub fn has_changed(&self) -> bool {
588        self.data.has_changed()
589    }
590
591    /// A function that checks if the data has been updated
592    ///
593    /// Do note that this function will check for the specific
594    /// [`RwData`] that was used in its creation, so if you call
595    /// [`read`] on that specific [`RwData`] for example, this
596    /// function will start returning `false`.
597    ///
598    /// [`read`]: RwData::read
599    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
600        self.data.checker()
601    }
602}
603
604// SAFETY: The only parts that are accessible from other threads are
605// the atomic counters from the Arcs. Everything else can only be
606// acquired when there is a Pass, i.e., on the main thread.
607unsafe impl<I: ?Sized + 'static, O: 'static> Send for DataMap<I, O> {}
608unsafe impl<I: ?Sized + 'static, O: 'static> Sync for DataMap<I, O> {}
609
610/// A mutable mapping of an [`RwData`]
611///
612/// This works very similarly to the [`DataMap`], except the function
613/// is allowed to mutate the data, so it takes a `&mut Pass` instead
614/// of a regular `&Pass`.
615pub struct MutDataMap<I: ?Sized + 'static, O: 'static> {
616    data: RwData<I>,
617    map: Arc<RefCell<dyn FnMut(&mut I) -> O>>,
618}
619
620impl<I: ?Sized, O> MutDataMap<I, O> {
621    /// Call this `DataMap`'s mapping function, returning the output
622    pub fn call(&self, pa: &mut Pass) -> O {
623        self.map.borrow_mut()(self.data.write(pa))
624    }
625
626    /// Maps the value within, works just like [`RwData::map`]
627    pub fn map<O2>(self, mut f: impl FnMut(O) -> O2 + 'static) -> MutDataMap<I, O2> {
628        self.data
629            .map_mut(move |input| f(self.map.borrow_mut()(input)))
630    }
631
632    /// Wether someone else called [`write`] or [`write_as`] since the
633    /// last [`read`] or [`write`]
634    ///
635    /// Do note that this *DOES NOT* mean that the value inside has
636    /// actually been changed, it just means a mutable reference was
637    /// acquired after the last call to [`has_changed`].
638    ///
639    /// Some types like [`Text`], and traits like [`Widget`] offer
640    /// [`needs_update`] methods, you should try to determine what
641    /// parts to look for changes.
642    ///
643    /// Generally though, you can use this method to gauge that.
644    ///
645    /// [`write`]: RwData::write
646    /// [`write_as`]: RwData::write_as
647    /// [`read`]: RwData::read
648    /// [`has_changed`]: RwData::has_changed
649    /// [`Text`]: crate::text::Text
650    /// [`Widget`]: crate::ui::Widget
651    /// [`needs_update`]: crate::ui::Widget::needs_update
652    pub fn has_changed(&self) -> bool {
653        self.data.has_changed()
654    }
655
656    /// A function that checks if the data has been updated
657    ///
658    /// Do note that this function will check for the specific
659    /// [`RwData`] that was used in its creation, so if you call
660    /// [`read`] on that specific [`RwData`] for example, this
661    /// function will start returning `false`.
662    ///
663    /// [`read`]: RwData::read
664    pub fn checker(&self) -> impl Fn() -> bool + Send + Sync + 'static {
665        self.data.checker()
666    }
667}
668
669// SAFETY: The only parts that are accessible from other threads are
670// the atomic counters from the Arcs. Everything else can only be
671// acquired when there is a Pass, i.e., on the main thread.
672unsafe impl<I: ?Sized + 'static, O: 'static> Send for MutDataMap<I, O> {}
673unsafe impl<I: ?Sized + 'static, O: 'static> Sync for MutDataMap<I, O> {}
674
675/// A struct used for asynchronously mutating [`RwData`]s without a
676/// [`Pass`]
677///
678/// This works by wrapping the `RwData` and collecting every mutating
679/// function inside a separate [`Mutex`]. Whenever you access the
680/// `Data`, the changes are applied to it.
681///
682/// With this in mind, one limitation of this type is that every
683/// access must make use of a `&mut Pass`, with the exception of
684/// [`BulkDataWriter::try_read`], which returns `Some` only when there
685/// have been no changes to the `Data`.
686#[derive(Default)]
687pub struct BulkDataWriter<Data: Default + 'static> {
688    actions: LazyLock<Arc<Mutex<Vec<Box<dyn FnOnce(&mut Data) + Send + 'static>>>>>,
689    data: LazyLock<RwData<Data>>,
690}
691
692impl<Data: Default + 'static> BulkDataWriter<Data> {
693    /// Returns a new `BulkDataWriter`
694    ///
695    /// Considering the fact that this struct is almost exclusively
696    /// used in `static` variables, I have decided to make its
697    /// constructor `const`, to facilitate its usage.
698    #[allow(clippy::new_without_default)]
699    pub const fn new() -> Self {
700        Self {
701            actions: LazyLock::new(|| Arc::new(Mutex::new(Vec::new()))),
702            data: LazyLock::new(|| RwData::new(Data::default())),
703        }
704    }
705
706    /// Adds a mutating function to the list of functions to call upon
707    /// accessing the `Data`
708    ///
709    /// This is useful for allowing mutation from any thread, and
710    /// without needing [`Pass`]es. `duat-core` makes extensive use of
711    /// this function in order to provide pleasant to use APIs.
712    pub fn mutate(&self, f: impl FnOnce(&mut Data) + Send + 'static) {
713        self.actions.lock().unwrap().push(Box::new(f));
714    }
715
716    /// Accesses the `Data`, calling all added actions
717    ///
718    /// This function will call all actions that were sent by the
719    /// [`BulkDataWriter::mutate`] function in order to write to the
720    /// `Data` asynchronously.
721    pub fn write<'p>(&'p self, pa: &'p mut Pass) -> &'p mut Data {
722        let data = self.data.write(pa);
723        for action in self.actions.lock().unwrap().drain(..) {
724            action(data);
725        }
726        data
727    }
728
729    /// Attempts to read the `Data`
730    ///
731    /// This function will return [`None`] if there are pending
732    /// actions that need to happen before reading/writing. You should
733    /// almost always prefer calling [`BulkDataWriter::write`]
734    /// instead.
735    pub fn try_read<'p>(&'p self, pa: &'p Pass) -> Option<&'p Data> {
736        self.actions
737            .lock()
738            .unwrap()
739            .is_empty()
740            .then(|| self.data.read(pa))
741    }
742
743    /// Maps the value to another value with a mutating function
744    ///
745    /// This will apply the delayed updting of
746    /// [`BulkDataWriter::write`] every time the mapping is called, so
747    /// the value always stays up to date.
748    pub fn map_mut<Ret: 'static>(
749        &self,
750        mut map: impl FnMut(&mut Data) -> Ret + 'static,
751    ) -> MutDataMap<Data, Ret> {
752        let actions = self.actions.clone();
753        self.data.map_mut(move |data| {
754            for action in actions.lock().unwrap().drain(..) {
755                action(data);
756            }
757            map(data)
758        })
759    }
760}
761
762/// A key for reading/writing to [`RwData`]
763///
764/// This key is necessary in order to prevent breakage of the number
765/// one rule of Rust: any number of shared references, or one
766/// exclusive reference.
767///
768/// When you call [`RwData::read`], any call to [`RwData::write`] may
769/// end up breaking this rule, and vice-versa, which is why this
770/// struct is necessary.
771///
772/// One downside of this approach is that it is even more restrictive
773/// than Rust's rule of thumb, since that one is enforced on
774/// individual instances, while this one is enforced on all
775/// [`RwData`]s. This (as far as i know) cannot be circumvented, as a
776/// more advanced compile time checker (that distinguishes
777/// [`RwData<T>`]s of different `T`s, for example) does not seem
778/// feasible without the use of unfinished features, which I am not
779/// willing to use.
780pub struct Pass(PhantomData<()>);
781
782impl Pass {
783    /// Returns a new instance of [`Pass`]
784    ///
785    /// Be careful when using this!
786    pub(crate) const unsafe fn new() -> Self {
787        Pass(PhantomData)
788    }
789
790    /// Writes to many [`RwData`]-like structs at once
791    ///
792    /// This function accepts tuples (or a single element) of
793    /// references to types that implement the [`WriteableData`]
794    /// trait, which is one of the following:
795    ///
796    /// - [`RwData`]: Duat's regular smart pointer.
797    /// - [`BulkDataWriter`]: A pointer to lazyly updated data.
798    /// - [`Handle`]: A handle for a [`Widget`]
799    /// - [`RwArea`]: A handle for a `Widget`'s [`Area`]
800    ///
801    /// Here's an example, which writes to two `RwData`s at the same
802    /// time as a `Handle`:
803    ///
804    /// ```rust
805    /// # duat_core::doc_duat!(duat);
806    /// use duat::{data::RwData, prelude::*};
807    /// setup_duat!(setup);
808    ///
809    /// fn setup() {
810    ///     let (num1, num2) = (RwData::new(0), RwData::new(0));
811    ///     hook::add::<BufferOpened>(move |pa, handle: &Handle| {
812    ///         let (num1, num2, buf) = pa.write_many((&num1, &num2, handle));
813    ///         // Rest of the function writes to all of them at the same time.
814    ///     });
815    /// }
816    /// ```
817    ///
818    /// This allows for much more flexibility when writing to global
819    /// state, which should hopefully lead to more streamlined
820    /// functions
821    ///
822    /// # Panics
823    ///
824    /// This function will panic if any of the elements of the tuple
825    /// point to the same data as any other element, for example, with
826    /// the earlier code snippet:
827    ///
828    /// ```rust
829    /// # duat_core::doc_duat!(duat);
830    /// use duat::{data::RwData, prelude::*};
831    /// setup_duat!(setup);
832    ///
833    /// fn setup() {
834    ///     let num1 = RwData::new(0);
835    ///     // num2 is now a clone of num1
836    ///     let num2 = num1.clone();
837    ///     hook::add::<BufferOpened>(move |pa, handle: &Handle| {
838    ///         let (num1, num2, buf) = pa.write_many((&num1, &num2, handle));
839    ///         // Rest of the function writes to all of them at the same time.
840    ///     });
841    /// }
842    /// ```
843    ///
844    /// Since `num1` and `num2` point to the same data, you'd be
845    /// getting two `&mut i32` for the same variable, which violates
846    /// rust's "mutability xor aliasing" rule. This is why this will
847    /// panic. If you want a non-panicking version of this function,
848    /// check out [`Pass::try_write_many`], which returns a [`Result`]
849    /// instead.
850    ///
851    /// [`Handle`]: crate::context::Handle
852    /// [`RwArea`]: crate::ui::RwArea
853    /// [`Area`]: crate::ui::Area
854    #[track_caller]
855    pub fn write_many<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
856        &'p mut self,
857        tup: Tup,
858    ) -> Tup::Return {
859        if let Some(ret) = tup.write_all(self) {
860            ret
861        } else {
862            panic!("Tried writing to the same data multiple times");
863        }
864    }
865
866    /// Tries writing to many [`RwData`]-like structs at once
867    ///
868    /// This function accepts tuples (or a single element) of
869    /// references to types that implement the [`WriteableData`]
870    /// trait, which is one of the following:
871    ///
872    /// - [`RwData`]: Duat's regular smart pointer.
873    /// - [`BulkDataWriter`]: A pointer to lazyly updated data.
874    /// - [`Handle`]: A handle for a [`Widget`]
875    /// - [`RwArea`]: A handle for a `Widget`'s [`Area`]
876    ///
877    /// This function works exactly like [`Pass::write_many`],
878    /// however, instead of panicking, this function returns a
879    /// [`Result`], returning an [`Err`] if any of the tuple's
880    /// elements point to the same data as any of the other elements.
881    ///
882    /// [`Handle`]: crate::context::Handle
883    /// [`RwArea`]: crate::ui::RwArea
884    /// [`Area`]: crate::ui::Area
885    pub fn try_write_many<'p, Tup: WriteableTuple<'p, impl std::any::Any>>(
886        &'p mut self,
887        tup: Tup,
888    ) -> Result<Tup::Return, crate::text::Text> {
889        tup.write_all(self)
890            .ok_or_else(|| crate::text::txt!("Tried writing to the same data multiple times"))
891    }
892}
893
894/// A tuple of [`WriteableData`], used for writing to many things at
895/// once
896#[doc(hidden)]
897pub trait WriteableTuple<'p, _Dummy> {
898    type Return;
899
900    #[doc(hidden)]
901    fn write_all(self, pa: &'p mut Pass) -> Option<Self::Return>;
902
903    #[doc(hidden)]
904    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>>;
905}
906
907macro_rules! implWriteableTuple {
908    ($(($tup:ident, $dummy:ident)),+) => {
909        #[allow(non_snake_case)]
910        impl<'p, $($tup),+, $($dummy),+> WriteableTuple<'p, ($(&mut $dummy),+)> for ($($tup),+)
911        where
912            $($tup: WriteableTuple<'p, $dummy>),+
913        {
914            type Return = ($($tup::Return),+);
915
916            fn write_all(self, _: &'p mut Pass) -> Option<Self::Return> {
917                if self.state_ptrs().into_iter().enumerate().any(|(lhs, i)| {
918                    self.state_ptrs()
919                        .into_iter()
920                        .enumerate()
921                        .any(|(rhs, j)| lhs == rhs && i != j)
922                }) {
923                    return None;
924                }
925
926                let ($($tup),+) = self;
927
928				/// SAFETY: The ptrs are already verifiably not pointing to the same data.
929                static PASS: Pass = unsafe { Pass::new() };
930
931                Some(($(
932                    $tup.write_all(
933                        unsafe { (&raw const PASS as *mut Pass).as_mut() }.unwrap()
934                    )
935                    .unwrap()
936                ),+))
937            }
938
939            fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
940                let ($($tup),+) = self;
941
942                implWriteableTuple!(@chain $($tup),+)
943            }
944        }
945    };
946
947    (@chain $tup:ident $(, $rest:ident)*) => {
948        $tup.state_ptrs().into_iter().chain(implWriteableTuple!(@chain $($rest),*))
949    };
950    (@chain ) => { [] };
951}
952
953impl<'p, Data, T> WriteableTuple<'p, (&mut T,)> for &'p Data
954where
955    Data: WriteableData<'p, T>,
956    T: ?Sized + 'p,
957{
958    type Return = &'p mut T;
959
960    fn write_all(self, pa: &'p mut Pass) -> Option<Self::Return> {
961        Some(self.write_one_of_many(pa))
962    }
963
964    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
965        [self.cur_state_ptr()]
966    }
967}
968
969implWriteableTuple!((D0, T0), (D1, T1));
970implWriteableTuple!((D0, T0), (D1, T1), (D2, T2));
971implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3));
972implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4));
973implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5));
974#[rustfmt::skip]
975implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6));
976#[rustfmt::skip]
977implWriteableTuple!((D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7));
978#[rustfmt::skip]
979implWriteableTuple!(
980    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8)
981);
982#[rustfmt::skip]
983implWriteableTuple!(
984    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
985    (D9, T9)
986);
987#[rustfmt::skip]
988implWriteableTuple!(
989    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
990    (D9, T9), (D10, T10)
991);
992#[rustfmt::skip]
993implWriteableTuple!(
994    (D0, T0), (D1, T1), (D2, T2), (D3, T3), (D4, T4), (D5, T5), (D6, T6), (D7, T7) , (D8, T8),
995    (D9, T9), (D10, T10), (D11, T11)
996);
997
998impl<'p, const N: usize, Tup, Dummy> WriteableTuple<'p, [Dummy; N]> for [Tup; N]
999where
1000    Tup: WriteableTuple<'p, Dummy> + 'p,
1001{
1002    type Return = [Tup::Return; N];
1003
1004    fn write_all(self, _: &'p mut Pass) -> Option<Self::Return> {
1005        if self.state_ptrs().into_iter().enumerate().any(|(lhs, i)| {
1006            self.state_ptrs()
1007                .into_iter()
1008                .enumerate()
1009                .any(|(rhs, j)| lhs == rhs && i != j)
1010        }) {
1011            return None;
1012        }
1013
1014        static PASS: Pass = unsafe { Pass::new() };
1015
1016        Some(self.map(|tup| {
1017            let pa = &raw const PASS as *mut Pass;
1018            tup.write_all(unsafe { pa.as_mut() }.unwrap()).unwrap()
1019        }))
1020    }
1021
1022    fn state_ptrs(&self) -> impl IntoIterator<Item = CurStatePtr<'_>> {
1023        self.iter().flat_map(|tup| tup.state_ptrs())
1024    }
1025}
1026
1027/// A trait for writing to multiple [`RwData`]-like structs at once
1028#[doc(hidden)]
1029pub trait WriteableData<'p, T: ?Sized + 'p>: InnerWriteableData {
1030    /// Just like [`RwData::write`]
1031    #[doc(hidden)]
1032    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T;
1033
1034    /// A pointer for [`Pass::try_write_many`]
1035    #[doc(hidden)]
1036    fn cur_state_ptr(&self) -> CurStatePtr<'_>;
1037}
1038
1039impl<'p, T: ?Sized + 'p> WriteableData<'p, T> for RwData<T> {
1040    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T {
1041        self.write(pa)
1042    }
1043
1044    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1045        CurStatePtr(&self.cur_state)
1046    }
1047}
1048
1049impl<'p, T: Default> WriteableData<'p, T> for BulkDataWriter<T> {
1050    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut T {
1051        self.write(pa)
1052    }
1053
1054    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1055        CurStatePtr(&self.data.cur_state)
1056    }
1057}
1058
1059impl<'p, W: Widget> WriteableData<'p, W> for crate::context::Handle<W> {
1060    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut W {
1061        self.write(pa)
1062    }
1063
1064    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1065        CurStatePtr(&self.widget().cur_state)
1066    }
1067}
1068
1069impl<'p> WriteableData<'p, crate::ui::Area> for crate::ui::RwArea {
1070    fn write_one_of_many(&'p self, pa: &'p mut Pass) -> &'p mut crate::ui::Area {
1071        self.write(pa)
1072    }
1073
1074    fn cur_state_ptr(&self) -> CurStatePtr<'_> {
1075        CurStatePtr(&self.0.cur_state)
1076    }
1077}
1078
1079/// To prevent outside implementations
1080trait InnerWriteableData {}
1081impl<T: ?Sized> InnerWriteableData for RwData<T> {}
1082impl<T: Default> InnerWriteableData for BulkDataWriter<T> {}
1083impl<W: Widget> InnerWriteableData for crate::context::Handle<W> {}
1084impl InnerWriteableData for crate::ui::RwArea {}
1085
1086/// A struct for comparison when calling [`Pass::write_many`]
1087#[doc(hidden)]
1088#[derive(Clone, Copy)]
1089pub struct CurStatePtr<'p>(&'p Arc<AtomicUsize>);
1090
1091impl std::cmp::PartialEq for CurStatePtr<'_> {
1092    fn eq(&self, other: &Self) -> bool {
1093        Arc::ptr_eq(self.0, other.0)
1094    }
1095}