Skip to content

Commit fbeea61

Browse files
richarddavisonLicenser
authored andcommitted
Treat big ints as floats
1 parent 7a2d44f commit fbeea61

3 files changed

Lines changed: 47 additions & 15 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ bench-canada = []
129129
bench-citm_catalog = []
130130
bench-log = []
131131
bench-twitter = []
132+
big-int-as-float = []
132133

133134
[[example]]
134135
name = "perf"

src/numberparse/correct.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ macro_rules! err {
2424
};
2525
}
2626

27+
macro_rules! check_overflow {
28+
($overflowed:ident, $buf:ident, $idx:ident, $start_idx:ident, $end_index:ident) => {
29+
if $overflowed {
30+
#[cfg(not(feature = "big-int-as-float"))]
31+
{
32+
err!($idx, get!($buf, $idx))
33+
}
34+
#[cfg(feature = "big-int-as-float")]
35+
{
36+
return f64_from_parts_slow(
37+
unsafe { $buf.get_kinda_unchecked($start_idx..$end_index) },
38+
$start_idx,
39+
);
40+
}
41+
}
42+
};
43+
}
44+
2745
#[cfg_attr(not(feature = "no-inline"), inline)]
2846
#[allow(clippy::cast_possible_truncation)]
2947
fn multiply_as_u128(a: u64, b: u64) -> (u64, u64) {
@@ -166,7 +184,7 @@ impl<'de> Deserializer<'de> {
166184
start_idx,
167185
)
168186
} else if unlikely!(digit_count >= 18) {
169-
parse_large_integer(start_idx, buf, negative)
187+
parse_large_integer(start_idx, buf, negative, idx)
170188
} else if is_structural_or_whitespace(get!(buf, idx)) == 0 {
171189
err!(idx, get!(buf, idx))
172190
} else {
@@ -182,7 +200,12 @@ impl<'de> Deserializer<'de> {
182200
#[cfg(not(feature = "128bit"))]
183201
#[cold]
184202
#[allow(clippy::cast_possible_wrap)]
185-
fn parse_large_integer(start_idx: usize, buf: &[u8], negative: bool) -> Result<StaticNode> {
203+
fn parse_large_integer(
204+
start_idx: usize,
205+
buf: &[u8],
206+
negative: bool,
207+
#[allow(unused_variables)] end_index: usize,
208+
) -> Result<StaticNode> {
186209
let mut idx = start_idx;
187210
if negative {
188211
idx += 1;
@@ -197,16 +220,12 @@ fn parse_large_integer(start_idx: usize, buf: &[u8], negative: bool) -> Result<S
197220
let digit = u64::from(get!(buf, idx) - b'0');
198221
{
199222
let (res, overflowed) = 10_u64.overflowing_mul(num);
200-
if overflowed {
201-
err!(idx, get!(buf, idx))
202-
}
223+
check_overflow!(overflowed, buf, idx, start_idx, end_index);
203224
num = res;
204225
}
205226
{
206227
let (res, overflowed) = num.overflowing_add(digit);
207-
if overflowed {
208-
err!(idx, get!(buf, idx))
209-
}
228+
check_overflow!(overflowed, buf, idx, start_idx, end_index);
210229
num = res;
211230
}
212231
idx += 1;
@@ -224,7 +243,12 @@ fn parse_large_integer(start_idx: usize, buf: &[u8], negative: bool) -> Result<S
224243
#[cfg(feature = "128bit")]
225244
#[cold]
226245
#[allow(clippy::cast_possible_wrap)]
227-
fn parse_large_integer(start_idx: usize, buf: &[u8], negative: bool) -> Result<StaticNode> {
246+
fn parse_large_integer(
247+
start_idx: usize,
248+
buf: &[u8],
249+
negative: bool,
250+
end_index: usize,
251+
) -> Result<StaticNode> {
228252
let mut idx = start_idx;
229253
if negative {
230254
idx += 1;
@@ -239,16 +263,12 @@ fn parse_large_integer(start_idx: usize, buf: &[u8], negative: bool) -> Result<S
239263
let digit = u128::from(get!(buf, idx) - b'0');
240264
{
241265
let (res, overflowed) = 10_u128.overflowing_mul(num);
242-
if overflowed {
243-
err!(idx, get!(buf, idx))
244-
}
266+
check_overflow!(overflowed, buf, idx, start_idx, end_index);
245267
num = res;
246268
}
247269
{
248270
let (res, overflowed) = num.overflowing_add(digit);
249-
if overflowed {
250-
err!(idx, get!(buf, idx))
251-
}
271+
check_overflow!(overflowed, buf, idx, start_idx, end_index);
252272
num = res;
253273
}
254274
idx += 1;
@@ -542,4 +562,14 @@ mod test {
542562
assert_eq!(to_value_from_str("-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000596916642387374")?, Static(F64(-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000596916642387374)));
543563
Ok(())
544564
}
565+
566+
#[test]
567+
#[cfg(feature = "big-int-as-float")]
568+
fn huge_int() -> Result<(), crate::Error> {
569+
assert_eq!(
570+
to_value_from_str("999999999999999999999999999999")?,
571+
Static(F64(999999999999999999999999999999f64))
572+
);
573+
Ok(())
574+
}
545575
}

tests/jsonchecker.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ fail!(fail67);
145145
fail!(fail68);
146146
// This is not a failure on 128bit parsing
147147
#[cfg(not(feature = "128bit"))]
148+
#[cfg(not(feature = "big-int-as-float"))]
148149
fail!(fail69);
149150

150151
fail!(fail70);

0 commit comments

Comments
 (0)