Add support and tests for Option and reference types
This commit is contained in:
parent
a1baedeb1b
commit
9d909d352a
|
@ -102,6 +102,12 @@ proc skipToken(r: var JsonReader, tk: TokKind) =
|
|||
r.requireToken tk
|
||||
r.lexer.next()
|
||||
|
||||
proc allocPtr[T](p: var ptr T) =
|
||||
p = create(T)
|
||||
|
||||
proc allocPtr[T](p: var ref T) =
|
||||
p = new(T)
|
||||
|
||||
proc readValue*(r: var JsonReader, value: var auto) =
|
||||
mixin readValue
|
||||
|
||||
|
@ -119,6 +125,14 @@ proc readValue*(r: var JsonReader, value: var auto) =
|
|||
else: r.raiseUnexpectedToken etBool
|
||||
r.lexer.next()
|
||||
|
||||
elif value is ref|ptr:
|
||||
if tok == tkNull:
|
||||
value = nil
|
||||
r.lexer.next()
|
||||
else:
|
||||
allocPtr value
|
||||
value[] = readValue(r, type(value[]))
|
||||
|
||||
elif value is enum:
|
||||
case tok
|
||||
of tkString:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import std/net, ../../json_serialization.nim
|
||||
export json_serialization
|
||||
export net
|
||||
|
||||
proc writeValue*(writer: var JsonWriter, value: Port) =
|
||||
writeValue(writer, uint16 value)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import std/options, ../../json_serialization/[reader, writer, lexer]
|
||||
export options
|
||||
|
||||
proc writeValue*(writer: var JsonWriter, value: Option) =
|
||||
if value.isSome:
|
||||
writer.writeValue value.get
|
||||
else:
|
||||
writer.writeValue JsonString("null")
|
||||
|
||||
proc readValue*[T](reader: var JsonReader, value: var Option[T]) =
|
||||
let tok = reader.lexer.tok
|
||||
if tok == tkNull:
|
||||
reset value
|
||||
reader.lexer.next()
|
||||
else:
|
||||
value = some reader.readValue(T)
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import
|
||||
strutils, options, unittest,
|
||||
strutils, unittest,
|
||||
serialization/testing/generic_suite,
|
||||
../json_serialization, ./utils
|
||||
../json_serialization, ./utils,
|
||||
../json_serialization/std/options
|
||||
|
||||
type
|
||||
Meter = distinct int
|
||||
|
@ -20,7 +21,10 @@ type
|
|||
Bar = object
|
||||
sf: seq[Foo]
|
||||
z: ref Simple
|
||||
# o: Option[Simple]
|
||||
|
||||
HoldsOption = object
|
||||
r: ref Simple
|
||||
o: Option[Simple]
|
||||
|
||||
HoldsArray = object
|
||||
data: seq[int]
|
||||
|
@ -37,8 +41,22 @@ template reject(code) =
|
|||
|
||||
borrowSerialization(Meter, int)
|
||||
|
||||
proc `==`(lhs, rhs: Meter): bool =
|
||||
int(lhs) == int(rhs)
|
||||
|
||||
proc `==`(lhs, rhs: ref Simple): bool =
|
||||
if lhs.isNil: return rhs.isNil
|
||||
if rhs.isNil: return false
|
||||
return lhs[] == rhs[]
|
||||
|
||||
executeReaderWriterTests Json
|
||||
|
||||
proc newSimple(x: int, y: string, d: Meter): ref Simple =
|
||||
new result
|
||||
result.x = x
|
||||
result.y = y
|
||||
result.distance = d
|
||||
|
||||
when false:
|
||||
# The compiler cannot handle this check at the moment
|
||||
# {.fatal.} seems fatal even in `compiles` context
|
||||
|
@ -111,3 +129,12 @@ suite "toJson tests":
|
|||
check:
|
||||
r.toJSON == """{"type":"uint8"}"""
|
||||
r == Json.decode("""{"type":"uint8"}""", Reserved)
|
||||
|
||||
test "Option types":
|
||||
let
|
||||
h1 = HoldsOption(o: some Simple(x: 1, y: "2", distance: Meter(3)))
|
||||
h2 = HoldsOption(r: newSimple(1, "2", Meter(3)))
|
||||
|
||||
Json.roundtripTest h1, """{"r":null,"o":{"x":1,"y":"2","distance":3}}"""
|
||||
Json.roundtripTest h2, """{"r":{"x":1,"y":"2","distance":3},"o":null}"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue