aboutsummaryrefslogtreecommitdiff
path: root/lib/std/json.zig
diff options
context:
space:
mode:
authorominitay <37453713+ominitay@users.noreply.github.com>2022-07-15 22:05:35 +0100
committerVeikka Tuominen <git@vexu.eu>2022-07-23 13:52:16 +0300
commit889efddd1a2b12d3348f06900436b9ba8c823a01 (patch)
tree16e0500940e8273e718ab704f07711bb4089f993 /lib/std/json.zig
parenta8bfddfaeae4f48c044fd134aac1e977e6a161f8 (diff)
downloadzig-889efddd1a2b12d3348f06900436b9ba8c823a01.tar.gz
zig-889efddd1a2b12d3348f06900436b9ba8c823a01.zip
std.json: Fix parsing of large numbers
Numbers greater than about 2^53 are encoded as strings in JSON. std.json.parseInternal previously errored out in this condition.
Diffstat (limited to 'lib/std/json.zig')
-rw-r--r--lib/std/json.zig40
1 files changed, 27 insertions, 13 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig
index 9f678fb4aa..baf93af47c 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -1422,23 +1422,37 @@ fn parseInternal(
};
},
.Float, .ComptimeFloat => {
- const numberToken = switch (token) {
- .Number => |n| n,
+ switch (token) {
+ .Number => |numberToken| return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1)),
+ .String => |stringToken| return try std.fmt.parseFloat(T, stringToken.slice(tokens.slice, tokens.i - 1)),
else => return error.UnexpectedToken,
- };
- return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1));
+ }
},
.Int, .ComptimeInt => {
- const numberToken = switch (token) {
- .Number => |n| n,
+ switch (token) {
+ .Number => |numberToken| {
+ 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 (@round(float) != float) return error.InvalidNumber;
+ if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow;
+ return @floatToInt(T, float);
+ },
+ .String => |stringToken| {
+ return std.fmt.parseInt(T, stringToken.slice(tokens.slice, tokens.i - 1), 10) catch |err| {
+ switch (err) {
+ error.Overflow => return err,
+ error.InvalidCharacter => {
+ const float = try std.fmt.parseFloat(f128, stringToken.slice(tokens.slice, tokens.i - 1));
+ if (@round(float) != float) return error.InvalidNumber;
+ if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow;
+ return @floatToInt(T, float);
+ },
+ }
+ };
+ },
else => return error.UnexpectedToken,
- };
- 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 (@round(float) != float) return error.InvalidNumber;
- if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow;
- return @floatToInt(T, float);
+ }
},
.Optional => |optionalInfo| {
if (token == .Null) {