From 0fbe50549e5bc69f53ed488c4d70c2c9f929e615 Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Tue, 20 May 2025 18:50:17 +0100 Subject: [PATCH] Added `dynatos_loadable::{LoadableBorrow, LoadableBorrowMut, SignalBorrowLoadable, SignalBorrowMutLoadable}`. --- dynatos-loadable/src/lib.rs | 2 + dynatos-loadable/src/loadable_borrow.rs | 149 ++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 dynatos-loadable/src/loadable_borrow.rs diff --git a/dynatos-loadable/src/lib.rs b/dynatos-loadable/src/lib.rs index bef8ab0..6090e51 100644 --- a/dynatos-loadable/src/lib.rs +++ b/dynatos-loadable/src/lib.rs @@ -5,10 +5,12 @@ // Modules pub mod loadable; +pub mod loadable_borrow; pub mod loadable_signal; // Exports pub use self::{ loadable::{IntoLoaded, IteratorLoadableExt, Loadable}, + loadable_borrow::{LoadableBorrow, LoadableBorrowMut, SignalBorrowLoadable, SignalBorrowMutLoadable}, loadable_signal::LoadableSignal, }; diff --git a/dynatos-loadable/src/loadable_borrow.rs b/dynatos-loadable/src/loadable_borrow.rs new file mode 100644 index 0000000..44c1c8f --- /dev/null +++ b/dynatos-loadable/src/loadable_borrow.rs @@ -0,0 +1,149 @@ +//! Loadable borrow + +// Imports +use { + crate::Loadable, + core::{ + fmt, + ops::{Deref, DerefMut}, + }, + dynatos_reactive::{SignalBorrow, SignalBorrowMut}, +}; + +/// Loadable borrow. +/// +/// Allows transforming a signal borrow `Borrow>` into a +/// `Loadable, E>`. +#[derive(Clone, Copy)] +pub struct LoadableBorrow(B); + +impl fmt::Debug for LoadableBorrow +where + B: Deref>, + T: fmt::Debug, + E: 'static, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl Deref for LoadableBorrow +where + B: Deref>, + E: 'static, +{ + type Target = T; + + #[track_caller] + fn deref(&self) -> &Self::Target { + match &*self.0 { + Loadable::Loaded(value) => value, + _ => panic!("Loadable should be loaded"), + } + } +} + +/// Extension trait to borrow with a [`LoadableBorrow`] +#[extend::ext(name = SignalBorrowLoadable)] +pub impl S +where + S: for<'a> SignalBorrow: Deref>>, + E: Clone, +{ + /// Borrows this signal as a `Loadable, E>` + fn borrow_loadable(&self) -> Loadable>, E> { + let borrow = self.borrow(); + match &*borrow { + Loadable::Empty => Loadable::Empty, + Loadable::Err(err) => Loadable::Err(err.clone()), + Loadable::Loaded(_) => Loadable::Loaded(LoadableBorrow(borrow)), + } + } + + /// Borrows this signal as a `Loadable, E>`, without adding a dependency + fn borrow_loadable_raw(&self) -> Loadable>, E> { + let borrow = self.borrow_raw(); + match &*borrow { + Loadable::Empty => Loadable::Empty, + Loadable::Err(err) => Loadable::Err(err.clone()), + Loadable::Loaded(_) => Loadable::Loaded(LoadableBorrow(borrow)), + } + } +} + +/// Loadable mutable borrow. +/// +/// Allows transforming a signal mutable borrow `Borrow>` into a +/// `Loadable, E>`. +#[derive(Clone, Copy)] +pub struct LoadableBorrowMut(B); + +impl fmt::Debug for LoadableBorrowMut +where + B: Deref>, + T: fmt::Debug, + E: 'static, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl Deref for LoadableBorrowMut +where + B: Deref>, + E: 'static, +{ + type Target = T; + + #[track_caller] + fn deref(&self) -> &Self::Target { + match &*self.0 { + Loadable::Loaded(value) => value, + _ => panic!("Loadable should be loaded"), + } + } +} + +impl DerefMut for LoadableBorrowMut +where + B: DerefMut>, + E: 'static, +{ + #[track_caller] + fn deref_mut(&mut self) -> &mut Self::Target { + match &mut *self.0 { + Loadable::Loaded(value) => value, + _ => panic!("Loadable should be loaded"), + } + } +} + +/// Extension trait to borrow with a [`LoadableBorrowMut`] +#[extend::ext(name = SignalBorrowMutLoadable)] +pub impl S +where + S: for<'a> SignalBorrowMut: DerefMut>>, + E: Clone, +{ + /// Borrows this signal as a `Loadable, E>` + fn borrow_mut_loadable(&self) -> Loadable>, E> { + let borrow = self.borrow_mut(); + match &*borrow { + Loadable::Empty => Loadable::Empty, + Loadable::Err(err) => Loadable::Err(err.clone()), + Loadable::Loaded(_) => Loadable::Loaded(LoadableBorrow(borrow)), + } + } + + /// Borrows this signal as a `Loadable, E>`, without adding a dependency + fn borrow_mut_loadable_raw(&self) -> Loadable>, E> { + let borrow = self.borrow_mut_raw(); + match &*borrow { + Loadable::Empty => Loadable::Empty, + Loadable::Err(err) => Loadable::Err(err.clone()), + Loadable::Loaded(_) => Loadable::Loaded(LoadableBorrow(borrow)), + } + } +}