hyper_scripter/query/
range_query.rs1use 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);