1use core::str::Bytes;
2
3use super::Unit;
4use crate::{UnitParseError, common::get_char_from_bytes};
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 { Ok(Unit::B) } else { Ok(Unit::Bit) }
51 },
52 b'K' => {
53 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
54
55 if i {
56 if byte { Ok(Unit::KiB) } else { Ok(Unit::Kibit) }
57 } else if byte {
58 Ok(Unit::KB)
59 } else {
60 Ok(Unit::Kbit)
61 }
62 },
63 b'M' => {
64 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
65
66 if i {
67 if byte { Ok(Unit::MiB) } else { Ok(Unit::Mibit) }
68 } else if byte {
69 Ok(Unit::MB)
70 } else {
71 Ok(Unit::Mbit)
72 }
73 },
74 b'G' => {
75 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
76
77 if i {
78 if byte { Ok(Unit::GiB) } else { Ok(Unit::Gibit) }
79 } else if byte {
80 Ok(Unit::GB)
81 } else {
82 Ok(Unit::Gbit)
83 }
84 },
85 b'T' => {
86 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
87
88 if i {
89 if byte { Ok(Unit::TiB) } else { Ok(Unit::Tibit) }
90 } else if byte {
91 Ok(Unit::TB)
92 } else {
93 Ok(Unit::Tbit)
94 }
95 },
96 b'P' => {
97 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
98
99 if i {
100 if byte { Ok(Unit::PiB) } else { Ok(Unit::Pibit) }
101 } else if byte {
102 Ok(Unit::PB)
103 } else {
104 Ok(Unit::Pbit)
105 }
106 },
107 b'E' => {
108 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
109
110 if i {
111 if byte { Ok(Unit::EiB) } else { Ok(Unit::Eibit) }
112 } else if byte {
113 Ok(Unit::EB)
114 } else {
115 Ok(Unit::Ebit)
116 }
117 },
118 #[cfg(feature = "u128")]
119 b'Z' => {
120 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
121
122 if i {
123 if byte { Ok(Unit::ZiB) } else { Ok(Unit::Zibit) }
124 } else if byte {
125 Ok(Unit::ZB)
126 } else {
127 Ok(Unit::Zbit)
128 }
129 },
130 #[cfg(feature = "u128")]
131 b'Y' => {
132 let (i, byte) = read_ib(bytes, ignore_case, prefer_byte)?;
133
134 if i {
135 if byte { Ok(Unit::YiB) } else { Ok(Unit::Yibit) }
136 } else if byte {
137 Ok(Unit::YB)
138 } else {
139 Ok(Unit::Ybit)
140 }
141 },
142 _ => {
143 #[cfg(feature = "u128")]
144 {
145 Err(UnitParseError {
146 character: unsafe { get_char_from_bytes(e, bytes) },
147 expected_characters: &['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
148 also_expect_no_character: true,
149 })
150 }
151 #[cfg(not(feature = "u128"))]
152 {
153 Err(UnitParseError {
154 character: unsafe { get_char_from_bytes(e, bytes) },
155 expected_characters: &['B', 'K', 'M', 'G', 'T', 'P', 'E'],
156 also_expect_no_character: true,
157 })
158 }
159 },
160 },
161 None => Ok(if prefer_byte { Unit::B } else { Unit::Bit }),
162 }
163}
164fn read_ib(
165 mut bytes: Bytes,
166 ignore_case: bool,
167 default_upper_case: bool,
168) -> Result<(bool, bool), UnitParseError> {
169 match bytes.next() {
170 Some(mut e) => {
171 let i = e == b'i' || e == b'I';
172
173 if i {
174 match bytes.next() {
175 Some(ne) => e = ne,
176 None => return Ok((true, default_upper_case)),
177 }
178 }
179
180 match e {
181 b'b' | b'B' => Ok((i, read_b(bytes, if ignore_case { true } else { e == b'B' })?)),
182 _ => {
183 let expected_characters: &[char] = if ignore_case {
184 if default_upper_case { &['B'] } else { &['b'] }
185 } else {
186 &['B', 'b']
187 };
188
189 Err(UnitParseError {
190 character: unsafe { get_char_from_bytes(e, bytes) },
191 expected_characters,
192 also_expect_no_character: true,
193 })
194 },
195 }
196 },
197 None => Ok((false, default_upper_case)),
198 }
199}
200
201fn read_b(mut bytes: Bytes, byte: bool) -> Result<bool, UnitParseError> {
202 match bytes.next() {
203 Some(e) => match e.to_ascii_lowercase() {
204 b'i' => match bytes.next() {
205 Some(e) => match e.to_ascii_lowercase() {
206 b't' => match bytes.next() {
207 Some(e) => match e.to_ascii_lowercase() {
208 b's' => match bytes.next() {
209 Some(e) => Err(UnitParseError {
210 character: unsafe {
211 get_char_from_bytes(e, bytes)
212 },
213 expected_characters: &[],
214 also_expect_no_character: true,
215 }),
216 None => Ok(false),
217 },
218 _ => Err(UnitParseError {
219 character: unsafe { get_char_from_bytes(e, bytes) },
220 expected_characters: &['s'],
221 also_expect_no_character: true,
222 }),
223 },
224 None => Ok(false),
225 },
226 _ => Err(UnitParseError {
227 character: unsafe { get_char_from_bytes(e, bytes) },
228 expected_characters: &['t'],
229 also_expect_no_character: false,
230 }),
231 },
232 None => Err(UnitParseError {
233 character: 'i',
234 expected_characters: &[],
235 also_expect_no_character: true,
236 }),
237 },
238 _ => Err(UnitParseError {
239 character: unsafe { get_char_from_bytes(e, bytes) },
240 expected_characters: &['i'],
241 also_expect_no_character: true,
242 }),
243 },
244 None => Ok(byte),
245 }
246}