byte_unit/bit/parse.rs
1use rust_decimal::prelude::*;
2
3use super::Bit;
4use crate::{ParseError, ValueParseError, common::get_char_from_bytes, unit::parse::read_xib};
5
6/// Associated functions for parsing strings.
7impl Bit {
8 /// Create a new `Bit` instance from a string.
9 /// The string may be `"10"`, `"10B"`, `"10M"`, `"10MB"`, `"10MiB"`, `"80b"`, `"80Mb"`, `"80Mbit"`.
10 ///
11 /// You can ignore the case of **"B"** (bit), which means **b** will still be treated as bits instead of bits.
12 ///
13 /// # Examples
14 ///
15 /// ```
16 /// # use byte_unit::Bit;
17 /// let bit = Bit::parse_str("123Kib").unwrap(); // 123 * 1024 bits
18 /// ```
19 pub fn parse_str<S: AsRef<str>>(s: S) -> Result<Self, ParseError> {
20 let s = s.as_ref().trim();
21
22 let mut bits = s.bytes();
23
24 let mut value = match bits.next() {
25 Some(e) => match e {
26 b'0'..=b'9' => Decimal::from(e - b'0'),
27 _ => {
28 return Err(ValueParseError::NotNumber(unsafe {
29 get_char_from_bytes(e, bits)
30 })
31 .into());
32 },
33 },
34 None => return Err(ValueParseError::NoValue.into()),
35 };
36
37 let e = 'outer: loop {
38 match bits.next() {
39 Some(e) => match e {
40 b'0'..=b'9' => {
41 value = value
42 .checked_mul(Decimal::TEN)
43 .ok_or(ValueParseError::NumberTooLong)?
44 .checked_add(Decimal::from(e - b'0'))
45 .ok_or(ValueParseError::NumberTooLong)?;
46 },
47 b'.' => {
48 let mut i = 1u32;
49
50 loop {
51 match bits.next() {
52 Some(e) => match e {
53 b'0'..=b'9' => {
54 value = value
55 .checked_add({
56 let mut d = Decimal::from(e - b'0');
57
58 d.set_scale(i)
59 .map_err(|_| ValueParseError::NumberTooLong)?;
60
61 d
62 })
63 .ok_or(ValueParseError::NumberTooLong)?;
64
65 i += 1;
66 },
67 _ => {
68 if i == 1 {
69 return Err(ValueParseError::NotNumber(unsafe {
70 get_char_from_bytes(e, bits)
71 })
72 .into());
73 }
74
75 match e {
76 b' ' => loop {
77 match bits.next() {
78 Some(e) => match e {
79 b' ' => (),
80 _ => break 'outer Some(e),
81 },
82 None => break 'outer None,
83 }
84 },
85 _ => break 'outer Some(e),
86 }
87 },
88 },
89 None => {
90 if i == 1 {
91 return Err(ValueParseError::NotNumber(unsafe {
92 get_char_from_bytes(e, bits)
93 })
94 .into());
95 }
96
97 break 'outer None;
98 },
99 }
100 }
101 },
102 b' ' => loop {
103 match bits.next() {
104 Some(e) => match e {
105 b' ' => (),
106 _ => break 'outer Some(e),
107 },
108 None => break 'outer None,
109 }
110 },
111 _ => break 'outer Some(e),
112 },
113 None => break None,
114 }
115 };
116
117 let unit = read_xib(e, bits, false, false)?;
118
119 Self::from_decimal_with_unit(value, unit)
120 .ok_or_else(|| ValueParseError::ExceededBounds(value).into())
121 }
122}