hyper_scripter/query/
range_query.rs

1use crate::error::{DisplayError, DisplayResult, FormatCode::RangeQuery as RangeQueryCode, Result};
2use crate::util::impl_ser_by_to_string;
3use std::num::NonZeroU64;
4use std::str::FromStr;
5
6#[derive(Debug, Clone, Copy)]
7pub struct RangeQuery {
8    min: NonZeroU64,
9    max: Option<NonZeroU64>,
10}
11
12const SEP: &str = "..";
13
14fn parse_int(s: &str) -> Result<NonZeroU64> {
15    let num: NonZeroU64 = s.parse().map_err(|e| {
16        RangeQueryCode
17            .to_err(s.to_owned())
18            .context(format!("解析整數錯誤 {}", e))
19    })?;
20    Ok(num)
21}
22
23impl RangeQuery {
24    pub fn get_max(&self) -> Option<NonZeroU64> {
25        self.max
26    }
27    pub fn get_min(&self) -> NonZeroU64 {
28        self.min
29    }
30}
31
32impl FromStr for RangeQuery {
33    type Err = DisplayError;
34    fn from_str(s: &str) -> DisplayResult<Self> {
35        if let Some((first, second)) = s.split_once(SEP) {
36            if first.is_empty() && second.is_empty() {
37                return Err(RangeQueryCode
38                    .to_err(s.to_owned())
39                    .context("不可前後皆為空")
40                    .into());
41            }
42            let min = if first.is_empty() {
43                NonZeroU64::new(1).unwrap()
44            } else {
45                parse_int(first)?
46            };
47            let max = if second.is_empty() {
48                None
49            } else {
50                let max = parse_int(second)?;
51                if max <= min {
52                    return Err(RangeQueryCode
53                        .to_err(s.to_owned())
54                        .context("max 不可小於等於 min")
55                        .into());
56                }
57                Some(max)
58            };
59            Ok(RangeQuery { min, max })
60        } else {
61            let num = parse_int(s)?;
62            Ok(RangeQuery {
63                min: num,
64                max: Some(NonZeroU64::new(num.get() + 1).unwrap()),
65            })
66        }
67    }
68}
69
70impl std::fmt::Display for RangeQuery {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        let RangeQuery { min, max } = *self;
73        if Some(min) == max {
74            write!(f, "{}", min)?;
75        } else {
76            write!(f, "{}{}", min, SEP)?;
77            if let Some(max) = max {
78                write!(f, "{}", max)?;
79            }
80        }
81        Ok(())
82    }
83}
84
85impl_ser_by_to_string!(RangeQuery);