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