1mod email;
2mod non_empty_string;
3mod phone;
4mod date_time;
5mod date;
6mod time;
7mod accept;
8mod iban;
9mod postal_code;
10mod field;
11mod regional_field;
12
13pub use email::*;
14pub use non_empty_string::*;
15pub use phone::*;
16pub use date_time::*;
17pub use date::*;
18pub use time::*;
19pub use accept::*;
20pub use iban::*;
21pub use postal_code::*;
22pub use field::*;
23pub use regional_field::*;
24
25use num_bigint::BigInt;
26use num_rational::BigRational;
27
28use leptos::*;
29use std::error::Error;
30use std::fmt::{Debug, Display};
31use std::rc::Rc;
32use std::str::FromStr;
33
34#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
36pub struct Optional<T>(Option<T>);
37
38impl<T> FromStr for Optional<T>
39where
40 T: FromStr,
41{
42 type Err = <T as FromStr>::Err;
43
44 fn from_str(s: &str) -> Result<Self, Self::Err> {
45 if s.is_empty() {
46 return Ok(Optional(None));
47 }
48 Ok(Optional(T::from_str(s).ok()))
49 }
50}
51
52impl<T> Display for Optional<T>
53where
54 T: Display,
55{
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 if let Some(value) = &self.0 {
58 write!(f, "{}", value)
59 } else {
60 write!(f, "")
61 }
62 }
63}
64
65macro_rules! impl_datatypes {
66 ( $( $t:ty where $($name:literal $( : $val:literal)? ),* $(,)? );* $(;)? ) => {
67 $(
68 impl Datatype for $t {
69 type Inner = $t;
70 type Error = <$t as FromStr>::Err;
71
72 fn validate(input: $t) -> Result<Self, <$t as FromStr>::Err> {
73 Ok(input)
74 }
75
76 fn attributes() -> Vec<(&'static str, Attribute)> {
77 vec![ $( ($name, {
78 #[allow(unused)]
79 let mut v = Attribute::Bool(true);
80 $( v = Attribute::String(Oco::Borrowed($val)); )?
81 v
82 }) ),* ]
83 }
84 }
85 )*
86 };
87}
88
89impl_datatypes! {
90 u8 where "type": "number", "step": "1", "min": "0", "max": "255", "required";
91 Optional<u8> where "type": "number", "step": "1", "min": "0", "max": "255";
92 u16 where "type": "number", "step": "1", "min": "0", "max": "65535", "required";
93 Optional<u16> where "type": "number", "step": "1", "min": "0", "max": "65535";
94 u32 where "type": "number", "step": "1", "min": "0", "max": "4294967295", "required";
95 Optional<u32> where "type": "number", "step": "1", "min": "0", "max": "4294967295";
96 u64 where "type": "number", "step": "1", "min": "0", "max": "18446744073709551615", "required";
97 Optional<u64> where "type": "number", "step": "1", "min": "0", "max": "18446744073709551615";
98 u128 where "type": "number", "step": "1", "min": "0", "max": "340282366920938463463374607431768211455", "required";
99 Optional<u128> where "type": "number", "step": "1", "min": "0", "max": "340282366920938463463374607431768211455";
100 i8 where "type": "number", "step": "1", "min": "-128", "max": "127", "required";
101 Optional<i8> where "type": "number", "step": "1", "min": "-128", "max": "127";
102 i16 where "type": "number", "step": "1", "min": "-32768", "max": "32767", "required";
103 Optional<i16> where "type": "number", "step": "1", "min": "-32768", "max": "32767";
104 i32 where "type": "number", "step": "1", "min": "-2147483648", "max": "2147483647", "required";
105 Optional<i32> where "type": "number", "step": "1", "min": "-2147483648", "max": "2147483647";
106 i64 where "type": "number", "step": "1", "min": "-9223372036854775808", "max": "9223372036854775807", "required";
107 Optional<i64> where "type": "number", "step": "1", "min": "-9223372036854775808", "max": "9223372036854775807";
108 i128 where "type": "number", "step": "1", "min": "-170141183460469231731687303715884105728", "max": "170141183460469231731687303715884105727", "required";
109 Optional<i128> where "type": "number", "step": "1", "min": "-170141183460469231731687303715884105728", "max": "170141183460469231731687303715884105727";
110 String where "type": "text";
111 BigInt where "type": "number", "step": "1", "required";
112 Optional<BigInt> where "type": "number", "step": "1";
113 BigRational where "type": "number", "required";
114 Optional<BigRational> where "type": "number";
115 DateTime where "type": "datetime-local", "required";
116 Optional<DateTime> where "type": "datetime-local";
117 Date where "type": "date", "required";
118 Optional<Date> where "type": "date";
119 Time where "type": "time", "required";
120 Optional<Time> where "type": "time";
121 bool where "type": "checkbox";
122}
123
124#[macro_export]
126macro_rules! impl_datatype {
127 ($this:ty) => {
128 impl std::str::FromStr for $this {
129 type Err = <$this as $crate::Datatype>::Error;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 <$this as $crate::Datatype>::validate(<$this as $crate::Datatype>::Inner::from_str(s).map_err(<$this as $crate::Datatype>::Error::from)?)
133 }
134 }
135
136 impl<'de> serde::Deserialize<'de> for $this {
137 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
138 where
139 D: serde::Deserializer<'de>,
140 {
141 let value = <$this as $crate::Datatype>::Inner::deserialize(deserializer)?;
142 <$this as $crate::Datatype>::validate(value).map_err(serde::de::Error::custom)
143 }
144 }
145 };
146
147 ($this:ty where $generic:ident : $sat:ident) => {
148 impl<$generic> std::str::FromStr for $this
149 where
150 $generic: $sat
151 {
152 type Err = <$this as $crate::Datatype>::Error;
153
154 fn from_str(s: &str) -> Result<Self, Self::Err> {
155 <$this as $crate::Datatype>::validate(<$this as $crate::Datatype>::Inner::from_str(s).map_err(<$this as $crate::Datatype>::Error::from)?)
156 }
157 }
158
159 impl<'de, $generic> serde::Deserialize<'de> for $this
160 where
161 $generic: $sat
162 {
163 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
164 where
165 D: serde::Deserializer<'de>,
166 {
167 let value = <$this as $crate::Datatype>::Inner::deserialize(deserializer)?;
168 <$this as $crate::Datatype>::validate(value).map_err(serde::de::Error::custom)
169 }
170 }
171 };
172}
173
174pub trait Datatype: Clone + Display + Debug + Default + FromStr<Err = Self::Error> + Into<Self::Inner> + PartialEq + 'static {
177 type Inner: Datatype;
178 type Error: From<<Self::Inner as Datatype>::Error> + Error + Clone + PartialEq + 'static;
179
180 fn validate(input: Self::Inner) -> Result<Self, Self::Error>
182 where
183 Self: Sized;
184
185 fn attributes() -> Vec<(&'static str, Attribute)>;
187}
188
189#[derive(Clone)]
192pub(crate) struct TranslationProvider<T>(Rc<dyn Fn(T) -> TextProp>);
193
194
195pub fn provide_translation<F, T>(f: F)
198where
199 T: Clone + 'static,
200 F: Fn(T) -> TextProp + 'static,
201{
202 provide_context(TranslationProvider(Rc::new(f)));
203}
204
205pub fn expect_translation<T, F>(value: F) -> TextProp
206where
207 F: Into<MaybeSignal<T>>,
208 T: Clone + 'static,
209{
210 let value = value.into();
211 let translation_provider = expect_context::<TranslationProvider<T>>();
212 (move || translation_provider.0(value.get()).get()).into()
213}
214
215pub fn use_translation<T, F>(value: F) -> TextProp
216where
217 F: Into<MaybeSignal<T>>,
218 T: Clone + Display + 'static,
219{
220 let value = value.into();
221 let translation_provider: Option<TranslationProvider<T>> = use_context::<TranslationProvider<T>>();
222 if let Some(translation_provider) = translation_provider {
223 (move || translation_provider.0(value.get()).get()).into()
224 } else {
225 (move || format!("{}", value.get())).into()
226 }
227}