diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-10 19:11:16 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-10 19:11:16 +0300 |
| commit | d6896cabcbe3b774c7a6864875803a35c20eae54 (patch) | |
| tree | 399bed79dccb4b310d7da262b062aa0b44c61b45 /src | |
| parent | 6bc6304143588d063f5b4cf05ec30443814957e1 (diff) | |
| download | nimpb-d6896cabcbe3b774c7a6864875803a35c20eae54.tar.gz nimpb-d6896cabcbe3b774c7a6864875803a35c20eae54.zip | |
Fixes to JSON parsing
Diffstat (limited to 'src')
| -rw-r--r-- | src/nimpb/json.nim | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/src/nimpb/json.nim b/src/nimpb/json.nim index 826569d..6079e37 100644 --- a/src/nimpb/json.nim +++ b/src/nimpb/json.nim @@ -16,7 +16,7 @@ import wkt/struct_pb import wkt/any_pb type - JsonParseError = object of nimpb.ParseError + JsonParseError* = object of nimpb.ParseError proc `%`*(u: uint32): JsonNode = newJFloat(float(u)) @@ -235,45 +235,73 @@ proc parseEnum*[T](node: JsonNode): T = else: raise newException(ValueError, "invalid enum value") -proc parseFloat*(node: JsonNode): float = +proc parseFloat*[T: float32|float64](node: JsonNode): T = if node.kind == JString: if node.str == "NaN": - result = NaN + return NaN elif node.str == "Infinity": - result = Inf + return Inf elif node.str == "-Infinity": - result = NegInf + return NegInf else: - result = parseFloat(node.str) + result = T(parseFloat(node.str)) else: - result = getFloat(node) + result = T(getFloat(node)) + + case classify(result) + of fcInf: raise newException(JsonParseError, "invalid floating point number") + of fcNegInf: raise newException(JsonParseError, "invalid floating point number") + of fcNan: raise newException(JsonParseError, "invalid floating point number") + else: discard proc parseInt*[T: int32|int64](node: JsonNode): T = + var big: BiggestInt + if node.kind == JString: - result = T(parseBiggestInt(node.str)) + try: + big = parseBiggestInt(node.str) + except Exception as exc: + raise newException(JsonParseError, exc.msg) elif node.kind == JInt: - result = T(getBiggestInt(node)) + big = getBiggestInt(node) elif node.kind == JFloat: let f = getFloat(node) if trunc(f) != f: raise newException(JsonParseError, "not an integer") - result = T(f) + big = BiggestInt(f) else: raise newException(JsonParseError, "not an integer") + if big < BiggestInt(low(T)) or big > BiggestInt(high(T)): + raise newException(JsonParseError, "integer out of bounds") + + result = T(big) + +proc high(t: typedesc[uint64]): uint64 = 18446744073709551615'u64 + proc parseInt*[T: uint32|uint64](node: JsonNode): T = + var big: BiggestUInt + if node.kind == JString: - result = T(parseBiggestUInt(node.str)) + try: + big = parseBiggestUInt(node.str) + except Exception as exc: + raise newException(JsonParseError, exc.msg) elif node.kind == JInt: - result = T(getBiggestInt(node)) + big = BiggestUInt(getBiggestInt(node)) elif node.kind == JFloat: let f = getFloat(node) if trunc(f) != f: raise newException(JsonParseError, "not an integer") - result = T(f) + big = BiggestUInt(f) else: raise newException(JsonParseError, "not an integer") + if big > BiggestUInt(high(T)): + raise newException(JsonParseError, "integer out of bounds") + + result = T(big) + proc parseString*(node: JsonNode): string = if node.kind != JString: raise newException(JsonParseError, "not a string") |
