1use units::*;
2type Result<T> = std::result::Result<T, ::std::num::ParseIntError>;
3
4pub fn parse(s: &str) -> Result<usize> {
30 let res: Result<Vec<usize>> = s.split('X').map(|s| scaled_part(s.trim())).collect();
31 Ok(res?.into_iter().product())
32}
33
34pub fn parse_opt(s: &str) -> Result<Option<usize>> { Ok(Some(parse(s)?)) }
36
37fn scaled_part(s: &str) -> Result<usize> {
38 let (scale_unit, offset) = scaling_factor(s);
39 let end = s.len() - offset;
40 Ok(scale_unit * numeric_part(&s[..end])?)
41}
42
43fn numeric_part(s: &str) -> Result<usize> {
44 let mut bytes = s.bytes();
45 match (bytes.next(), bytes.next()) {
46 (Some(b'0'), Some(b'x')) | (Some(b'0'), Some(b'X')) => usize::from_str_radix(&s[2..], 16),
48 (Some(b'0'), Some(b'o')) => usize::from_str_radix(&s[2..], 8),
50 _ => usize::from_str_radix(s, 10),
52 }
53}
54fn scaling_factor(s: &str) -> (usize, usize) {
57 let (scaling, offset) = if let Some(x) = two_byte_scaling_factor(s) {
58 (x, 2)
59 } else if let Some(x) = one_byte_scaling_factor(s) {
60 (x, 1)
61 } else {
62 (1, 0)
63 };
64 (scaling, offset)
65}
66
67fn two_byte_scaling_factor(s: &str) -> Option<usize> {
68 let mut bytes = s.bytes();
69 if Some(b'B') != bytes.next_back() {
70 return None;
71 }
72 match bytes.next_back()? {
73 b'K' => Some(KB),
74 b'M' => Some(MB),
75 b'G' => Some(GB),
76 b'T' => Some(TB),
77 b'P' => Some(PB),
78 b'Z' => Some(ZB),
79 _ => None,
80 }
81}
82fn one_byte_scaling_factor(s: &str) -> Option<usize> {
83 Some(match s.bytes().next_back()? {
84 b'C' => 1,
85 b'W' => BITSIZE,
86 b'B' => B,
87 b'K' => K,
88 b'M' => M,
89 b'G' => G,
90 b'T' => T,
91 b'P' => P,
92 b'Z' => Z,
93 _ => return None,
95 })
96}
97pub mod units {}