aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2018-04-10 19:11:16 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2018-04-10 19:11:16 +0300
commitd6896cabcbe3b774c7a6864875803a35c20eae54 (patch)
tree399bed79dccb4b310d7da262b062aa0b44c61b45 /src
parent6bc6304143588d063f5b4cf05ec30443814957e1 (diff)
downloadnimpb-d6896cabcbe3b774c7a6864875803a35c20eae54.tar.gz
nimpb-d6896cabcbe3b774c7a6864875803a35c20eae54.zip
Fixes to JSON parsing
Diffstat (limited to 'src')
-rw-r--r--src/nimpb/json.nim54
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")