libaki_resort/util/
opt_max_buffer_size.rs1use regex::Regex;
2use std::convert::TryInto;
3
4#[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#[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#[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}