Skip to main content

freya_core/
helpers.rs

1use std::{
2    any::Any,
3    hash::{
4        Hash,
5        Hasher,
6    },
7    rc::Rc,
8};
9
10use rustc_hash::FxHasher;
11
12use crate::{
13    diff_key::DiffKey,
14    element::Element,
15};
16
17#[cfg(feature = "test")]
18pub fn from_fn_captured<T: Fn() -> Element + 'static>(comp: T) -> Element {
19    use std::rc::Rc;
20
21    use crate::diff_key::DiffKey;
22
23    Element::Component {
24        key: DiffKey::None,
25        #[cfg(feature = "hotreload")]
26        comp: Rc::new(move |_| crate::hotreload::subsecond::HotFn::current(&comp).call(())),
27        #[cfg(not(feature = "hotreload"))]
28        comp: Rc::new(move |_| comp()),
29        props: Rc::new(()),
30    }
31}
32
33#[cfg(feature = "test")]
34pub fn from_fn_standalone(comp: fn() -> Element) -> Element {
35    Element::Component {
36        key: comp.into(),
37        #[cfg(feature = "hotreload")]
38        comp: Rc::new(move |_| crate::hotreload::subsecond::HotFn::current(comp).call(())),
39        #[cfg(not(feature = "hotreload"))]
40        comp: Rc::new(move |_| comp()),
41        props: Rc::new(()),
42    }
43}
44
45#[cfg(feature = "test")]
46pub fn from_fn_standalone_borrowed<P: 'static + PartialEq>(
47    props: P,
48    comp: fn(&P) -> Element,
49) -> Element {
50    Element::Component {
51        key: comp.into(),
52        #[cfg(feature = "hotreload")]
53        comp: Rc::new(move |props| {
54            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
55            crate::hotreload::subsecond::HotFn::current(comp).call((props,))
56        }),
57        #[cfg(not(feature = "hotreload"))]
58        comp: Rc::new(move |props| {
59            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
60            comp(props)
61        }),
62        props: Rc::new(props),
63    }
64}
65
66/// Create a component instance from a given `Key`, `Props` and `Render` function.
67pub fn from_fn<P: PartialEq + 'static>(
68    key: impl Hash,
69    props: P,
70    comp: impl Fn(&P) -> Element + Clone + 'static,
71) -> Element {
72    let mut hasher = FxHasher::default();
73    key.hash(&mut hasher);
74    Element::Component {
75        key: DiffKey::U64(hasher.finish()),
76        #[cfg(feature = "hotreload")]
77        comp: Rc::new(move |props| {
78            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
79            crate::hotreload::subsecond::HotFn::current(comp.clone()).call((props,))
80        }),
81        #[cfg(not(feature = "hotreload"))]
82        comp: Rc::new(move |props| {
83            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
84            comp(props)
85        }),
86        props: Rc::new(props),
87    }
88}
89
90/// Create a component instance from a given `Key`, `Props` and `Render` function. Similar to [from_fn] but instead gives owned props.
91pub fn from_fn_owned<P: PartialEq + Clone + 'static>(
92    key: impl Hash,
93    props: P,
94    comp: impl Fn(P) -> Element + Clone + 'static,
95) -> Element {
96    let mut hasher = FxHasher::default();
97    key.hash(&mut hasher);
98    Element::Component {
99        key: DiffKey::U64(hasher.finish()),
100        #[cfg(feature = "hotreload")]
101        comp: Rc::new(move |props| {
102            let props = (&*props as &dyn Any).downcast_ref::<P>().cloned().unwrap();
103            crate::hotreload::subsecond::HotFn::current(comp.clone()).call((props,))
104        }),
105        #[cfg(not(feature = "hotreload"))]
106        comp: Rc::new(move |props| {
107            let props = (&*props as &dyn Any).downcast_ref::<P>().cloned().unwrap();
108            comp(props)
109        }),
110        props: Rc::new(props),
111    }
112}
113
114pub fn from_fn_standalone_borrowed_keyed<K: Hash, P: 'static + PartialEq>(
115    key: K,
116    props: P,
117    comp: fn(&P) -> Element,
118) -> Element {
119    let mut hasher = FxHasher::default();
120    key.hash(&mut hasher);
121    Element::Component {
122        key: DiffKey::U64(hasher.finish()),
123        #[cfg(feature = "hotreload")]
124        comp: Rc::new(move |props| {
125            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
126            crate::hotreload::subsecond::HotFn::current(comp).call((props,))
127        }),
128        #[cfg(not(feature = "hotreload"))]
129        comp: Rc::new(move |props| {
130            let props = (&*props as &dyn Any).downcast_ref::<P>().unwrap();
131            comp(props)
132        }),
133        props: Rc::new(props),
134    }
135}