1use crate::tools::default_true;
2use crate::value::Value;
3use crate::Error;
4use serde::de::{self, MapAccess, Visitor};
5use serde::{Deserialize, Deserializer, Serialize};
6use std::fmt;
7use std::marker::PhantomData;
8use std::str::FromStr;
9
10const ERR_INVALID_RANGE_CONDITION: &str = "Invalid range condition";
11
12#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq)]
13#[serde(deny_unknown_fields)]
14pub struct Range {
15 #[serde(default)]
16 pub min: Option<f64>,
17 #[serde(default)]
18 pub max: Option<f64>,
19 #[serde(default = "default_true")]
20 pub min_eq: bool,
21 #[serde(default = "default_true")]
22 pub max_eq: bool,
23}
24
25impl Default for Range {
26 fn default() -> Self {
27 Self {
28 min: None,
29 max: None,
30 min_eq: true,
31 max_eq: true,
32 }
33 }
34}
35
36impl Range {
37 #[inline]
38 pub fn matches_any(&self) -> bool {
39 self.min.is_none() && self.max.is_none()
40 }
41 pub fn matches_value(&self, val: &Value) -> bool {
42 if let Ok(v) = TryInto::<f64>::try_into(val) {
43 self.matches(v)
44 } else {
45 false
46 }
47 }
48 pub fn matches(&self, val: f64) -> bool {
49 if let Some(min) = self.min {
50 if (self.min_eq && val < min) || (!self.min_eq && val <= min) {
51 return false;
52 }
53 }
54 if let Some(max) = self.max {
55 if (self.max_eq && val > max) || (!self.max_eq && val >= max) {
56 return false;
57 }
58 }
59 true
60 }
61 #[inline]
62 fn min_eq_sym(&self) -> &'static str {
63 if self.min_eq {
64 "<="
65 } else {
66 "<"
67 }
68 }
69 #[inline]
70 fn max_eq_sym(&self) -> &'static str {
71 if self.max_eq {
72 "<="
73 } else {
74 "<"
75 }
76 }
77}
78
79impl fmt::Display for Range {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 if let Some(min) = self.min {
82 if let Some(max) = self.max {
83 if (min - max).abs() < f64::EPSILON && self.min_eq && self.max_eq {
84 write!(f, "x = {}", min)
85 } else {
86 write!(
87 f,
88 "{} {} x {} {}",
89 min,
90 self.min_eq_sym(),
91 self.max_eq_sym(),
92 max
93 )
94 }
95 } else {
96 write!(f, "{} {} x", min, self.min_eq_sym())
97 }
98 } else if let Some(max) = self.max {
99 write!(f, "x {} {}", self.max_eq_sym(), max)
100 } else {
101 write!(f, "*")
102 }
103 }
104}
105
106impl FromStr for Range {
107 type Err = Error;
108
109 fn from_str(s: &str) -> Result<Self, Self::Err> {
110 let condition = s.trim();
111 if condition.is_empty() || condition == "*" || condition == "#" {
112 Ok(Range::default())
113 } else {
114 let mut r_inspected_min: Option<f64> = None;
115 let mut r_inspected_max: Option<f64> = None;
116 let mut r_inspected_min_eq = false;
117 let mut r_inspected_max_eq = false;
118 let c = condition
119 .replace(' ', "")
120 .replace(">=", "}")
121 .replace("=>", "}")
122 .replace("<=", "{")
123 .replace("=<", "{")
124 .replace("===", "=")
125 .replace("==", "=");
126 let vals = c
127 .split(&['<', '>', '}', '{', '='][..])
128 .collect::<Vec<&str>>();
129 if vals.len() > 3 {
130 return Err(Error::invalid_data(ERR_INVALID_RANGE_CONDITION));
131 }
132 if vals.len() > 1 {
133 for (i, v) in vals.iter().enumerate() {
134 if *v == "x" || *v == "X" {
135 if vals.len() == 2 {
136 if i > 1 {
137 return Err(Error::invalid_data(ERR_INVALID_RANGE_CONDITION));
138 }
139 let s = c
140 .chars()
141 .nth(vals[0].len())
142 .ok_or_else(|| Error::invalid_data(ERR_INVALID_RANGE_CONDITION))?;
143 if s == '=' {
144 r_inspected_min = Some(vals[1 - i].parse()?);
145 r_inspected_max = r_inspected_min;
146 r_inspected_min_eq = true;
147 r_inspected_max_eq = true;
148 } else if ((s == '}' || s == '>') && i == 0)
149 || ((s == '{' || s == '<') && i == 1)
150 {
151 r_inspected_min = Some(vals[1 - i].parse()?);
152 r_inspected_min_eq = s == '}' || s == '{';
153 } else if ((s == '}' || s == '>') && i == 1)
154 || ((s == '{' || s == '<') && i == 0)
155 {
156 r_inspected_max = Some(vals[1 - i].parse()?);
157 r_inspected_max_eq = s == '}' || s == '{';
158 }
159 } else if vals.len() == 3 {
160 if i != 1 {
161 return Err(Error::invalid_data(ERR_INVALID_RANGE_CONDITION));
162 }
163 let s1_ch = c.chars().nth(vals[0].len());
164 let s2_ch = c.chars().nth(vals[0].len() + 2);
165 if let Some(s1) = s1_ch {
166 if let Some(s2) = s2_ch {
167 if s2 == '}' || s2 == '>' {
168 r_inspected_max = Some(vals[i - 1].parse()?);
169 r_inspected_max_eq = s1 == '}';
170 r_inspected_min = Some(vals[i + 1].parse()?);
171 r_inspected_min_eq = s2 == '}';
172 } else if s2 == '{' || s2 == '<' {
173 r_inspected_min = Some(vals[i - 1].parse()?);
174 r_inspected_min_eq = s1 == '{';
175 r_inspected_max = Some(vals[i + 1].parse()?);
176 r_inspected_max_eq = s2 == '{';
177 }
178 }
179 }
180 if r_inspected_max.unwrap() <= r_inspected_min.unwrap() {
181 return Err(Error::invalid_data(ERR_INVALID_RANGE_CONDITION));
182 }
183 }
184 break;
185 }
186 }
187 } else {
188 return Err(Error::invalid_data(ERR_INVALID_RANGE_CONDITION));
189 }
190 Ok(Self {
191 min: r_inspected_min,
192 max: r_inspected_max,
193 min_eq: r_inspected_min_eq,
194 max_eq: r_inspected_max_eq,
195 })
196 }
197 }
198}
199
200pub fn de_range<'de, T, D>(deserializer: D) -> Result<T, D::Error>
201where
202 T: Deserialize<'de> + FromStr<Err = Error>,
203 D: Deserializer<'de>,
204{
205 struct StringOrStruct<T>(PhantomData<fn() -> T>);
206
207 impl<'de, T> Visitor<'de> for StringOrStruct<T>
208 where
209 T: Deserialize<'de> + FromStr<Err = Error>,
210 {
211 type Value = T;
212
213 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
214 formatter.write_str("string or map")
215 }
216
217 fn visit_str<E>(self, value: &str) -> Result<T, E>
218 where
219 E: de::Error,
220 {
221 Ok(FromStr::from_str(value).unwrap())
222 }
223 fn visit_string<E>(self, value: String) -> Result<T, E>
224 where
225 E: de::Error,
226 {
227 Ok(FromStr::from_str(&value).unwrap())
228 }
229 fn visit_map<M>(self, map: M) -> Result<T, M::Error>
230 where
231 M: MapAccess<'de>,
232 {
233 Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))
234 }
235 }
236
237 deserializer.deserialize_any(StringOrStruct(PhantomData))
238}
239
240pub fn de_opt_range<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
241where
242 T: Deserialize<'de> + FromStr<Err = Error>,
243 D: Deserializer<'de>,
244{
245 struct StringOrStruct<T>(PhantomData<fn() -> Option<T>>);
246
247 impl<'de, T> Visitor<'de> for StringOrStruct<T>
248 where
249 T: Deserialize<'de> + FromStr<Err = Error>,
250 {
251 type Value = Option<T>;
252
253 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
254 formatter.write_str("string or map")
255 }
256
257 fn visit_unit<E>(self) -> Result<Option<T>, E>
258 where
259 E: de::Error,
260 {
261 Ok(None)
262 }
263 fn visit_str<E>(self, value: &str) -> Result<Option<T>, E>
264 where
265 E: de::Error,
266 {
267 Ok(Some(FromStr::from_str(value).unwrap()))
268 }
269 fn visit_string<E>(self, value: String) -> Result<Option<T>, E>
270 where
271 E: de::Error,
272 {
273 Ok(Some(FromStr::from_str(&value).unwrap()))
274 }
275 fn visit_map<M>(self, map: M) -> Result<Option<T>, M::Error>
276 where
277 M: MapAccess<'de>,
278 {
279 let res = Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?;
280 Ok(Some(res))
281 }
282 }
283
284 deserializer.deserialize_any(StringOrStruct(PhantomData))
285}
286
287#[cfg(test)]
288mod test {
289 use super::{de_opt_range, de_range, Range};
290 use serde::Deserialize;
291
292 #[test]
293 fn test_de() {
294 #[derive(Deserialize)]
295 struct TestR {
296 #[serde(deserialize_with = "de_range")]
297 range: Range,
298 }
299 let range = Range {
300 min: Some(20.0),
301 max: Some(100.0),
302 min_eq: true,
303 max_eq: false,
304 };
305 let rs = r#"{ "range": {"min": 20, "max": 100, "min_eq": true, "max_eq": false }}"#;
306 let rdes: TestR = serde_json::from_str(rs).unwrap();
307 assert_eq!(rdes.range, range);
308 let rs = r#"{ "range": "20 <=x < 100" }"#;
309 let rdes: TestR = serde_json::from_str(rs).unwrap();
310 assert_eq!(rdes.range, range);
311 }
312
313 #[test]
314 fn test_opt_de() {
315 #[derive(Deserialize)]
316 struct TestR {
317 #[serde(default, deserialize_with = "de_opt_range")]
318 range: Option<Range>,
319 }
320 let range = Range {
321 min: Some(20.0),
322 max: Some(100.0),
323 min_eq: true,
324 max_eq: false,
325 };
326 let rs = r#"{ "range": {"min": 20, "max": 100, "min_eq": true, "max_eq": false }}"#;
327 let rdes: TestR = serde_json::from_str(rs).unwrap();
328 assert_eq!(rdes.range.unwrap(), range);
329 let rs = r#"{ "range": "20 <=x < 100" }"#;
330 let rdes: TestR = serde_json::from_str(rs).unwrap();
331 assert_eq!(rdes.range.unwrap(), range);
332 let rs = r#"{ "range": null }"#;
333 let rdes: TestR = serde_json::from_str(rs).unwrap();
334 assert!(rdes.range.is_none());
335 let rs = r"{}";
336 let rdes: TestR = serde_json::from_str(rs).unwrap();
337 assert!(rdes.range.is_none());
338 }
339
340 #[test]
341 fn test_range() {
342 let r = Range::default();
343 let r2 = Range::default();
344 assert_eq!(r, r2);
345 assert!(r.matches(111.0));
346 assert_eq!(r.to_string(), "*");
347 assert_eq!(r, "*".parse().unwrap());
348 let mut r = Range {
349 min: Some(0.0),
350 max: None,
351 min_eq: true,
352 max_eq: false,
353 };
354 let r2 = r;
355 assert_eq!(r, r2);
356 assert!(r.matches(1.0));
357 assert!(r.matches(0.0));
358 assert!(!r.matches(-1.0));
359 assert_eq!(r.to_string(), "0 <= x");
360 assert_eq!(r, "0 <= x".parse().unwrap());
361 assert_eq!(r, "x >= 0".parse().unwrap());
362 assert_eq!(r, "x => 0".parse().unwrap());
363 r.min_eq = false;
364 assert!(r.matches(1.0));
365 assert!(!r.matches(0.0));
366 assert!(!r.matches(-1.0));
367 assert_eq!(r.to_string(), "0 < x");
368 assert_eq!(r, "0 < x".parse().unwrap());
369 assert_eq!(r, "x>0".parse().unwrap());
370 r.max = Some(100.0);
371 assert!(r.matches(1.0));
372 assert!(!r.matches(0.0));
373 assert!(!r.matches(-1.0));
374 assert!(r.matches(99.0));
375 assert!(!r.matches(100.0));
376 assert!(!r.matches(101.0));
377 assert_eq!(r.to_string(), "0 < x < 100");
378 assert_eq!(r, "0 < x < 100".parse().unwrap());
379 assert_eq!(r, "100>x > 0".parse().unwrap());
380 r.max_eq = true;
381 assert!(r.matches(1.0));
382 assert!(!r.matches(0.0));
383 assert!(!r.matches(-1.0));
384 assert!(r.matches(99.0));
385 assert!(r.matches(100.0));
386 assert!(!r.matches(101.0));
387 assert_eq!(r.to_string(), "0 < x <= 100");
388 assert_eq!(r, "0 < x <= 100".parse().unwrap());
389 assert_eq!(r, "100=>x > 0".parse().unwrap());
390 r.min_eq = true;
391 assert_eq!(r.to_string(), "0 <= x <= 100");
392 assert_eq!(r, "0 <= x <= 100".parse().unwrap());
393 assert_eq!(r, "100=>x=> 0".parse().unwrap());
394 let r = Range {
395 min: None,
396 max: Some(100.0),
397 min_eq: false,
398 max_eq: true,
399 };
400 assert!(r.matches(1.0));
401 assert!(r.matches(0.0));
402 assert!(r.matches(-1.0));
403 assert!(r.matches(99.0));
404 assert!(r.matches(100.0));
405 assert!(!r.matches(101.0));
406 assert_eq!(r.to_string(), "x <= 100");
407 assert_eq!(r, "x <= 100".parse().unwrap());
408 assert_eq!(r, "100>=x".parse().unwrap());
409 }
410}