From 89390041b3d1404fcb036a07afeaab6e9ec55477 Mon Sep 17 00:00:00 2001 From: Wayne Van Son Date: Mon, 4 Sep 2023 10:19:20 +1000 Subject: [PATCH] refactor: impl iso for optics better --- packages/uischema/src/optics.rs | 168 ------------------- packages/uischema/src/optics/iso.rs | 190 ++++++++++++++++++++++ packages/uischema/src/optics/lens.rs | 2 + packages/uischema/src/optics/mod.rs | 5 + packages/uischema/src/optics/optional.rs | 2 + packages/uischema/src/optics/prism.rs | 2 + packages/uischema/src/optics/traversal.rs | 2 + packages/uischema/src/output.rs | 16 +- 8 files changed, 210 insertions(+), 177 deletions(-) delete mode 100644 packages/uischema/src/optics.rs create mode 100644 packages/uischema/src/optics/iso.rs create mode 100644 packages/uischema/src/optics/lens.rs create mode 100644 packages/uischema/src/optics/mod.rs create mode 100644 packages/uischema/src/optics/optional.rs create mode 100644 packages/uischema/src/optics/prism.rs create mode 100644 packages/uischema/src/optics/traversal.rs diff --git a/packages/uischema/src/optics.rs b/packages/uischema/src/optics.rs deleted file mode 100644 index 6db5688..0000000 --- a/packages/uischema/src/optics.rs +++ /dev/null @@ -1,168 +0,0 @@ -pub type Get = Box A>; -pub type Apply = Box S>; -pub type Set = Box S>; -pub type GetOption = Box Option>; - -pub struct Iso { - get: Get, - apply: Apply, -} - -impl Iso { - pub fn id() -> Self { - Self { - get: Box::new(|s| s), - apply: Box::new(|s| s), - } - } -} - -impl Iso -where - S: 'static, - A: 'static, -{ - pub fn map_invariant( - self, - covariant: impl Fn(A) -> B + 'static, - contravariant: impl Fn(B) -> A + 'static, - ) -> Iso { - let Self { get, apply } = self; - Iso { - get: Box::new(move |s| covariant(get(s))), - apply: Box::new(move |b| apply(contravariant(b))), - } - } - - pub fn lens(self) -> Lens { - let Self { get, apply } = self; - Lens { - get, - set: Box::new(move |_s, a| apply(a)), - } - } -} - -pub struct Lens { - get: Get, - set: Set, -} - -impl Lens { - pub fn id() -> Self { - Self { - get: Box::new(|s| s), - set: Box::new(|_s, a| a), - } - } -} - -impl Lens -where - S: 'static, - A: 'static, -{ - pub fn map_invariant( - self, - covariant: impl Fn(A) -> B + 'static, - contravariant: impl Fn(B) -> A + 'static, - ) -> Lens { - let Self { get, set } = self; - Lens { - get: Box::new(move |s| covariant(get(s))), - set: Box::new(move |s, b| set(s, contravariant(b))), - } - } - - pub fn prism(self) -> Prism { - let Self { get, set } = self; - Prism { - get_option: Box::new(move |s| Some(get(s))), - set, - } - } -} - -pub struct Prism { - get_option: GetOption, - set: Set, -} - -impl Prism { - pub fn id() -> Self { - Self { - get_option: Box::new(|s| Some(s)), - set: Box::new(|_s, a| a), - } - } -} - -impl Prism -where - S: 'static, - A: 'static, -{ - pub fn map_invariant( - self, - covariant: impl Fn(A) -> B + 'static, - contravariant: impl Fn(B) -> A + 'static, - ) -> Prism { - let Self { get_option, set } = self; - Prism { - get_option: Box::new(move |s| get_option(s).map(&covariant)), - set: Box::new(move |s, b| set(s, contravariant(b))), - } - } - - pub fn optional(self) -> Optional { - let Self { get_option, set } = self; - Optional { - get_option, - replace: set, - } - } -} - -pub struct Optional { - get_option: GetOption, - replace: Set, -} - -impl Optional { - pub fn id() -> Self { - Self { - get_option: Box::new(|s| Some(s)), - replace: Box::new(|_s, a| a), - } - } -} - -impl Optional -where - S: 'static, - A: 'static, -{ - pub fn map_invariant( - self, - covariant: impl Fn(A) -> B + 'static, - contravariant: impl Fn(B) -> A + 'static, - ) -> Optional { - let Self { - get_option, - replace, - } = self; - Optional { - get_option: Box::new(move |s| get_option(s).map(&covariant)), - replace: Box::new(move |s, b| replace(s, contravariant(b))), - } - } -} - -pub trait Traversal { - type Traversable: Iterator; - - fn get_all(s: S) -> Self::Traversable; - fn modify_all(f: F) -> fn(S) -> S - where - F: Fn(A) -> A; -} diff --git a/packages/uischema/src/optics/iso.rs b/packages/uischema/src/optics/iso.rs new file mode 100644 index 0000000..41a8652 --- /dev/null +++ b/packages/uischema/src/optics/iso.rs @@ -0,0 +1,190 @@ +pub mod traits { + pub trait IsoRef { + type Source; + type Target; + + fn get_ref(&self, source: Self::Source) -> Self::Target; + } + + pub trait IsoMut: IsoRef { + fn get_mut(&mut self, source: Self::Source) -> Self::Target; + } + + pub trait Iso: IsoMut { + fn get(self, source: Self::Source) -> Self::Target; + } +} + +pub mod impls { + use super::traits::{IsoMut, IsoRef}; + use std::marker::PhantomData; + + #[derive(Debug)] + pub struct IsoId { + phantom: PhantomData, + } + + impl IsoId { + pub fn new() -> Self { + Self::default() + } + + pub fn map(self, closure: G) -> Map + where + G: Fn(S) -> B, + { + Map { + iso: self, + f: closure, + } + } + + pub fn compose(self, second: V) -> IsoCompose + where + V: IsoRef, + { + IsoCompose { + first: self, + second, + } + } + } + + impl Default for IsoId { + fn default() -> Self { + Self { + phantom: PhantomData, + } + } + } + + impl IsoRef for IsoId { + type Source = S; + type Target = S; + + fn get_ref(&self, source: Self::Source) -> Self::Target { + source + } + } + + impl IsoMut for IsoId { + fn get_mut(&mut self, source: Self::Source) -> Self::Target { + self.get_ref(source) + } + } + + pub struct Map { + iso: I, + f: F, + } + + impl Map + where + I: IsoRef, + { + pub fn map(self, closure: G) -> Map + where + G: Fn(A) -> B, + { + Map { + iso: self, + f: closure, + } + } + + pub fn compose(self, second: V) -> IsoCompose + where + V: IsoRef, + { + IsoCompose { + first: self, + second, + } + } + } + + impl IsoRef for Map + where + I: IsoRef, + F: Fn(A) -> B, + { + type Source = I::Source; + type Target = B; + + fn get_ref(&self, source: Self::Source) -> Self::Target { + let a = self.iso.get_ref(source); + (self.f)(a) + } + } + + impl IsoMut for Map + where + I: IsoRef, + F: Fn(A) -> B, + { + fn get_mut(&mut self, source: Self::Source) -> Self::Target { + let a = self.iso.get_ref(source); + (self.f)(a) + } + } + + pub struct IsoCompose { + first: I, + second: V, + } + + impl IsoCompose + where + I: IsoRef, + { + pub fn map(self, closure: G) -> Map + where + G: Fn(A) -> B, + { + Map { + iso: self, + f: closure, + } + } + } + + impl IsoCompose + where + V: IsoRef, + { + pub fn compose(self, second: W) -> IsoCompose + where + W: IsoRef, + { + IsoCompose { + first: self, + second, + } + } + } + + impl IsoRef for IsoCompose + where + I: IsoRef, + V: IsoRef, + { + type Source = I::Source; + type Target = V::Target; + + fn get_ref(&self, source: Self::Source) -> Self::Target { + let a = self.first.get_ref(source); + self.second.get_ref(a) + } + } + + impl IsoMut for IsoCompose + where + I: IsoMut, + V: IsoMut, + { + fn get_mut(&mut self, source: Self::Source) -> Self::Target { + let a = self.first.get_ref(source); + self.second.get_ref(a) + } + } +} diff --git a/packages/uischema/src/optics/lens.rs b/packages/uischema/src/optics/lens.rs new file mode 100644 index 0000000..0de9a6b --- /dev/null +++ b/packages/uischema/src/optics/lens.rs @@ -0,0 +1,2 @@ +pub mod traits {} +pub mod impls {} diff --git a/packages/uischema/src/optics/mod.rs b/packages/uischema/src/optics/mod.rs new file mode 100644 index 0000000..0d649af --- /dev/null +++ b/packages/uischema/src/optics/mod.rs @@ -0,0 +1,5 @@ +mod iso; +mod lens; +mod optional; +mod prism; +mod traversal; diff --git a/packages/uischema/src/optics/optional.rs b/packages/uischema/src/optics/optional.rs new file mode 100644 index 0000000..0de9a6b --- /dev/null +++ b/packages/uischema/src/optics/optional.rs @@ -0,0 +1,2 @@ +pub mod traits {} +pub mod impls {} diff --git a/packages/uischema/src/optics/prism.rs b/packages/uischema/src/optics/prism.rs new file mode 100644 index 0000000..0de9a6b --- /dev/null +++ b/packages/uischema/src/optics/prism.rs @@ -0,0 +1,2 @@ +pub mod traits {} +pub mod impls {} diff --git a/packages/uischema/src/optics/traversal.rs b/packages/uischema/src/optics/traversal.rs new file mode 100644 index 0000000..0de9a6b --- /dev/null +++ b/packages/uischema/src/optics/traversal.rs @@ -0,0 +1,2 @@ +pub mod traits {} +pub mod impls {} diff --git a/packages/uischema/src/output.rs b/packages/uischema/src/output.rs index fa5286d..5cbf220 100644 --- a/packages/uischema/src/output.rs +++ b/packages/uischema/src/output.rs @@ -1,19 +1,17 @@ // first thing I think of is JS values go in, js values come out // a hashmap -use std::collections::HashMap; -use wasm_bindgen::JsValue; -use crate::{optics::Optional}; +use std::collections::HashMap; // #/**/* -pub struct Scope(String); // so we send this map back to the client, how will the client like that? -pub struct OptionalsByScope(HashMap>); +// send traversal fns +pub struct OptionalsByScope(HashMap); -// need Schema to get the scopes -// Validate Schema against UISchema -// fn UISchema -> (Scope, Value) -> Data -> Data -// fn (UISchema -> Scopes) -> (Scope, Value) -> Data -> Data +enum Step { + Object(String), + Array, +}