Add support and tests for Option and reference types

This commit is contained in:
Zahary Karadjov 2019-06-24 17:38:37 +03:00
parent a1baedeb1b
commit 9d909d352a
4 changed files with 62 additions and 4 deletions

View File

@ -102,6 +102,12 @@ proc skipToken(r: var JsonReader, tk: TokKind) =
r.requireToken tk r.requireToken tk
r.lexer.next() 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) = proc readValue*(r: var JsonReader, value: var auto) =
mixin readValue mixin readValue
@ -119,6 +125,14 @@ proc readValue*(r: var JsonReader, value: var auto) =
else: r.raiseUnexpectedToken etBool else: r.raiseUnexpectedToken etBool
r.lexer.next() 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: elif value is enum:
case tok case tok
of tkString: of tkString:

View File

@ -1,5 +1,5 @@
import std/net, ../../json_serialization.nim import std/net, ../../json_serialization.nim
export json_serialization export net
proc writeValue*(writer: var JsonWriter, value: Port) = proc writeValue*(writer: var JsonWriter, value: Port) =
writeValue(writer, uint16 value) writeValue(writer, uint16 value)

View File

@ -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)

View File

@ -1,7 +1,8 @@
import import
strutils, options, unittest, strutils, unittest,
serialization/testing/generic_suite, serialization/testing/generic_suite,
../json_serialization, ./utils ../json_serialization, ./utils,
../json_serialization/std/options
type type
Meter = distinct int Meter = distinct int
@ -20,7 +21,10 @@ type
Bar = object Bar = object
sf: seq[Foo] sf: seq[Foo]
z: ref Simple z: ref Simple
# o: Option[Simple]
HoldsOption = object
r: ref Simple
o: Option[Simple]
HoldsArray = object HoldsArray = object
data: seq[int] data: seq[int]
@ -37,8 +41,22 @@ template reject(code) =
borrowSerialization(Meter, int) 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 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: when false:
# The compiler cannot handle this check at the moment # The compiler cannot handle this check at the moment
# {.fatal.} seems fatal even in `compiles` context # {.fatal.} seems fatal even in `compiles` context
@ -111,3 +129,12 @@ suite "toJson tests":
check: check:
r.toJSON == """{"type":"uint8"}""" r.toJSON == """{"type":"uint8"}"""
r == Json.decode("""{"type":"uint8"}""", Reserved) 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}"""