yew_stdweb/html/
conversion.rs

1use super::{Component, NodeRef, Scope};
2use std::{borrow::Cow, rc::Rc};
3
4/// Marker trait for types that the [`html!`] macro may clone implicitly.
5pub trait ImplicitClone: Clone {}
6
7// this is only implemented because there's no way to avoid cloning this value
8impl ImplicitClone for Cow<'static, str> {}
9
10impl<T: ImplicitClone> ImplicitClone for Option<T> {}
11impl<T> ImplicitClone for Rc<T> {}
12
13impl ImplicitClone for NodeRef {}
14impl<Comp: Component> ImplicitClone for Scope<Comp> {}
15// TODO there are still a few missing like AgentScope
16
17/// A trait similar to `Into<T>` which allows conversion to a value of a `Properties` struct.
18pub trait IntoPropValue<T> {
19    /// Convert `self` to a value of a `Properties` struct.
20    fn into_prop_value(self) -> T;
21}
22
23impl<T> IntoPropValue<T> for T {
24    fn into_prop_value(self) -> T {
25        self
26    }
27}
28impl<T> IntoPropValue<T> for &T
29where
30    T: ImplicitClone,
31{
32    fn into_prop_value(self) -> T {
33        self.clone()
34    }
35}
36
37impl<T> IntoPropValue<Option<T>> for T {
38    fn into_prop_value(self) -> Option<T> {
39        Some(self)
40    }
41}
42impl<T> IntoPropValue<Option<T>> for &T
43where
44    T: ImplicitClone,
45{
46    fn into_prop_value(self) -> Option<T> {
47        Some(self.clone())
48    }
49}
50
51macro_rules! impl_into_prop {
52    (|$value:ident: $from_ty:ty| -> $to_ty:ty { $conversion:expr }) => {
53        // implement V -> T
54        impl IntoPropValue<$to_ty> for $from_ty {
55            fn into_prop_value(self) -> $to_ty {
56                let $value = self;
57                $conversion
58            }
59        }
60        // implement V -> Option<T>
61        impl IntoOptPropValue<$to_ty> for $from_ty {
62            fn into_opt_prop_value(self) -> Option<$to_ty> {
63                let $value = self;
64                Some({ $conversion })
65            }
66        }
67        // implement Option<V> -> Option<T>
68        impl IntoOptPropValue<$to_ty> for Option<$from_ty> {
69            fn into_opt_prop_value(self) -> Option<$to_ty> {
70                self.map(IntoPropValue::into_prop_value)
71            }
72        }
73    };
74}
75
76// implemented with literals in mind
77impl_into_prop!(|value: &'static str| -> String { value.to_owned() });
78
79impl_into_prop!(|value: &'static str| -> Cow<'static, str> { Cow::Borrowed(value) });
80impl_into_prop!(|value: String| -> Cow<'static, str> { Cow::Owned(value) });
81
82/// A trait similar to `Into<Option<T>>` which allows conversion to an optional value of a
83/// `Properties` struct.
84pub trait IntoOptPropValue<T> {
85    /// Convert `self` to an optional value of a `Properties` struct.
86    fn into_opt_prop_value(self) -> Option<T>;
87}
88impl<T, V> IntoOptPropValue<V> for T
89where
90    T: IntoPropValue<Option<V>>,
91{
92    fn into_opt_prop_value(self) -> Option<V> {
93        self.into_prop_value()
94    }
95}