biscuit_converter/
lib.rs

1//! # biscuit-converter
2//! 
3//! `biscuit-converter` is a decimal integer parser using bitwise operations.
4//! 
5//! ## Usage
6//! 
7//! Add this to your `Cargo.toml`:
8//! 
9//! ```toml
10//! [dependencies]
11//! biscuit-converter = "0.3"
12//! ```
13//! 
14//! Then, use it in your Rust code:
15//! 
16//! ```rust
17//! use biscuit_converter::{Biscuit, error::ParseIntErr};
18//! 
19//! let val = i32::parse_decimal(b"1234");
20//! assert_eq!(val, Ok(1234));
21//!
22//! let val = i32::parse_decimal(b"1234a");
23//! assert_eq!(val, Err(ParseIntErr::NonDecimal));
24//! 
25//! let val = i32::parse_decimal(b"a1234");
26//! assert_eq!(val, Err(ParseIntErr::NonDecimal));
27//! 
28//! let val = i32::parse_decimal(b"");
29//! assert_eq!(val, Err(ParseIntErr::Empty));
30//! 
31//! let val = i32::parse_decimal(b" ");
32//! assert_eq!(val, Err(ParseIntErr::NonDecimal));
33//! 
34//! let val = i32::parse_decimal(b"2147483647"); // i32::MAX
35//! assert_eq!(val, Ok(2147483647));
36//! 
37//! let val = i32::parse_decimal(b"2147483648"); // i32::MAX + 1
38//! assert_eq!(val, Err(ParseIntErr::Overflow));
39//! 
40//! let val = i32::parse_decimal(b"-2147483648"); // i32::MIN
41//! assert_eq!(val, Ok(-2147483648));
42//! 
43//! let val = i32::parse_decimal(b"-2147483649"); // i32::MIN - 1
44//! assert_eq!(val, Err(ParseIntErr::NegOverflow));
45//! 
46//! let reading = i32::parse_decimal(b"0000000000000000000000000000000000000123");
47//! assert_eq!(reading, Ok(123));
48//! ```
49//! 
50//! ## License
51//! 
52//! This project is licensed under either of
53//! - Apache License, Version 2.0, <http://www.apache.org/licenses/LICENSE-2.0>
54//! - MIT license <http://opensource.org/licenses/MIT>
55//! at your option.
56//! 
57//! ## Contributions
58//! 
59//! Contributions are welcome! Feel free to open issues or submit pull requests on our GitHub repository.
60
61// Rest of your library code goes here...
62pub mod unsigned_decimal;
63pub mod little_endian_decimal;
64pub mod integer_decimal;
65pub mod error;
66pub mod utils;
67/// Parser for decimal notation
68/// It can not parse scientific notation
69pub trait Biscuit: Sized {
70    #[inline]
71    fn parse_decimal(u: &[u8]) -> Result<Self, error::ParseIntErr> {
72        Self::unsinged_decimal_core(u, false, false)
73    }
74
75    fn unsinged_decimal_core(_u: &[u8], _neg_max_check: bool, _pos_max_check: bool) -> Result<Self, error::ParseIntErr> {
76        unimplemented!("This function should be implemented in the child struct")
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use crate::Biscuit;
83    use crate::error::ParseIntErr;
84    use anyhow::Result;
85    use atoi::atoi;
86
87    #[test]
88    fn test_base() -> Result<()> {
89        let err_overflow = i32::parse_decimal(b"1234567890123");
90        assert_eq!(err_overflow, Err(ParseIntErr::Overflow));
91
92        let val_i64 = i64::parse_decimal(b"1234567890123");
93        assert_eq!(val_i64, Ok(1234567890123));
94
95        let nondecimal = i32::parse_decimal(b"123a");
96        assert_eq!(nondecimal, Err(ParseIntErr::NonDecimal));
97
98        let nondecimal = i32::parse_decimal(b"a123");
99        assert_eq!(nondecimal, Err(ParseIntErr::NonDecimal));
100
101        let err_empty = i32::parse_decimal(b"");
102        assert_eq!(err_empty, Err(ParseIntErr::Empty));
103
104        let u128_max_str = b"340282366920938463463374607431768211455";
105        let val_u128_max = u128::parse_decimal(u128_max_str)?;
106        assert_eq!(val_u128_max, u128::MAX);
107
108        let u128_overflow_str = b"340282366920938463463374607431768211456";
109        let err_u128_overflow = u128::parse_decimal(u128_overflow_str);
110        assert_eq!(err_u128_overflow, Err(ParseIntErr::Overflow));
111        
112        let i128_max_str = b"170141183460469231731687303715884105727";
113        let val_i128_max = i128::parse_decimal(i128_max_str)?;
114        assert_eq!(val_i128_max, i128::MAX);
115
116        let i128_overflow_str = b"170141183460469231731687303715884105728";
117        let i128_overflowed_value = i128::parse_decimal(i128_overflow_str);
118        // it is under the maximum of u128 
119        assert_eq!(i128_overflowed_value, Err(ParseIntErr::Overflow));
120
121        let i128_leading_zero_str = b"00000000000000000000000000000000000000000000001234";
122        let val_i128_leading_zero = i128::parse_decimal(i128_leading_zero_str)?;
123        assert_eq!(val_i128_leading_zero, 1234);
124        
125        Ok(())
126    }
127
128    #[test]
129    fn test_atoi() -> Result<()> {
130        let err_overflow = atoi::<i32>(b"1234567890123");
131        assert_eq!(err_overflow, None);
132
133        let val_i64 = atoi::<i64>(b"1234567890123");
134        assert_eq!(val_i64, Some(1234567890123));
135
136        let nondecimal = atoi::<i64>(b"123a");
137        assert_eq!(nondecimal, Some(123));
138
139        let nondecimal = atoi::<i64>(b"a123");
140        assert_eq!(nondecimal, None);
141
142        let err_empty = atoi::<i64>(b"");
143        assert_eq!(err_empty, None);
144
145        let u128_max_str = b"340282366920938463463374607431768211455";
146        let val_u128_max = atoi::<u128>(u128_max_str);
147        assert_eq!(val_u128_max, Some(u128::MAX));
148
149        let u128_overflow_str = b"340282366920938463463374607431768211456";
150        let err_u128_overflow = atoi::<u128>(u128_overflow_str);
151        assert_eq!(err_u128_overflow, None);
152        
153        let i128_max_str = b"170141183460469231731687303715884105727";
154        let val_i128_max = atoi::<i128>(i128_max_str);
155        assert_eq!(val_i128_max, Some(i128::MAX));
156
157        let i128_overflow_str = b"170141183460469231731687303715884105728";
158        let i128_overflowed_value = atoi::<i128>(i128_overflow_str);
159        // it is under the maximum of u128 
160        assert_eq!(i128_overflowed_value, None);
161
162        let i128_leading_zero_str = b"000000000000000000000000000000000000000000000000001234";
163        let val_i128_leading_zero = atoi::<i128>(i128_leading_zero_str);
164        assert_eq!(val_i128_leading_zero, Some(1234));
165        
166        Ok(())
167    }
168
169    #[test]
170    fn test_std() -> Result<()> {
171        let err_overflow = "1234567890123".parse::<i32>();
172        match err_overflow {
173            Ok(_) => panic!("Should have failed to parse"),
174            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::PosOverflow),
175        }
176
177        let val_i64 = "1234567890123".parse::<i64>();
178        assert_eq!(val_i64, Ok(1234567890123));
179
180        let nondecimal = "123a".parse::<i64>();
181        match nondecimal {
182            Ok(_) => panic!("Should have failed to parse"),
183            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::InvalidDigit),
184        }
185
186        let nondecimal = "a123".parse::<i64>();
187        match nondecimal {
188            Ok(_) => panic!("Should have failed to parse"),
189            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::InvalidDigit),
190        }
191
192        let err_empty = "".parse::<i64>();
193        match err_empty {
194            Ok(_) => panic!("Should have failed to parse"),
195            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::Empty),
196        }
197
198        let u128_max_str = "340282366920938463463374607431768211455".parse::<u128>();
199        assert_eq!(u128_max_str, Ok(u128::MAX));
200
201        let u128_overflow_str = "340282366920938463463374607431768211456".parse::<u128>();
202        match u128_overflow_str {
203            Ok(_) => panic!("Should have failed to parse"),
204            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::PosOverflow),
205        }
206
207        let i128_max_str = "170141183460469231731687303715884105727".parse::<i128>();
208        assert_eq!(i128_max_str, Ok(i128::MAX));
209
210        let i128_overflow_str = "170141183460469231731687303715884105728".parse::<i128>();
211        match i128_overflow_str {
212            Ok(_) => panic!("Should have failed to parse"),
213            Err(e) => assert_eq!(*e.kind(), std::num::IntErrorKind::PosOverflow),
214        }
215
216        let i128_leading_zero_str = "000000000000000000000000000000000000000000000000001234".parse::<i128>();
217        assert_eq!(i128_leading_zero_str, Ok(1234));
218
219        Ok(())
220    }
221}