rooting_forms/
impl_macroutil.rs1use std::{
2 cell::RefCell,
3 marker::PhantomData,
4 rc::Rc,
5};
6use crate::{
7 FormElements,
8 FormState,
9 FormWith,
10};
11
12struct LazySubform_<C, T: FormWith<C>> {
13 data: RefCell<Option<Rc<(FormElements, Box<dyn FormState<T>>)>>>,
14 initializer: Box<dyn Fn() -> (FormElements, Box<dyn FormState<T>>)>,
15 _pd: PhantomData<C>,
16}
17
18pub struct LazySubform<C, T: FormWith<C>>(Rc<LazySubform_<C, T>>);
19
20impl<C, T: FormWith<C>> Clone for LazySubform<C, T> {
21 fn clone(&self) -> Self {
22 return Self(self.0.clone());
23 }
24}
25
26impl<C, T: FormWith<C>> LazySubform<C, T> {
27 pub fn new(f: impl 'static + Fn() -> (FormElements, Box<dyn FormState<T>>)) -> Self {
28 return Self(Rc::new(LazySubform_ {
29 data: RefCell::new(None),
30 initializer: Box::new(f),
31 _pd: Default::default(),
32 }));
33 }
34
35 fn init(&self) -> Rc<(FormElements, Box<dyn FormState<T>>)> {
36 return self.0.data.borrow_mut().get_or_insert_with(|| Rc::new((self.0.initializer)())).clone();
37 }
38
39 pub fn elements(&self) -> Vec<rooting::El> {
40 let init = self.init();
41 let mut out = vec![];
42 if let Some(error) = &init.0.error {
43 out.push(error.clone());
44 }
45 out.extend(init.0.elements.clone());
46 return out;
47 }
48
49 pub fn parse(&self) -> Result<T, ()> {
50 return self.init().1.parse();
51 }
52}
53
54pub struct VariantUnitFormState<C: 'static + Clone, T: FormWith<C>>(pub fn() -> T, pub PhantomData<C>);
55
56impl<C: 'static + Clone, T: FormWith<C>> VariantUnitFormState<C, T> {
57 pub fn new(f: fn() -> T) -> Self {
58 return Self(f, Default::default());
59 }
60}
61
62impl<C: 'static + Clone, T: FormWith<C>> FormState<T> for VariantUnitFormState<C, T> {
63 fn parse(&self) -> Result<T, ()> {
64 return Ok((self.0)());
65 }
66}
67
68pub struct VariantWrapFormState<C: 'static + Clone, V: FormWith<C>, T: FormWith<C>> {
69 inner: Box<dyn FormState<V>>,
70 wrap: fn(V) -> T,
71 _pd: PhantomData<C>,
72}
73
74impl<C: 'static + Clone, V: FormWith<C>, T: FormWith<C>> VariantWrapFormState<C, V, T> {
75 pub fn new(inner: Box<dyn FormState<V>>, wrap: fn(V) -> T) -> Self {
76 return Self {
77 inner: inner,
78 wrap,
79 _pd: Default::default(),
80 };
81 }
82}
83
84impl<C: 'static + Clone, V: FormWith<C>, T: FormWith<C>> FormState<T> for VariantWrapFormState<C, V, T> {
85 fn parse(&self) -> Result<T, ()> {
86 return Ok((self.wrap)(self.inner.parse()?));
87 }
88}