libaki_resort/util/
opt_max_buffer_size.rs

1use regex::Regex;
2use std::convert::TryInto;
3
4//{{{ OptMaxBufferSize
5#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
6pub struct OptMaxBufferSize(usize);
7impl OptMaxBufferSize {
8    pub fn new(v: usize) -> Self {
9        Self(v)
10    }
11    pub fn is_ok(&self, v: usize) -> bool {
12        if self.0 == 0 {
13            true
14        } else {
15            v <= self.0
16        }
17    }
18}
19
20impl ::std::str::FromStr for OptMaxBufferSize {
21    type Err = OptMaxBufferSizeParseError;
22    fn from_str(s: &str) -> Result<Self, Self::Err> {
23        lazy_static! {
24            static ref RE: Regex = Regex::new("([0-9]+)([KMGTPkmgtp])?[bB]?").unwrap();
25        }
26        if let Some(caps) = RE.captures(s) {
27            let digit: usize = if let Some(mat) = caps.get(1) {
28                match mat.as_str().parse::<usize>() {
29                    Ok(digit) => digit,
30                    Err(err) => {
31                        let s = format!("can not parse '{s}': {err}");
32                        return Err(OptMaxBufferSizeParseError::new(s));
33                    }
34                }
35            } else {
36                let s = format!("can not parse '{s}'");
37                return Err(OptMaxBufferSizeParseError::new(s));
38            };
39            let unit: usize = if let Some(mat) = caps.get(2) {
40                let un: u64 = match mat.as_str() {
41                    "K" | "k" => 1024,
42                    "M" | "m" => 1024 * 1024,
43                    "G" | "g" => 1024 * 1024 * 1024,
44                    "T" | "t" => 1024 * 1024 * 1024 * 1024,
45                    "P" | "p" => 1024 * 1024 * 1024 * 1024 * 1024,
46                    _ => 1,
47                };
48                if un > usize::MAX.try_into().unwrap()
49                    || digit as u64 * un > usize::MAX.try_into().unwrap()
50                {
51                    let s = format!("can not parse '{s}': overflow");
52                    return Err(OptMaxBufferSizeParseError::new(s));
53                } else {
54                    un.try_into().unwrap()
55                }
56            } else {
57                1
58            };
59            Ok(OptMaxBufferSize::new(digit * unit))
60        } else {
61            let s = format!("can not parse '{s}'");
62            Err(OptMaxBufferSizeParseError::new(s))
63        }
64    }
65}
66
67impl ::std::fmt::Display for OptMaxBufferSize {
68    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
69        write!(f, "{}", self.0)
70    }
71}
72//}}} OptMaxBufferSize
73
74//{{{ OptMaxBufferSizeParseError
75#[derive(Debug)]
76pub struct OptMaxBufferSizeParseError {
77    desc: String,
78}
79
80impl OptMaxBufferSizeParseError {
81    fn new(s: String) -> OptMaxBufferSizeParseError {
82        OptMaxBufferSizeParseError { desc: s }
83    }
84}
85
86impl ::std::fmt::Display for OptMaxBufferSizeParseError {
87    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
88        self.desc.fmt(f)
89    }
90}
91
92impl ::std::error::Error for OptMaxBufferSizeParseError {
93    fn description(&self) -> &str {
94        self.desc.as_str()
95    }
96}
97//}}} OptMaxBufferSizeParseError
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102    use std::str::FromStr;
103
104    #[test]
105    fn test_display_0() {
106        let v = OptMaxBufferSize::new(0);
107        assert_eq!(format!("{v}"), "0");
108    }
109    #[test]
110    fn test_display_1024() {
111        let v = OptMaxBufferSize::new(1024);
112        assert_eq!(format!("{v}"), "1024");
113    }
114    #[test]
115    fn test_from_str_123() {
116        let col: OptMaxBufferSize = match FromStr::from_str("123") {
117            Ok(c) => c,
118            Err(_) => {
119                unreachable!();
120            }
121        };
122        assert_eq!(col, OptMaxBufferSize::new(123));
123    }
124    #[test]
125    fn test_from_str_123k() {
126        let col: OptMaxBufferSize = match FromStr::from_str("123k") {
127            Ok(c) => c,
128            Err(_) => {
129                unreachable!();
130            }
131        };
132        assert_eq!(col, OptMaxBufferSize::new(123 * 1024));
133    }
134    #[test]
135    fn test_from_str_123m() {
136        let col: OptMaxBufferSize = match FromStr::from_str("123m") {
137            Ok(c) => c,
138            Err(_) => {
139                unreachable!();
140            }
141        };
142        assert_eq!(col, OptMaxBufferSize::new(123 * 1024 * 1024));
143    }
144    #[cfg(target_pointer_width = "64")]
145    #[test]
146    fn test_from_str_123g() {
147        let _col: OptMaxBufferSize = match FromStr::from_str("123g") {
148            Ok(c) => c,
149            Err(_) => {
150                unreachable!();
151            }
152        };
153        #[cfg(target_pointer_width = "64")]
154        assert_eq!(_col, OptMaxBufferSize::new(123 * 1024 * 1024 * 1024));
155    }
156    #[cfg(target_pointer_width = "32")]
157    #[test]
158    fn test_from_str_123g() {
159        match FromStr::from_str("123g") {
160            Ok(c) => {
161                let _col: OptMaxBufferSize = c;
162                unreachable!();
163            }
164            Err(err) => {
165                assert_eq!(format!("{}", err), "can not parse \'123g\': overflow");
166            }
167        };
168    }
169    #[cfg(target_pointer_width = "64")]
170    #[test]
171    fn test_from_str_123t() {
172        let _col: OptMaxBufferSize = match FromStr::from_str("123t") {
173            Ok(c) => c,
174            Err(_) => {
175                unreachable!();
176            }
177        };
178        assert_eq!(_col, OptMaxBufferSize::new(123 * 1024 * 1024 * 1024 * 1024));
179    }
180    #[cfg(target_pointer_width = "32")]
181    #[test]
182    fn test_from_str_123t() {
183        match FromStr::from_str("123t") {
184            Ok(c) => {
185                let _col: OptMaxBufferSize = c;
186                unreachable!();
187            }
188            Err(err) => {
189                assert_eq!(format!("{}", err), "can not parse \'123t\': overflow");
190            }
191        };
192    }
193    #[cfg(target_pointer_width = "64")]
194    #[test]
195    fn test_from_str_123p() {
196        let _col: OptMaxBufferSize = match FromStr::from_str("123p") {
197            Ok(c) => c,
198            Err(_) => {
199                unreachable!();
200            }
201        };
202        #[cfg(target_pointer_width = "64")]
203        assert_eq!(
204            _col,
205            OptMaxBufferSize::new(123 * 1024 * 1024 * 1024 * 1024 * 1024)
206        );
207    }
208    #[cfg(target_pointer_width = "32")]
209    #[test]
210    fn test_from_str_123p() {
211        match FromStr::from_str("123p") {
212            Ok(c) => {
213                let _col: OptMaxBufferSize = c;
214                unreachable!();
215            }
216            Err(err) => {
217                assert_eq!(format!("{}", err), "can not parse \'123p\': overflow");
218            }
219        };
220    }
221    #[test]
222    fn test_from_str_invalid() {
223        let _col: OptMaxBufferSize = match FromStr::from_str("other") {
224            Ok(_c) => _c,
225            Err(e) => {
226                assert_eq!(e.to_string(), "can not parse \'other\'");
227                return;
228            }
229        };
230        unreachable!();
231    }
232}