1use core::str::Bytes;
2
3use super::Unit;
4use crate::{common::get_char_from_bytes, UnitParseError};
5
6impl Unit {
8 pub fn parse_str<S: AsRef<str>>(
27 s: S,
28 ignore_case: bool,
29 prefer_byte: bool,
30 ) -> Result<Self, UnitParseError> {
31 let s = s.as_ref().trim();
32
33 let mut bytes = s.bytes();
34
35 read_xib(bytes.next(), bytes, ignore_case, prefer_byte)
36 }
37}
38
39pub(crate) fn read_xib(
40 e: Option<u8>,
41 bytes: Bytes,
42 ignore_case: bool,
43 prefer_byte: bool,
44) -> Result<Unit, UnitParseError> {
45 match e {
46 Some(e) => match e.to_ascii_uppercase() {
47 b'B' => {
48 let byte = read_b(bytes, if ignore_case { true } else { e == b'B' })?;
49
50 if byte {
51 Ok(Unit::B)
52 } else {
53 Ok(Unit::Bit)
54 }
55 },
56 b'K' => {
57 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
58
59 if i {
60 if byte {
61 Ok(Unit::KiB)
62 } else {
63 Ok(Unit::Kibit)
64 }
65 } else if byte {
66 Ok(Unit::KB)
67 } else {
68 Ok(Unit::Kbit)
69 }
70 },
71 b'M' => {
72 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
73
74 if i {
75 if byte {
76 Ok(Unit::MiB)
77 } else {
78 Ok(Unit::Mibit)
79 }
80 } else if byte {
81 Ok(Unit::MB)
82 } else {
83 Ok(Unit::Mbit)
84 }
85 },
86 b'G' => {
87 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
88
89 if i {
90 if byte {
91 Ok(Unit::GiB)
92 } else {
93 Ok(Unit::Gibit)
94 }
95 } else if byte {
96 Ok(Unit::GB)
97 } else {
98 Ok(Unit::Gbit)
99 }
100 },
101 b'T' => {
102 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
103
104 if i {
105 if byte {
106 Ok(Unit::TiB)
107 } else {
108 Ok(Unit::Tibit)
109 }
110 } else if byte {
111 Ok(Unit::TB)
112 } else {
113 Ok(Unit::Tbit)
114 }
115 },
116 b'P' => {
117 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
118
119 if i {
120 if byte {
121 Ok(Unit::PiB)
122 } else {
123 Ok(Unit::Pibit)
124 }
125 } else if byte {
126 Ok(Unit::PB)
127 } else {
128 Ok(Unit::Pbit)
129 }
130 },
131 b'E' => {
132 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
133
134 if i {
135 if byte {
136 Ok(Unit::EiB)
137 } else {
138 Ok(Unit::Eibit)
139 }
140 } else if byte {
141 Ok(Unit::EB)
142 } else {
143 Ok(Unit::Ebit)
144 }
145 },
146 #[cfg(feature = "u128")]
147 b'Z' => {
148 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
149
150 if i {
151 if byte {
152 Ok(Unit::ZiB)
153 } else {
154 Ok(Unit::Zibit)
155 }
156 } else if byte {
157 Ok(Unit::ZB)
158 } else {
159 Ok(Unit::Zbit)
160 }
161 },
162 #[cfg(feature = "u128")]
163 b'Y' => {
164 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
165
166 if i {
167 if byte {
168 Ok(Unit::YiB)
169 } else {
170 Ok(Unit::Yibit)
171 }
172 } else if byte {
173 Ok(Unit::YB)
174 } else {
175 Ok(Unit::Ybit)
176 }
177 },
178 _ => {
179 #[cfg(feature = "u128")]
180 {
181 Err(UnitParseError {
182 character: unsafe { get_char_from_bytes(e, bytes) },
183 expected_characters: &['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
184 also_expect_no_character: true,
185 })
186 }
187 #[cfg(not(feature = "u128"))]
188 {
189 Err(UnitParseError {
190 character: unsafe { get_char_from_bytes(e, bytes) },
191 expected_characters: &['B', 'K', 'M', 'G', 'T', 'P', 'E'],
192 also_expect_no_character: true,
193 })
194 }
195 },
196 },
197 None => Ok(if prefer_byte { Unit::B } else { Unit::Bit }),
198 }
199}
200fn read_ib(
201 mut bytes: Bytes,
202 ignore_case: bool,
203 default_upper_case: bool,
204) -> Result<(bool, bool), UnitParseError> {
205 match bytes.next() {
206 Some(mut e) => {
207 let i = e == b'i' || e == b'I';
208
209 if i {
210 match bytes.next() {
211 Some(ne) => e = ne,
212 None => return Ok((true, default_upper_case)),
213 }
214 }
215
216 match e {
217 b'b' | b'B' => Ok((i, read_b(bytes, if ignore_case { true } else { e == b'B' })?)),
218 _ => {
219 let expected_characters: &[char] = if ignore_case {
220 if default_upper_case {
221 &['B']
222 } else {
223 &['b']
224 }
225 } else {
226 &['B', 'b']
227 };
228
229 Err(UnitParseError {
230 character: unsafe { get_char_from_bytes(e, bytes) },
231 expected_characters,
232 also_expect_no_character: true,
233 })
234 },
235 }
236 },
237 None => Ok((false, default_upper_case)),
238 }
239}
240
241fn read_b(mut bytes: Bytes, byte: bool) -> Result<bool, UnitParseError> {
242 match bytes.next() {
243 Some(e) => match e.to_ascii_lowercase() {
244 b'i' => match bytes.next() {
245 Some(e) => match e.to_ascii_lowercase() {
246 b't' => match bytes.next() {
247 Some(e) => match e.to_ascii_lowercase() {
248 b's' => match bytes.next() {
249 Some(e) => Err(UnitParseError {
250 character: unsafe {
251 get_char_from_bytes(e, bytes)
252 },
253 expected_characters: &[],
254 also_expect_no_character: true,
255 }),
256 None => Ok(false),
257 },
258 _ => Err(UnitParseError {
259 character: unsafe { get_char_from_bytes(e, bytes) },
260 expected_characters: &['s'],
261 also_expect_no_character: true,
262 }),
263 },
264 None => Ok(false),
265 },
266 _ => Err(UnitParseError {
267 character: unsafe { get_char_from_bytes(e, bytes) },
268 expected_characters: &['t'],
269 also_expect_no_character: false,
270 }),
271 },
272 None => Err(UnitParseError {
273 character: 'i',
274 expected_characters: &[],
275 also_expect_no_character: true,
276 }),
277 },
278 _ => Err(UnitParseError {
279 character: unsafe { get_char_from_bytes(e, bytes) },
280 expected_characters: &['i'],
281 also_expect_no_character: true,
282 }),
283 },
284 None => Ok(byte),
285 }
286}