mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 07:18:08 +08:00
Implement wcstod() in Rust
This is built around fast-float. Factor the error type from this and wcstoi() together into a shared type.
This commit is contained in:
parent
0e68405ccd
commit
7729d3206a
@ -6,6 +6,9 @@
|
||||
|
||||
pub use widestring::{Utf32Str as wstr, Utf32String as WString};
|
||||
|
||||
/// Pull in our extensions.
|
||||
pub use crate::wchar_ext::{IntoCharIter, WExt};
|
||||
|
||||
/// Creates a wstr string slice, like the "L" prefix of C++.
|
||||
/// The result is of type wstr.
|
||||
/// It is NOT nul-terminated.
|
||||
@ -27,9 +30,6 @@ pub(crate) use L;
|
||||
/// Note: the resulting string is NOT nul-terminated.
|
||||
pub use widestring_suffix::widestrs;
|
||||
|
||||
/// Pull in our extensions.
|
||||
pub use crate::wchar_ext::{CharPrefixSuffix, WExt};
|
||||
|
||||
// Use Unicode "non-characters" for internal characters as much as we can. This
|
||||
// gives us 32 "characters" for internal use that we can guarantee should not
|
||||
// appear in our input stream. See http://www.unicode.org/faq/private_use.html.
|
||||
|
@ -80,35 +80,36 @@ fn test_to_wstring() {
|
||||
assert_eq!(i64::MAX.to_wstring(), "9223372036854775807");
|
||||
}
|
||||
|
||||
/// A thing that a wide string can start with or end with.
|
||||
/// It must have a chars() method which returns a double-ended char iterator.
|
||||
pub trait CharPrefixSuffix {
|
||||
type Iter: DoubleEndedIterator<Item = char>;
|
||||
/// A trait for a thing that can produce a double-ended, cloneable
|
||||
/// iterator of chars.
|
||||
/// Common implementations include char, &str, &wstr, &WString.
|
||||
pub trait IntoCharIter {
|
||||
type Iter: DoubleEndedIterator<Item = char> + Clone;
|
||||
fn chars(self) -> Self::Iter;
|
||||
}
|
||||
|
||||
impl CharPrefixSuffix for char {
|
||||
impl IntoCharIter for char {
|
||||
type Iter = std::iter::Once<char>;
|
||||
fn chars(self) -> Self::Iter {
|
||||
std::iter::once(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CharPrefixSuffix for &'a str {
|
||||
impl<'a> IntoCharIter for &'a str {
|
||||
type Iter = std::str::Chars<'a>;
|
||||
fn chars(self) -> Self::Iter {
|
||||
str::chars(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CharPrefixSuffix for &'a wstr {
|
||||
impl<'a> IntoCharIter for &'a wstr {
|
||||
type Iter = CharsUtf32<'a>;
|
||||
fn chars(self) -> Self::Iter {
|
||||
wstr::chars(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CharPrefixSuffix for &'a WString {
|
||||
impl<'a> IntoCharIter for &'a WString {
|
||||
type Iter = CharsUtf32<'a>;
|
||||
fn chars(self) -> Self::Iter {
|
||||
wstr::chars(self)
|
||||
@ -155,13 +156,13 @@ pub trait WExt {
|
||||
|
||||
/// \return whether we start with a given Prefix.
|
||||
/// The Prefix can be a char, a &str, a &wstr, or a &WString.
|
||||
fn starts_with<Prefix: CharPrefixSuffix>(&self, prefix: Prefix) -> bool {
|
||||
fn starts_with<Prefix: IntoCharIter>(&self, prefix: Prefix) -> bool {
|
||||
iter_prefixes_iter(prefix.chars(), self.as_char_slice().iter().copied())
|
||||
}
|
||||
|
||||
/// \return whether we end with a given Suffix.
|
||||
/// The Suffix can be a char, a &str, a &wstr, or a &WString.
|
||||
fn ends_with<Suffix: CharPrefixSuffix>(&self, suffix: Suffix) -> bool {
|
||||
fn ends_with<Suffix: IntoCharIter>(&self, suffix: Suffix) -> bool {
|
||||
iter_prefixes_iter(
|
||||
suffix.chars().rev(),
|
||||
self.as_char_slice().iter().copied().rev(),
|
||||
|
15
fish-rust/src/wutil/errors.rs
Normal file
15
fish-rust/src/wutil/errors.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
// The value overflowed.
|
||||
Overflow,
|
||||
|
||||
// The input string was empty.
|
||||
Empty,
|
||||
|
||||
// The input string contained an invalid char.
|
||||
// Note this may not be returned for conversions which stop at invalid chars.
|
||||
InvalidChar,
|
||||
|
||||
// There were chars remaining in the input.
|
||||
CharsLeft,
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
pub mod errors;
|
||||
pub mod format;
|
||||
pub mod gettext;
|
||||
mod normalize_path;
|
||||
mod wcstoi;
|
||||
pub mod wcstod;
|
||||
pub mod wcstoi;
|
||||
mod wrealpath;
|
||||
|
||||
use std::io::Write;
|
||||
|
444
fish-rust/src/wutil/wcstod.rs
Normal file
444
fish-rust/src/wutil/wcstod.rs
Normal file
@ -0,0 +1,444 @@
|
||||
use super::errors::Error;
|
||||
use crate::wchar::IntoCharIter;
|
||||
use fast_float::parse_partial_iter;
|
||||
|
||||
/// Parses a 64-bit floating point number.
|
||||
///
|
||||
/// Leading whitespace and trailing characters are ignored. If the input
|
||||
/// string does not contain a valid floating point number (where e.g.
|
||||
/// `"."` is seen as a valid floating point number), `None` is returned.
|
||||
/// Otherwise the parsed floating point number is returned.
|
||||
///
|
||||
/// The `decimal_sep` parameter is used to specify the decimal separator.
|
||||
/// '.' is a normal default.
|
||||
///
|
||||
/// The `consumed` parameter is used to return the number of characters
|
||||
/// consumed, similar to the "end" parameter to strtod.
|
||||
/// This is only meaningful if parsing succeeds.
|
||||
///
|
||||
/// Error::Overflow is returned if the value is too large in magnitude.
|
||||
pub fn wcstod<Chars>(input: Chars, decimal_sep: char, consumed: &mut usize) -> Result<f64, Error>
|
||||
where
|
||||
Chars: IntoCharIter,
|
||||
{
|
||||
let chars = input.chars();
|
||||
if chars.clone().next().is_none() {
|
||||
*consumed = 0;
|
||||
return Err(Error::Empty);
|
||||
}
|
||||
|
||||
let ret = parse_partial_iter(chars.clone().fuse(), decimal_sep);
|
||||
if ret.is_err() {
|
||||
*consumed = 0;
|
||||
return Err(Error::InvalidChar);
|
||||
}
|
||||
let (val, n): (f64, usize) = ret.unwrap();
|
||||
|
||||
// Fast-float does not return overflow errors; instead it just returns +/- infinity.
|
||||
// Check to see if the first character is a digit or the decimal; if so that indicates overflow.
|
||||
if val.is_infinite() {
|
||||
for c in chars {
|
||||
if c.is_whitespace() {
|
||||
continue;
|
||||
} else if c.is_ascii_digit() || c == decimal_sep {
|
||||
return Err(Error::Overflow);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*consumed = n;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#![allow(overflowing_literals)]
|
||||
|
||||
use super::{wcstod, Error};
|
||||
use std::f64;
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::all)]
|
||||
pub fn tests() {
|
||||
test("12.345", Ok(12.345));
|
||||
test("12.345e19", Ok(12.345e19));
|
||||
test("-.1e+9", Ok(-0.1e+9));
|
||||
test(".125", Ok(0.125));
|
||||
test("1e20", Ok(1e20));
|
||||
test("0e-19", Ok(0.0));
|
||||
test_consumed("4\00012", Ok(4.0), 1);
|
||||
test("5.9e-76", Ok(5.9e-76));
|
||||
test("", Err(Error::Empty));
|
||||
test("Inf", Ok(f64::INFINITY));
|
||||
test("-Inf", Ok(f64::NEG_INFINITY));
|
||||
test("+InFiNiTy", Ok(f64::INFINITY));
|
||||
test("1e-324", Ok(0.0));
|
||||
test(
|
||||
"+1.000000000116415321826934814453125",
|
||||
Ok(1.000000000116415321826934814453125),
|
||||
);
|
||||
test("42.0000000000000000001", Ok(42.0000000000000000001));
|
||||
test("42.00000000000000000001", Ok(42.00000000000000000001));
|
||||
test("42.000000000000000000001", Ok(42.000000000000000000001));
|
||||
test("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368", Ok(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000));
|
||||
test_consumed("1y", Ok(1.0), 1);
|
||||
test_consumed("0.y", Ok(0.0), 2);
|
||||
test_consumed(".0y", Ok(0.0), 2);
|
||||
test_consumed("000,,,e1", Ok(0.0), 3);
|
||||
test("000e1", Ok(0.0));
|
||||
test_consumed("000,1e1", Ok(0.0), 3);
|
||||
test("0", Ok(0.0));
|
||||
test("000", Ok(0.0));
|
||||
test("-0", Ok(-0.0));
|
||||
test("-000", Ok(-0.0));
|
||||
test_consumed("0,", Ok(0.0), 1);
|
||||
test_consumed("-0,", Ok(-0.0), 2);
|
||||
test_consumed("0,0", Ok(0.0), 1);
|
||||
test_consumed("-0,0", Ok(-0.0), 2);
|
||||
test("0e-10", Ok(0.0));
|
||||
test("-0e-10", Ok(-0.0));
|
||||
test_consumed("0,e-10", Ok(0.0), 1);
|
||||
test_consumed("-0,e-10", Ok(-0.0), 2);
|
||||
test_consumed("0,0e-10", Ok(0.0), 1);
|
||||
test_consumed("-0,0e-10", Ok(-0.0), 2);
|
||||
test("0e-1000000", Ok(0.0));
|
||||
test("-0e-1000000", Ok(-0.0));
|
||||
test_consumed("0,0e-1000000", Ok(0.0), 1);
|
||||
test_consumed("-0,0e-1000000", Ok(-0.0), 2);
|
||||
test("0", Ok(0.0));
|
||||
test("000", Ok(0.0));
|
||||
test("-0", Ok(-0.0));
|
||||
test("-000", Ok(-0.0));
|
||||
test("0e-10", Ok(0.0));
|
||||
test("-0e-10", Ok(-0.0));
|
||||
test("0e-1000000", Ok(0.0));
|
||||
test("-0e-1000000", Ok(-0.0));
|
||||
test("1", Ok(1_f64));
|
||||
test("1.1", Ok(1.1));
|
||||
test("1.1e1", Ok(1.1e1));
|
||||
test("1234.1234", Ok(1234.1234));
|
||||
test("1234.12345678", Ok(1234.12345678));
|
||||
test("1234.123456789012", Ok(1234.123456789012));
|
||||
test(
|
||||
"1.797693134862315708145274237317e+10",
|
||||
Ok(1.797693134862315708145274237317e+10),
|
||||
);
|
||||
test(
|
||||
"1.797693134862315708145274237317e+308",
|
||||
Ok(1.797693134862315708145274237317e+308_f64),
|
||||
);
|
||||
test("000000000e123", Ok(0.0));
|
||||
test("0000000010000e-329", Ok(0.0));
|
||||
test("000000001e-325", Ok(0.0));
|
||||
test("0000000020000e-328", Ok(0.0));
|
||||
test("0000000090000e-329", Ok(0.0));
|
||||
test("0e+999", Ok(0.0));
|
||||
test("0e1", Ok(0.0));
|
||||
test("0e12345", Ok(0.0));
|
||||
test("0e2", Ok(0.0));
|
||||
test("0e-2", Ok(0.0));
|
||||
test("0e-999", Ok(0.0));
|
||||
test("10000e-329", Ok(0.0));
|
||||
test("1e-325", Ok(0.0));
|
||||
test("20000e-328", Ok(0.0));
|
||||
test("2e-324", Ok(0.0));
|
||||
test("90000e-329", Ok(0.0));
|
||||
test_consumed("e1324", Err(Error::InvalidChar), 0);
|
||||
test("1e0", Ok(1.0));
|
||||
test("17976931348623157e292", Ok(1.7976931348623157E+308));
|
||||
test("17976931348623158e292", Ok(1.7976931348623158E+308));
|
||||
test("1e1", Ok(10.0));
|
||||
test("1e2", Ok(100.0));
|
||||
test(
|
||||
"10141204801825834086073718800384e0",
|
||||
Ok(10141204801825834086073718800384.0),
|
||||
);
|
||||
test(
|
||||
"1014120480182583464902367222169599999e-5",
|
||||
Ok(10141204801825834086073718800384.0),
|
||||
);
|
||||
test(
|
||||
"1014120480182583464902367222169600001e-5",
|
||||
Ok(10141204801825835211973625643008.0),
|
||||
);
|
||||
test(
|
||||
"10141204801825834649023672221696e0",
|
||||
Ok(10141204801825835211973625643008.0),
|
||||
);
|
||||
test(
|
||||
"10141204801825835211973625643008e0",
|
||||
Ok(10141204801825835211973625643008.0),
|
||||
);
|
||||
test("104110013277974872254e-225", Ok(104110013277974872254e-225));
|
||||
test("12345e0", Ok(12345.0));
|
||||
test("12345e1", Ok(123450.0));
|
||||
test("12345e2", Ok(1234500.0));
|
||||
test("12345678901234e0", Ok(12345678901234.0));
|
||||
test("12345678901234e1", Ok(123456789012340.0));
|
||||
test("12345678901234e2", Ok(1234567890123400.0));
|
||||
test("123456789012345e0", Ok(123456789012345.0));
|
||||
test("123456789012345e1", Ok(1234567890123450.0));
|
||||
test("123456789012345e2", Ok(12345678901234500.0));
|
||||
test(
|
||||
"1234567890123456789012345e108",
|
||||
Ok(1234567890123456789012345e108),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e109",
|
||||
Ok(1234567890123456789012345e109),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e110",
|
||||
Ok(1234567890123456789012345e110),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e111",
|
||||
Ok(1234567890123456789012345e111),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e112",
|
||||
Ok(1234567890123456789012345e112),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e113",
|
||||
Ok(1234567890123456789012345e113),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e114",
|
||||
Ok(1234567890123456789012345e114),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789012345e115",
|
||||
Ok(1234567890123456789012345e115),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e108",
|
||||
Ok(1234567890123456789052345e108),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e109",
|
||||
Ok(1234567890123456789052345e109),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e110",
|
||||
Ok(1234567890123456789052345e110),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e111",
|
||||
Ok(1234567890123456789052345e111),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e112",
|
||||
Ok(1234567890123456789052345e112),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e113",
|
||||
Ok(1234567890123456789052345e113),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e114",
|
||||
Ok(1234567890123456789052345e114),
|
||||
);
|
||||
test(
|
||||
"1234567890123456789052345e115",
|
||||
Ok(1234567890123456789052345e115),
|
||||
);
|
||||
test("123456789012345e-1", Ok(123456789012345e-1));
|
||||
test("123456789012345e-2", Ok(123456789012345e-2));
|
||||
test("123456789012345e20", Ok(123456789012345e20));
|
||||
test("123456789012345e-20", Ok(123456789012345e-20));
|
||||
test("123456789012345e22", Ok(123456789012345e22));
|
||||
test("123456789012345e-22", Ok(123456789012345e-22));
|
||||
test("123456789012345e23", Ok(123456789012345e23));
|
||||
test("123456789012345e-23", Ok(123456789012345e-23));
|
||||
test("123456789012345e-25", Ok(123456789012345e-25));
|
||||
test("123456789012345e35", Ok(123456789012345e35));
|
||||
test("123456789012345e36", Ok(123456789012345e36));
|
||||
test("123456789012345e37", Ok(123456789012345e37));
|
||||
test("123456789012345e39", Ok(123456789012345e39));
|
||||
test("123456789012345e-39", Ok(123456789012345e-39));
|
||||
test("123456789012345e-5", Ok(123456789012345e-5));
|
||||
test("12345678901234e-1", Ok(12345678901234e-1));
|
||||
test("12345678901234e-2", Ok(12345678901234e-2));
|
||||
test("12345678901234e20", Ok(12345678901234e20));
|
||||
test("12345678901234e-20", Ok(12345678901234e-20));
|
||||
test("12345678901234e22", Ok(12345678901234e22));
|
||||
test("12345678901234e-22", Ok(12345678901234e-22));
|
||||
test("12345678901234e23", Ok(12345678901234e23));
|
||||
test("12345678901234e-23", Ok(12345678901234e-23));
|
||||
test("12345678901234e-25", Ok(12345678901234e-25));
|
||||
test("12345678901234e30", Ok(12345678901234e30));
|
||||
test("12345678901234e31", Ok(12345678901234e31));
|
||||
test("12345678901234e32", Ok(12345678901234e32));
|
||||
test("12345678901234e35", Ok(12345678901234e35));
|
||||
test("12345678901234e36", Ok(12345678901234e36));
|
||||
test("12345678901234e37", Ok(12345678901234e37));
|
||||
test("12345678901234e-39", Ok(12345678901234e-39));
|
||||
test("12345678901234e-5", Ok(12345678901234e-5));
|
||||
test("123456789e108", Ok(123456789e108));
|
||||
test("123456789e109", Ok(123456789e109));
|
||||
test("123456789e110", Ok(123456789e110));
|
||||
test("123456789e111", Ok(123456789e111));
|
||||
test("123456789e112", Ok(123456789e112));
|
||||
test("123456789e113", Ok(123456789e113));
|
||||
test("123456789e114", Ok(123456789e114));
|
||||
test("123456789e115", Ok(123456789e115));
|
||||
test("12345e-1", Ok(12345e-1));
|
||||
test("12345e-2", Ok(12345e-2));
|
||||
test("12345e20", Ok(12345e20));
|
||||
test("12345e-20", Ok(12345e-20));
|
||||
test("12345e22", Ok(12345e22));
|
||||
test("12345e-22", Ok(12345e-22));
|
||||
test("12345e23", Ok(12345e23));
|
||||
test("12345e-23", Ok(12345e-23));
|
||||
test("12345e-25", Ok(12345e-25));
|
||||
test("12345e30", Ok(12345e30));
|
||||
test("12345e31", Ok(12345e31));
|
||||
test("12345e32", Ok(12345e32));
|
||||
test("12345e35", Ok(12345e35));
|
||||
test("12345e36", Ok(12345e36));
|
||||
test("12345e37", Ok(12345e37));
|
||||
test("12345e-39", Ok(12345e-39));
|
||||
test("12345e-5", Ok(12345e-5));
|
||||
test("000000001234e304", Ok(1234e304));
|
||||
test("0000000123400000e299", Ok(1234e304));
|
||||
test("123400000e299", Ok(1234e304));
|
||||
test("1234e304", Ok(1234e304));
|
||||
test("00000000123400000e300", Ok(1234e305));
|
||||
test("00000001234e305", Ok(1234e305));
|
||||
test("123400000e300", Ok(1234e305));
|
||||
test("1234e305", Ok(1234e305));
|
||||
test("00000000170000000e300", Ok(17e307));
|
||||
test("0000000017e307", Ok(17e307));
|
||||
test("170000000e300", Ok(17e307));
|
||||
test("17e307", Ok(17e307));
|
||||
test("1e-1", Ok(1e-1));
|
||||
test("1e-2", Ok(1e-2));
|
||||
test("1e20", Ok(1e20));
|
||||
test("1e-20", Ok(1e-20));
|
||||
test("1e22", Ok(1e22));
|
||||
test("1e-22", Ok(1e-22));
|
||||
test("1e23", Ok(1e23));
|
||||
test("1e-23", Ok(1e-23));
|
||||
test("1e-25", Ok(1e-25));
|
||||
test("000000000000100000e303", Ok(1e308));
|
||||
test("00000001e308", Ok(1e308));
|
||||
test("100000e303", Ok(1e308));
|
||||
test("1e308", Ok(1e308));
|
||||
test("1e35", Ok(1e35));
|
||||
test("1e36", Ok(1e36));
|
||||
test("1e37", Ok(1e37));
|
||||
test("1e-39", Ok(1e-39));
|
||||
test("1e-5", Ok(1e-5));
|
||||
test("2e0", Ok(2.0));
|
||||
test("22250738585072011e-324", Ok(2.225073858507201e-308));
|
||||
test("2e1", Ok(20.0));
|
||||
test("2e2", Ok(200.0));
|
||||
test("2e-1", Ok(2e-1));
|
||||
test("2e-2", Ok(2e-2));
|
||||
test("2e20", Ok(2e20));
|
||||
test("2e-20", Ok(2e-20));
|
||||
test("2e22", Ok(2e22));
|
||||
test("2e-22", Ok(2e-22));
|
||||
test("2e23", Ok(2e23));
|
||||
test("2e-23", Ok(2e-23));
|
||||
test("2e-25", Ok(2e-25));
|
||||
test("2e35", Ok(2e35));
|
||||
test("2e36", Ok(2e36));
|
||||
test("2e37", Ok(2e37));
|
||||
test("2e-39", Ok(2e-39));
|
||||
test("2e-5", Ok(2e-5));
|
||||
test("358416272e-33", Ok(358416272e-33));
|
||||
test("00000030000e-328", Ok(40000e-328));
|
||||
test("30000e-328", Ok(40000e-328));
|
||||
test("3e-324", Ok(4e-324));
|
||||
test("5445618932859895362967233318697132813618813095743952975439298223406969961560047552942717636670910728746893019786283454139917900193169748259349067524939840552682198095012176093045431437495773903922425632551857520884625114624126588173520906670968542074438852601438992904761759703022688483745081090292688986958251711580854575674815074162979705098246243690189880319928315307816832576838178256307401454285988871020923752587330172447966674453785790265533466496640456213871241930958703059911787722565044368663670643970181259143319016472430928902201239474588139233890135329130660705762320235358869874608541509790266400643191187286648422874774910682648288516244021893172769161449825765517353755844373640588822904791244190695299838293263075467057383813882521706545084301049855505888186560731e-1035", Ok(5.445618932859895e-255));
|
||||
test(
|
||||
"5708990770823838890407843763683279797179383808e0",
|
||||
Ok(5708990770823838890407843763683279797179383808.0),
|
||||
);
|
||||
test(
|
||||
"5708990770823839207320493820740630171355185151999e-3",
|
||||
Ok(5708990770823838890407843763683279797179383808.0),
|
||||
);
|
||||
test(
|
||||
"5708990770823839207320493820740630171355185152001e-3",
|
||||
Ok(5708990770823839524233143877797980545530986496.0),
|
||||
);
|
||||
test(
|
||||
"5708990770823839207320493820740630171355185152e0",
|
||||
Ok(5708990770823839524233143877797980545530986496.0),
|
||||
);
|
||||
test(
|
||||
"5708990770823839524233143877797980545530986496e0",
|
||||
Ok(5708990770823839524233143877797980545530986496.0),
|
||||
);
|
||||
test("72057594037927928e0", Ok(72057594037927928.0));
|
||||
test("7205759403792793199999e-5", Ok(72057594037927928.0));
|
||||
test("7205759403792793200001e-5", Ok(72057594037927936.0));
|
||||
test("72057594037927932e0", Ok(72057594037927936.0));
|
||||
test("72057594037927936e0", Ok(72057594037927936.0));
|
||||
test("89255e-22", Ok(89255e-22));
|
||||
test("9e0", Ok(9.0));
|
||||
test("9e1", Ok(90.0));
|
||||
test("9e2", Ok(900.0));
|
||||
test("9223372036854774784e0", Ok(9223372036854774784.0));
|
||||
test("922337203685477529599999e-5", Ok(9223372036854774784.0));
|
||||
test("922337203685477529600001e-5", Ok(9223372036854775808.0));
|
||||
test("9223372036854775296e0", Ok(9223372036854775808.0));
|
||||
test("9223372036854775808e0", Ok(9223372036854775808.0));
|
||||
test("9e-1", Ok(9e-1));
|
||||
test("9e-2", Ok(9e-2));
|
||||
test("9e20", Ok(9e20));
|
||||
test("9e-20", Ok(9e-20));
|
||||
test("9e22", Ok(9e22));
|
||||
test("9e-22", Ok(9e-22));
|
||||
test("9e23", Ok(9e23));
|
||||
test("9e-23", Ok(9e-23));
|
||||
test("9e-25", Ok(9e-25));
|
||||
test("9e35", Ok(9e35));
|
||||
test("9e36", Ok(9e36));
|
||||
test("9e37", Ok(9e37));
|
||||
test("9e-39", Ok(9e-39));
|
||||
test("9e-5", Ok(9e-5));
|
||||
test("00000000180000000e300", Err(Error::Overflow));
|
||||
test("0000000018e307", Err(Error::Overflow));
|
||||
test("00000001000000e303", Err(Error::Overflow));
|
||||
test("0000001e309", Err(Error::Overflow));
|
||||
test("1000000e303", Err(Error::Overflow));
|
||||
test("17976931348623159e292", Err(Error::Overflow));
|
||||
test("180000000e300", Err(Error::Overflow));
|
||||
test("18e307", Err(Error::Overflow));
|
||||
test("1e309", Err(Error::Overflow));
|
||||
test("1e-409", Ok(0.0));
|
||||
|
||||
test_sep("1,1e1", Ok(1.1e1), ',');
|
||||
|
||||
test_consumed("12345e37randomstuff", Ok(12345e37), 8);
|
||||
}
|
||||
|
||||
fn test(input: &str, val: Result<f64, Error>) {
|
||||
test_sep(input, val, '.')
|
||||
}
|
||||
|
||||
fn test_sep(input: &str, val: Result<f64, Error>, decimalsep: char) {
|
||||
let mut consumed = 0;
|
||||
let result = wcstod(input, decimalsep, &mut consumed);
|
||||
assert_eq!(result, val);
|
||||
if result.is_ok() {
|
||||
assert_eq!(consumed, input.chars().count());
|
||||
assert_eq!(
|
||||
result.unwrap().is_sign_positive(),
|
||||
val.unwrap().is_sign_positive()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_consumed(input: &str, val: Result<f64, Error>, exp_consumed: usize) {
|
||||
let mut consumed = 0;
|
||||
let result = wcstod(input, '.', &mut consumed);
|
||||
assert_eq!(result, val);
|
||||
assert_eq!(consumed, exp_consumed);
|
||||
}
|
||||
}
|
@ -1,13 +1,7 @@
|
||||
pub use super::errors::Error;
|
||||
use num_traits::{NumCast, PrimInt};
|
||||
use std::iter::Peekable;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
Overflow,
|
||||
Empty,
|
||||
InvalidDigit,
|
||||
CharsLeft,
|
||||
}
|
||||
use std::result::Result;
|
||||
|
||||
struct ParseResult {
|
||||
result: u64,
|
||||
@ -98,7 +92,7 @@ where
|
||||
|
||||
// Did we consume at least one char?
|
||||
if !consumed1 {
|
||||
return Err(Error::InvalidDigit);
|
||||
return Err(Error::InvalidChar);
|
||||
}
|
||||
|
||||
// Do not return -0.
|
||||
@ -135,7 +129,7 @@ where
|
||||
} = fish_parse_radix(src, mradix)?;
|
||||
|
||||
if !signed && negative {
|
||||
Err(Error::InvalidDigit)
|
||||
Err(Error::InvalidChar)
|
||||
} else if consume_all && !consumed_all {
|
||||
Err(Error::CharsLeft)
|
||||
} else if !signed || !negative {
|
||||
@ -211,8 +205,8 @@ mod tests {
|
||||
assert_eq!(run1("0"), Ok(0));
|
||||
assert_eq!(run1("-0"), Ok(0));
|
||||
assert_eq!(run1("+0"), Ok(0));
|
||||
assert_eq!(run1("+-0"), Err(Error::InvalidDigit));
|
||||
assert_eq!(run1("-+0"), Err(Error::InvalidDigit));
|
||||
assert_eq!(run1("+-0"), Err(Error::InvalidChar));
|
||||
assert_eq!(run1("-+0"), Err(Error::InvalidChar));
|
||||
assert_eq!(run1("123"), Ok(123));
|
||||
assert_eq!(run1("+123"), Ok(123));
|
||||
assert_eq!(run1("-123"), Ok(-123));
|
||||
@ -225,7 +219,7 @@ mod tests {
|
||||
assert_eq!(run1("-0123"), Ok(-83));
|
||||
assert_eq!(run1(" 345 "), Ok(345));
|
||||
assert_eq!(run1(" -345 "), Ok(-345));
|
||||
assert_eq!(run1(" x345"), Err(Error::InvalidDigit));
|
||||
assert_eq!(run1(" x345"), Err(Error::InvalidChar));
|
||||
assert_eq!(run1("456x"), Ok(456));
|
||||
assert_eq!(run1("456 x"), Ok(456));
|
||||
assert_eq!(run1("99999999999999999999999"), Err(Error::Overflow));
|
||||
|
Loading…
x
Reference in New Issue
Block a user