aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorEmil Lerch <emil@lerch.org>2021-06-24 17:07:58 -0700
committerVeikka Tuominen <git@vexu.eu>2021-06-26 10:10:36 +0300
commit2ac769eab9b7dba4cd38e5de01dfa6400f7ebd5b (patch)
treee6f6bf4b763c9a22c5b6dcf69ec5ac52efb51d19 /lib/std
parentdacc5e624eb28570fe517b1f00ddc6287e2c5249 (diff)
downloadzig-2ac769eab9b7dba4cd38e5de01dfa6400f7ebd5b.tar.gz
zig-2ac769eab9b7dba4cd38e5de01dfa6400f7ebd5b.zip
allow json scientific notation to coerce to integers as long as they actually resolve to int type
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/json.zig18
1 files changed, 14 insertions, 4 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig
index 8759469327..7cce202634 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -1551,8 +1551,11 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
.Number => |n| n,
else => return error.UnexpectedToken,
};
- if (!numberToken.is_integer) return error.UnexpectedToken;
- return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10);
+ if (numberToken.is_integer)
+ return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10);
+ const float = try std.fmt.parseFloat(f128, numberToken.slice(tokens.slice, tokens.i - 1));
+ if (std.math.round(float) != float) return error.InvalidNumber;
+ return @floatToInt(T, float);
},
.Optional => |optionalInfo| {
if (token == .Null) {
@@ -2122,8 +2125,8 @@ test "parse into struct with duplicate field" {
const T1 = struct { a: *u64 };
// both .UseFirst and .UseLast should fail because second "a" value isn't a u64
- try testing.expectError(error.UnexpectedToken, parse(T1, &TokenStream.init(str), options_first));
- try testing.expectError(error.UnexpectedToken, parse(T1, &TokenStream.init(str), options_last));
+ try testing.expectError(error.InvalidNumber, parse(T1, &TokenStream.init(str), options_first));
+ try testing.expectError(error.InvalidNumber, parse(T1, &TokenStream.init(str), options_last));
const T2 = struct { a: f64 };
try testing.expectEqual(T2{ .a = 1.0 }, try parse(T2, &TokenStream.init(str), options_first));
@@ -2609,6 +2612,13 @@ test "integer after float has proper type" {
try std.testing.expect(json.Object.get("ints").?.Array.items[0] == .Integer);
}
+test "parse exponential into int" {
+ const T = struct { int: i64 };
+ const r = try parse(T, &TokenStream.init("{ \"int\": 4.2e2 }"), ParseOptions{});
+ try testing.expectEqual(@as(i64, 420), r.int);
+ try testing.expectError(error.InvalidNumber, parse(T, &TokenStream.init("{ \"int\": 0.042e2 }"), ParseOptions{}));
+}
+
test "escaped characters" {
var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena_allocator.deinit();