rooting_forms/
impl_macroutil.rs

1use 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}