|
1 | | -use std::{iter::repeat_n, result::Result as StdResult}; |
| 1 | +use std::result::Result as StdResult; |
2 | 2 |
|
3 | 3 | use chrono::{DateTime, Days, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc}; |
4 | 4 |
|
@@ -470,15 +470,18 @@ fn parse_scaled_decimal_i128(s: &str, scale: i64, kind: &'static str) -> StdResu |
470 | 470 | return Err(format!("Could not decode {kind}: {s}")); |
471 | 471 | } |
472 | 472 |
|
473 | | - let mut digits = frac_str.bytes().collect::<Vec<_>>(); |
474 | | - if digits.len() < scale as usize { |
475 | | - digits.resize(scale as usize, b'0'); |
| 473 | + let mut frac = 0i128; |
| 474 | + for b in frac_str.bytes() { |
| 475 | + frac = frac |
| 476 | + .checked_mul(10) |
| 477 | + .and_then(|value| value.checked_add(i128::from(b - b'0'))) |
| 478 | + .ok_or_else(|| format!("Could not decode {kind}: {s}"))?; |
| 479 | + } |
| 480 | + for _ in frac_str.len()..scale as usize { |
| 481 | + frac = frac |
| 482 | + .checked_mul(10) |
| 483 | + .ok_or_else(|| format!("Could not decode {kind}: {s}"))?; |
476 | 484 | } |
477 | | - |
478 | | - let frac = std::str::from_utf8(&digits) |
479 | | - .map_err(|_| format!("Could not decode {kind}: {s}"))? |
480 | | - .parse::<i128>() |
481 | | - .map_err(|_| format!("Could not decode {kind}: {s}"))?; |
482 | 485 | scaled = scaled |
483 | 486 | .checked_add(frac) |
484 | 487 | .ok_or_else(|| format!("Could not decode {kind}: {s}"))?; |
@@ -562,7 +565,9 @@ fn parse_legacy_timestamp_tz_wire(s: &str, scale: i64) -> StdResult<TimestampTzW |
562 | 565 |
|
563 | 566 | let tz_index = |
564 | 567 | i32::try_from(tz_index).map_err(|_| format!("invalid timezone for timestamp_tz: {s}"))?; |
565 | | - let tz_index = parse_timestamp_tz_index(&tz_index.to_string(), s)?; |
| 568 | + if !(0..=2880).contains(&tz_index) { |
| 569 | + return Err(format!("invalid timezone for timestamp_tz: {s}")); |
| 570 | + } |
566 | 571 |
|
567 | 572 | Ok(TimestampTzWire { utc, tz_index }) |
568 | 573 | } |
@@ -625,19 +630,19 @@ pub(crate) fn parse_time_seconds_and_nanos( |
625 | 630 | return Ok((secs, 0)); |
626 | 631 | } |
627 | 632 |
|
628 | | - let mut frac_digits = frac_str.as_bytes().to_vec(); |
629 | | - if frac_digits.len() > scale { |
630 | | - frac_digits.truncate(scale); |
| 633 | + let mut frac_scaled = 0u32; |
| 634 | + let used_digits = frac_str.len().min(scale); |
| 635 | + for b in frac_str.bytes().take(used_digits) { |
| 636 | + frac_scaled = frac_scaled |
| 637 | + .checked_mul(10) |
| 638 | + .and_then(|value| value.checked_add(u32::from(b - b'0'))) |
| 639 | + .ok_or_else(|| format!("invalid time: {value}"))?; |
631 | 640 | } |
632 | | - if frac_digits.len() < scale { |
633 | | - frac_digits.extend(repeat_n(b'0', scale - frac_digits.len())); |
| 641 | + for _ in used_digits..scale { |
| 642 | + frac_scaled = frac_scaled |
| 643 | + .checked_mul(10) |
| 644 | + .ok_or_else(|| format!("invalid time: {value}"))?; |
634 | 645 | } |
635 | | - |
636 | | - let frac_scaled = { |
637 | | - let s = std::str::from_utf8(&frac_digits).map_err(|_| format!("invalid time: {value}"))?; |
638 | | - s.parse::<u32>() |
639 | | - .map_err(|_| format!("invalid time: {value}"))? |
640 | | - }; |
641 | 646 | let nsec = frac_scaled |
642 | 647 | .checked_mul(10u32.pow((9 - scale) as u32)) |
643 | 648 | .ok_or_else(|| format!("invalid time: {value}"))?; |
|
0 commit comments