Skip to content

Commit 3cfa6de

Browse files
committed
Add a proper public-facing API with Result etc
1 parent bb1677c commit 3cfa6de

File tree

4 files changed

+76
-21
lines changed

4 files changed

+76
-21
lines changed

extras/simple-bench/src/main.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use fastrand::Rng;
1010
use lexical::FromLexical;
1111
use structopt::StructOpt;
1212

13-
use fast_float::Float;
13+
use fast_float::ParseFloat;
1414

1515
use random::RandomGen;
1616

@@ -66,7 +66,7 @@ struct BenchResult {
6666
pub times: Vec<i64>,
6767
}
6868

69-
fn run_one_bench<T: Float, F: Fn(&str) -> T>(
69+
fn run_one_bench<T: ParseFloat, F: Fn(&str) -> T>(
7070
name: &str,
7171
inputs: &[String],
7272
repeat: usize,
@@ -87,15 +87,11 @@ fn run_one_bench<T: Float, F: Fn(&str) -> T>(
8787
BenchResult { name, times }
8888
}
8989

90-
fn run_all_benches<T: Float + FromLexical + FromStr>(
90+
fn run_all_benches<T: ParseFloat + FromLexical + FromStr>(
9191
inputs: &[String],
9292
repeat: usize,
9393
) -> Vec<BenchResult> {
94-
let ff_func = |s: &str| {
95-
fast_float::parse_float::<T>(s.as_bytes())
96-
.unwrap_or_default()
97-
.0
98-
};
94+
let ff_func = |s: &str| fast_float::parse_partial::<T, _>(s).unwrap_or_default().0;
9995
let ff_res = run_one_bench("fast_float", inputs, repeat, ff_func);
10096

10197
let lex_func = |s: &str| {

src/lib.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::error::Error as StdError;
2+
use std::fmt::{self, Display};
3+
14
mod binary;
25
mod common;
36
mod decimal;
@@ -8,7 +11,70 @@ mod parse;
811
mod simple;
912

1013
pub use format::FloatFormat;
11-
pub use parse::{parse_float, parse_float_fmt};
1214

13-
#[doc(hidden)]
14-
pub use float::Float;
15+
/// Opaque error type for fast-float parsing functions.
16+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17+
pub struct Error;
18+
19+
impl Display for Error {
20+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21+
write!(f, "error while parsing a float")
22+
}
23+
}
24+
25+
impl StdError for Error {}
26+
27+
/// Result type alias for fast-float parsing functions.
28+
pub type Result<T> = std::result::Result<T, Error>;
29+
30+
pub trait ParseFloat: float::Float {
31+
#[inline]
32+
fn parse_float<S: AsRef<[u8]>>(s: S) -> Result<Self> {
33+
Self::parse_float_fmt(s, FloatFormat::default())
34+
}
35+
36+
#[inline]
37+
fn parse_float_partial<S: AsRef<[u8]>>(s: S) -> Result<(Self, usize)> {
38+
Self::parse_float_partial_fmt(s, FloatFormat::default())
39+
}
40+
41+
#[inline]
42+
fn parse_float_fmt<S: AsRef<[u8]>>(s: S, fmt: FloatFormat) -> Result<Self> {
43+
let s = s.as_ref();
44+
match Self::parse_float_partial_fmt(s, fmt) {
45+
Ok((v, n)) if n == s.len() => Ok(v),
46+
_ => Err(Error),
47+
}
48+
}
49+
50+
#[inline]
51+
fn parse_float_partial_fmt<S: AsRef<[u8]>>(s: S, fmt: FloatFormat) -> Result<(Self, usize)> {
52+
parse::parse_float_fmt(s.as_ref(), fmt).ok_or(Error)
53+
}
54+
}
55+
56+
impl ParseFloat for f32 {}
57+
impl ParseFloat for f64 {}
58+
59+
#[inline]
60+
pub fn parse<T: ParseFloat, S: AsRef<[u8]>>(s: S) -> Result<T> {
61+
T::parse_float(s)
62+
}
63+
64+
#[inline]
65+
pub fn parse_fmt<T: ParseFloat, S: AsRef<[u8]>>(s: S, fmt: FloatFormat) -> Result<T> {
66+
T::parse_float_fmt(s, fmt)
67+
}
68+
69+
#[inline]
70+
pub fn parse_partial<T: ParseFloat, S: AsRef<[u8]>>(s: S) -> Result<(T, usize)> {
71+
T::parse_float_partial(s)
72+
}
73+
74+
#[inline]
75+
pub fn parse_partial_fmt<T: ParseFloat, S: AsRef<[u8]>>(
76+
s: S,
77+
fmt: FloatFormat,
78+
) -> Result<(T, usize)> {
79+
T::parse_float_partial_fmt(s, fmt)
80+
}

src/parse.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,3 @@ pub fn parse_float_fmt<F: Float>(mut s: &[u8], fmt: FloatFormat) -> Option<(F, u
4747

4848
Some((value, rest))
4949
}
50-
51-
#[inline]
52-
pub fn parse_float<F: Float>(s: &[u8]) -> Option<(F, usize)> {
53-
parse_float_fmt(s, Default::default())
54-
}

tests/test_basic.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ macro_rules! check {
1313
check!($ty, $s, <$ty>::NEG_INFINITY)
1414
}};
1515
($ty:ty, $s:expr, $e:expr) => {{
16-
// eprintln!("\n\nCHECKING: {:?}", $s);
1716
let s = $s.as_bytes();
18-
let (result, n) = fast_float::parse_float::<$ty>(s).unwrap();
19-
assert_eq!(n, s.len());
2017
let expected: $ty = $e;
18+
let result = fast_float::parse::<$ty, _>(s).unwrap();
2119
assert_eq!(result, expected);
2220
let lex = lexical_core::parse::<$ty>(s).unwrap();
2321
assert_eq!(result, lex);
@@ -375,7 +373,7 @@ fn test_f64_pow10() {
375373
for i in -308..=308 {
376374
let s = format!("1e{}", i);
377375
let v = f64::from_str(&s).unwrap();
378-
assert_eq!(fast_float::parse_float::<f64>(s.as_bytes()).unwrap().0, v);
376+
assert_eq!(fast_float::parse::<f64, _>(s).unwrap(), v);
379377
}
380378
}
381379

@@ -384,6 +382,6 @@ fn test_f32_pow10() {
384382
for i in -38..=38 {
385383
let s = format!("1e{}", i);
386384
let v = f32::from_str(&s).unwrap();
387-
assert_eq!(fast_float::parse_float::<f32>(s.as_bytes()).unwrap().0, v);
385+
assert_eq!(fast_float::parse::<f32, _>(s).unwrap(), v);
388386
}
389387
}

0 commit comments

Comments
 (0)