1use crate::Decimal;
18use crate::convert::MAX_I128_REPR;
19use crate::decimal::{MAX_PRECISION, MAX_SCALE, MIN_SCALE};
20use crate::error::DecimalParseError;
21use std::convert::{TryFrom, TryInto};
22use std::str::FromStr;
23
24#[derive(Debug, PartialEq)]
25enum Sign {
26 Positive,
27 Negative,
28}
29
30#[derive(Debug)]
32struct Parts<'a> {
33 pub sign: Sign,
34 pub integral: &'a [u8],
35 pub fractional: &'a [u8],
36 pub exp: i16,
37}
38
39#[inline]
41fn extract_sign(s: &[u8]) -> (Sign, &[u8]) {
42 match s.first() {
43 Some(b'+') => (Sign::Positive, &s[1..]),
44 Some(b'-') => (Sign::Negative, &s[1..]),
45 _ => (Sign::Positive, s),
46 }
47}
48
49#[inline]
51fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
52 let i = s.iter().take_while(|&i| i.is_ascii_digit()).count();
53 (&s[..i], &s[i..])
54}
55
56fn extract_exponent(s: &[u8], decimal_is_zero: bool) -> Result<(i16, &[u8]), DecimalParseError> {
58 let (sign, s) = extract_sign(s);
59 let (mut number, s) = eat_digits(s);
60
61 if number.is_empty() {
62 return Err(DecimalParseError::Invalid);
63 }
64
65 if decimal_is_zero {
66 return Ok((0, s));
67 }
68
69 while number.first() == Some(&b'0') {
70 number = &number[1..];
71 }
72
73 if number.len() > 3 {
74 return match sign {
75 Sign::Positive => Err(DecimalParseError::Overflow),
76 Sign::Negative => Err(DecimalParseError::Underflow),
77 };
78 }
79
80 let exp = {
81 let mut result: i16 = 0;
82 for &n in number {
83 result = result * 10 + (n - b'0') as i16;
84 }
85 match sign {
86 Sign::Positive => result,
87 Sign::Negative => -result,
88 }
89 };
90
91 Ok((exp, s))
92}
93
94fn parse_decimal(s: &[u8]) -> Result<(Parts<'_>, &[u8]), DecimalParseError> {
97 let (sign, s) = extract_sign(s);
98
99 if s.is_empty() {
100 return Err(DecimalParseError::Invalid);
101 }
102
103 let (mut integral, s) = eat_digits(s);
104
105 while integral.first() == Some(&b'0') && integral.len() > 1 {
106 integral = &integral[1..];
107 }
108
109 let (fractional, exp, s) = match s.first() {
110 Some(&b'e') | Some(&b'E') => {
111 if integral.is_empty() {
112 return Err(DecimalParseError::Invalid);
113 }
114
115 let decimal_is_zero = integral[0] == b'0';
116 let (exp, s) = extract_exponent(&s[1..], decimal_is_zero)?;
117 (&b""[..], exp, s)
118 }
119 Some(&b'.') => {
120 let (mut fractional, s) = eat_digits(&s[1..]);
121 if integral.is_empty() && fractional.is_empty() {
122 return Err(DecimalParseError::Invalid);
123 }
124
125 while fractional.last() == Some(&b'0') {
126 fractional = &fractional[0..fractional.len() - 1];
127 }
128
129 match s.first() {
130 Some(&b'e') | Some(&b'E') => {
131 let decimal_is_zero = (integral.is_empty() || integral[0] == b'0') && fractional.is_empty();
132 let (exp, s) = extract_exponent(&s[1..], decimal_is_zero)?;
133 (fractional, exp, s)
134 }
135 _ => (fractional, 0, s),
136 }
137 }
138 _ => {
139 if integral.is_empty() {
140 return Err(DecimalParseError::Invalid);
141 }
142
143 (&b""[..], 0, s)
144 }
145 };
146
147 Ok((
148 Parts {
149 sign,
150 integral,
151 fractional,
152 exp,
153 },
154 s,
155 ))
156}
157
158#[inline]
160fn eat_whitespaces(s: &[u8]) -> &[u8] {
161 let i = s.iter().take_while(|&i| i.is_ascii_whitespace()).count();
162 &s[i..]
163}
164
165#[inline]
167fn extract_nan(s: &[u8]) -> (bool, &[u8]) {
168 if s.len() < 3 {
169 (false, s)
170 } else {
171 let mut buf: [u8; 3] = s[0..3].try_into().unwrap();
172 buf.make_ascii_lowercase();
173 if &buf == b"nan" { (true, &s[3..]) } else { (false, s) }
174 }
175}
176
177#[inline]
183fn parse_str(s: &[u8]) -> Result<(Decimal, &[u8]), DecimalParseError> {
184 let (
185 Parts {
186 sign,
187 integral,
188 fractional,
189 exp,
190 },
191 s,
192 ) = parse_decimal(s)?;
193
194 let mut integral = integral;
195 let mut fractional = fractional;
196 let mut scale = -exp;
197
198 let mut carry = false;
199 const MAX_PRECISION_USIZE: usize = MAX_PRECISION as usize;
200
201 let mut normalized_exp = exp;
204
205 if integral == b"0" {
206 let zero_count = fractional.iter().take_while(|i| **i == b'0').count();
208 normalized_exp -= zero_count as i16;
209
210 let max_fractional_precision = MAX_PRECISION_USIZE + zero_count;
211 if fractional.len() > max_fractional_precision {
212 carry = fractional[max_fractional_precision] > b'4';
213 fractional = &fractional[0..max_fractional_precision];
214 }
215
216 debug_assert!(fractional.len() <= max_fractional_precision);
217 } else {
218 let int_len = integral.len() as i16;
219 normalized_exp += int_len;
220
221 if int_len > MAX_PRECISION_USIZE as i16 {
222 carry = integral[MAX_PRECISION_USIZE] > b'4';
223 scale -= int_len - MAX_PRECISION_USIZE as i16;
224
225 integral = &integral[0..MAX_PRECISION_USIZE];
226 fractional = &[];
227 } else {
228 let max_fractional_precision = MAX_PRECISION_USIZE - int_len as usize;
229 if fractional.len() > max_fractional_precision {
230 carry = fractional[max_fractional_precision] > b'4';
231 fractional = &fractional[0..max_fractional_precision];
232 }
233
234 debug_assert!(fractional.len() <= max_fractional_precision);
235 }
236 };
237
238 let mut int = 0u128;
239 for &i in integral {
240 int = int * 10 + (i - b'0') as u128;
241 }
242 for &i in fractional {
243 int = int * 10 + (i - b'0') as u128;
244 }
245 int += carry as u128;
248 if int > MAX_I128_REPR as u128 {
249 normalized_exp += 1;
250 int /= 10;
251 scale -= 1;
252 }
253
254 if normalized_exp <= -MAX_SCALE {
255 return Err(DecimalParseError::Underflow);
256 }
257 if normalized_exp > -MIN_SCALE {
258 return Err(DecimalParseError::Overflow);
259 }
260
261 let negative = if int != 0 { sign == Sign::Negative } else { false };
262
263 scale += fractional.len() as i16;
264 Ok((unsafe { Decimal::from_parts_unchecked(int, scale, negative) }, s))
265}
266
267#[inline]
272fn from_bytes(s: &[u8]) -> Result<Decimal, DecimalParseError> {
273 let s = eat_whitespaces(s);
274 if s.is_empty() {
275 return Err(DecimalParseError::Empty);
276 }
277
278 let (is_nan, s) = extract_nan(s);
279
280 if is_nan {
281 Err(DecimalParseError::Invalid)
282 } else {
283 let (n, s) = parse_str(s)?;
284
285 if s.iter().any(|n| !n.is_ascii_whitespace()) {
286 return Err(DecimalParseError::Invalid);
287 }
288
289 Ok(n)
290 }
291}
292
293impl FromStr for Decimal {
294 type Err = DecimalParseError;
295
296 #[inline]
297 fn from_str(s: &str) -> Result<Self, Self::Err> {
298 from_bytes(s.as_bytes())
299 }
300}
301
302impl TryFrom<&[u8]> for Decimal {
303 type Error = DecimalParseError;
304
305 #[inline]
306 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
307 from_bytes(value)
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314
315 fn assert_parse_empty<S: AsRef<str>>(s: S) {
316 let result = s.as_ref().parse::<Decimal>();
317 assert_eq!(result.unwrap_err(), DecimalParseError::Empty);
318 }
319
320 fn assert_parse_invalid<S: AsRef<str>>(s: S) {
321 let result = s.as_ref().parse::<Decimal>();
322 assert_eq!(result.unwrap_err(), DecimalParseError::Invalid);
323 }
324
325 fn assert_parse_overflow<S: AsRef<str>>(s: S) {
326 let result = s.as_ref().parse::<Decimal>();
327 assert_eq!(result.unwrap_err(), DecimalParseError::Overflow);
328 }
329
330 fn assert_parse_underflow<S: AsRef<str>>(s: S) {
331 let result = s.as_ref().parse::<Decimal>();
332 assert_eq!(result.unwrap_err(), DecimalParseError::Underflow);
333 }
334
335 #[test]
336 fn test_parse_error() {
337 assert_parse_empty("");
338 assert_parse_empty(" ");
339 assert_parse_invalid("-");
340 assert_parse_invalid(" - ");
341 assert_parse_invalid("-.");
342 assert_parse_invalid("- 1");
343 assert_parse_invalid("-NaN");
344 assert_parse_invalid("NaN.");
345 assert_parse_invalid("NaN1");
346 assert_parse_invalid(" NaN . ");
347 assert_parse_invalid(" NaN 1 ");
348 assert_parse_invalid(".");
349 assert_parse_invalid(" . ");
350 assert_parse_invalid("e");
351 assert_parse_invalid(" e ");
352 assert_parse_invalid("-e");
353 assert_parse_invalid("-1e");
354 assert_parse_invalid("1e1.1");
355 assert_parse_invalid("-1 e1");
356 assert_parse_invalid(" x ");
357 assert_parse_overflow("1e1000");
358 assert_parse_overflow("1e100000");
359 assert_parse_overflow("1e127");
360 assert_parse_underflow("1e-131");
361 assert_parse_underflow("1e-1000");
362 assert_parse_underflow("1e-100000");
363 }
364
365 fn assert_parse<S: AsRef<str>, V: AsRef<str>>(s: S, expected: V) {
366 let decimal = s.as_ref().parse::<Decimal>().unwrap();
367 assert_eq!(decimal.to_string(), expected.as_ref());
368 }
369
370 #[test]
371 fn test_parse_valid() {
372 assert_parse("0", "0");
374 assert_parse("-0", "0");
375 assert_parse(" -0 ", "0");
376 assert_parse("00000.", "0");
377 assert_parse("-00000.", "0");
378 assert_parse("128", "128");
379 assert_parse("-128", "-128");
380 assert_parse("65536", "65536");
381 assert_parse("-65536", "-65536");
382 assert_parse("4294967296", "4294967296");
383 assert_parse("-4294967296", "-4294967296");
384 assert_parse("18446744073709551616", "18446744073709551616");
385 assert_parse("-18446744073709551616", "-18446744073709551616");
386 assert_parse(
387 "99999999999999999999999999999999999999",
388 "99999999999999999999999999999999999999",
389 );
390 assert_parse(
391 "0099999999999999999999999999999999999999",
392 "99999999999999999999999999999999999999",
393 );
394 assert_parse(
395 "-99999999999999999999999999999999999999",
396 "-99999999999999999999999999999999999999",
397 );
398 assert_parse("000000000123", "123");
399 assert_parse("-000000000123", "-123");
400 assert_parse(
401 "170141183460469231713240559642175554110",
402 "170141183460469231713240559642175554110",
403 );
404 assert_parse(
405 "999999999999999999999999999999999999990000000000",
406 "999999999999999999999999999999999999990000000000",
407 );
408
409 assert_parse("0.0", "0");
411 assert_parse("-0.0", "0");
412 assert_parse(" -0.0 ", "0");
413 assert_parse(".0", "0");
414 assert_parse(".00000", "0");
415 assert_parse("-.0", "0");
416 assert_parse("-.00000", "0");
417 assert_parse("128.128", "128.128");
418 assert_parse("-128.128", "-128.128");
419 assert_parse("65536.65536", "65536.65536");
420 assert_parse("-65536.65536", "-65536.65536");
421 assert_parse("4294967296.4294967296", "4294967296.4294967296");
422 assert_parse("-4294967296.4294967296", "-4294967296.4294967296");
423 assert_parse(
424 "9999999999999999999.9999999999999999999",
425 "9999999999999999999.9999999999999999999",
426 );
427 assert_parse(
428 "-9999999999999999999.9999999999999999999",
429 "-9999999999999999999.9999999999999999999",
430 );
431 assert_parse("000000000123.000000000123", "123.000000000123");
432 assert_parse("-000000000123.000000000123", "-123.000000000123");
433 assert_parse(
434 "00.000000000000000000000000000000000000123",
435 "0.000000000000000000000000000000000000123",
436 );
437 assert_parse(
438 "00.000000000000000000000000000000000000123e-87",
439 "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123",
440 );
441 assert_parse(
442 "99999999999999999999999999999999999999500000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
443 "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
444 );
445
446 assert_parse("0e0", "0");
448 assert_parse("-0E-0", "0");
449 assert_parse("0000000000E0000000000", "0");
450 assert_parse("-0000000000E-0000000000", "0");
451 assert_parse("00000000001e0000000000", "1");
452 assert_parse("-00000000001e-0000000000", "-1");
453 assert_parse("00000000001e00000000001", "10");
454 assert_parse("-00000000001e-00000000001", "-0.1");
455 assert_parse("1e10", "10000000000");
456 assert_parse("-1e-10", "-0.0000000001");
457 assert_parse("0000001.23456000e3", "1234.56");
458 assert_parse("-0000001.23456000E-3", "-0.00123456");
459 assert_parse("0e999", "0");
460 assert_parse("0e+99999", "0");
461 assert_parse("0e9999999", "0");
462 assert_parse("0.e999", "0");
463 assert_parse("0.e+99999", "0");
464 assert_parse("0.e9999999", "0");
465 assert_parse("0.0e999", "0");
466 assert_parse("0.0e+99999", "0");
467 assert_parse("0.0e9999999", "0");
468 assert_parse("0.0000e999", "0");
469 assert_parse("0.0000e+99999", "0");
470 assert_parse("0.0000e9999999", "0");
471 assert_parse(".000e999", "0");
472 assert_parse(".000e+99999", "0");
473 assert_parse(".000e9999999", "0");
474 }
475
476 #[test]
477 fn test_parse_boundary() {
478 assert_parse(
479 "100E-131",
480 "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100",
481 );
482 assert_parse(
483 "0.000012345E130",
484 "123450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
485 );
486 assert_parse(
487 "4.94065645841247E-126",
488 "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000494065645841247",
489 );
490 assert_parse(
491 "1234.94065645841247E-126",
492 "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123494065645841247",
493 );
494 assert_parse(
495 "12345678987654321999999E-132",
496 "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012345678987654321999999",
497 );
498 assert_parse(
499 "10000000000000000000000000000000000000e88",
500 "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
501 );
502 assert_parse(
503 "0.999999999999999999999999999999999999995e-130",
504 "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000",
505 );
506 assert_parse_underflow("0.999999999999999999999999999999999999995e-131");
507 assert_parse_overflow(
508 "999999999999999999999999999999999999995000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
509 );
510 }
511
512 #[test]
513 fn test_parse_over_precision_but_valid() {
514 assert_parse(
516 "999999999999999999999999999999999999999",
517 "1000000000000000000000000000000000000000",
518 );
519 assert_parse(
520 "900719925474099290071992547409929007112123123123123",
521 "900719925474099290071992547409929007110000000000000",
522 );
523
524 assert_parse(
526 "0.123123123123123135555555555555555555555555555555",
527 "0.12312312312312313555555555555555555556",
528 );
529 assert_parse(
530 "0.0000000123123123123123135555555555555555555555555555555",
531 "0.000000012312312312312313555555555555555555556",
532 );
533 assert_parse(
534 "0.0000000123123123123123135555555555555515555555555555555",
535 "0.000000012312312312312313555555555555551555556",
536 );
537 assert_parse(
538 "0.0000000123123123123123135555555555555565555551555555555",
539 "0.000000012312312312312313555555555555556555555",
540 );
541
542 assert_parse(
544 "1231231231231231231231231255555555555555555555.123",
545 "1231231231231231231231231255555555555600000000",
546 );
547
548 assert_parse(
550 "123123.5555555555555555555555555555555555555555",
551 "123123.55555555555555555555555555555556",
552 );
553
554 assert_parse_overflow(
555 "90071992547409929007199254740992900711212312312312312312312312312311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
556 );
557 }
558}