Add object encoding/decoding
This commit is contained in:
parent
2db4d48802
commit
aae968ac3b
2 changed files with 32 additions and 17 deletions
|
|
@ -38,13 +38,6 @@ type
|
||||||
proc newProtoBuffer*(): ProtoBuffer =
|
proc newProtoBuffer*(): ProtoBuffer =
|
||||||
ProtoBuffer(outstream: OutputStream.init(), fieldNum: 1)
|
ProtoBuffer(outstream: OutputStream.init(), fieldNum: 1)
|
||||||
|
|
||||||
# Main interface
|
|
||||||
proc encode*(): ProtoBuffer =
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc decode*[T](source: ProtoBuffer): T =
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc output*(proto: ProtoBuffer): seq[byte] {.inline.} =
|
proc output*(proto: ProtoBuffer): seq[byte] {.inline.} =
|
||||||
proto.outstream.getOutput
|
proto.outstream.getOutput
|
||||||
|
|
||||||
|
|
@ -59,6 +52,8 @@ template protoHeader*(fieldNum: int, wire: ProtoWireType): byte =
|
||||||
((cast[uint](fieldNum) shl 3) or cast[uint](wire)).byte
|
((cast[uint](fieldNum) shl 3) or cast[uint](wire)).byte
|
||||||
|
|
||||||
template increaseBytesRead(amount = 1) =
|
template increaseBytesRead(amount = 1) =
|
||||||
|
## Convenience template for increasing
|
||||||
|
## all of the counts
|
||||||
mixin isSome
|
mixin isSome
|
||||||
bytesRead += amount
|
bytesRead += amount
|
||||||
outOffset += amount
|
outOffset += amount
|
||||||
|
|
@ -111,10 +106,14 @@ proc encodeField*(protobuf: var ProtoBuffer, value: SomeLengthDelimited) {.inlin
|
||||||
proc put(stream: OutputStreamVar, value: object) {.inline.}
|
proc put(stream: OutputStreamVar, value: object) {.inline.}
|
||||||
|
|
||||||
proc encodeField(stream: OutputStreamVar, fieldNum: int, value: object) {.inline.} =
|
proc encodeField(stream: OutputStreamVar, fieldNum: int, value: object) {.inline.} =
|
||||||
#TODO Encode generic objects
|
|
||||||
stream.append protoHeader(fieldNum, LengthDelimited)
|
stream.append protoHeader(fieldNum, LengthDelimited)
|
||||||
|
|
||||||
|
# This is currently needed in order to get the size
|
||||||
|
# of the output before adding it to the stream.
|
||||||
|
# Maybe there is a better way to do this
|
||||||
let objStream = OutputStream.init()
|
let objStream = OutputStream.init()
|
||||||
objStream.put(value)
|
objStream.put(value)
|
||||||
|
|
||||||
let objOutput = objStream.getOutput()
|
let objOutput = objStream.getOutput()
|
||||||
stream.put(len(objOutput).uint)
|
stream.put(len(objOutput).uint)
|
||||||
stream.put(objOutput)
|
stream.put(objOutput)
|
||||||
|
|
@ -123,11 +122,17 @@ proc encodeField*(protobuf: var ProtoBuffer, value: object) {.inline.} =
|
||||||
protobuf.outstream.encodeField(protobuf.fieldNum, value)
|
protobuf.outstream.encodeField(protobuf.fieldNum, value)
|
||||||
inc protobuf.fieldNum
|
inc protobuf.fieldNum
|
||||||
|
|
||||||
|
proc encode*(protobuf: var ProtoBuffer, value: object) {.inline.} =
|
||||||
|
var fieldNum = 1
|
||||||
|
for field, val in value.fieldPairs:
|
||||||
|
protobuf.outstream.encodeField(fieldNum, val)
|
||||||
|
inc fieldNum
|
||||||
|
|
||||||
proc put(stream: OutputStreamVar, value: object) {.inline.} =
|
proc put(stream: OutputStreamVar, value: object) {.inline.} =
|
||||||
var fieldNum = 1
|
var fieldNum = 1
|
||||||
for field, val in value.fieldPairs:
|
for field, val in value.fieldPairs:
|
||||||
stream.encodeField(fieldNum, val)
|
stream.encodeField(fieldNum, val)
|
||||||
fieldNum += 1
|
inc fieldNum
|
||||||
|
|
||||||
proc getVarint[T: SomeVarint](
|
proc getVarint[T: SomeVarint](
|
||||||
bytes: var seq[byte],
|
bytes: var seq[byte],
|
||||||
|
|
@ -320,7 +325,7 @@ proc decodeField*[T: object](
|
||||||
let bytesToRead = some(decodedSize.int)
|
let bytesToRead = some(decodedSize.int)
|
||||||
for field, val in result.value.fieldPairs:
|
for field, val in result.value.fieldPairs:
|
||||||
setField(result.value, index, outOffset, outBytesProcessed, bytesToRead, bytes)
|
setField(result.value, index, outOffset, outBytesProcessed, bytesToRead, bytes)
|
||||||
index += 1
|
inc index
|
||||||
|
|
||||||
proc decode*[T: object](
|
proc decode*[T: object](
|
||||||
bytes: var seq[byte],
|
bytes: var seq[byte],
|
||||||
|
|
@ -332,4 +337,4 @@ proc decode*[T: object](
|
||||||
var fieldNum = 1
|
var fieldNum = 1
|
||||||
for field, val in result.fieldPairs:
|
for field, val in result.fieldPairs:
|
||||||
setField(result, fieldNum, offset, bytesRead, none(int), bytes)
|
setField(result, fieldNum, offset, bytesRead, none(int), bytes)
|
||||||
fieldNum += 1
|
inc fieldNum
|
||||||
|
|
@ -15,7 +15,7 @@ type
|
||||||
i: Test1
|
i: Test1
|
||||||
|
|
||||||
suite "Test Varint Encoding":
|
suite "Test Varint Encoding":
|
||||||
test "Can encode/decode enum":
|
test "Can encode/decode enum field":
|
||||||
var proto = newProtoBuffer()
|
var proto = newProtoBuffer()
|
||||||
var bytesProcessed: int
|
var bytesProcessed: int
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ suite "Test Varint Encoding":
|
||||||
assert decodedME2.value == ME2
|
assert decodedME2.value == ME2
|
||||||
assert decodedME2.index == 2
|
assert decodedME2.index == 2
|
||||||
|
|
||||||
test "Can encode/decode negative number":
|
test "Can encode/decode negative number field":
|
||||||
var proto = newProtoBuffer()
|
var proto = newProtoBuffer()
|
||||||
let num = -153452
|
let num = -153452
|
||||||
var bytesProcessed: int
|
var bytesProcessed: int
|
||||||
|
|
@ -50,7 +50,7 @@ suite "Test Varint Encoding":
|
||||||
assert decoded.value == num
|
assert decoded.value == num
|
||||||
assert decoded.index == 1
|
assert decoded.index == 1
|
||||||
|
|
||||||
test "Can encode/decode unsigned number":
|
test "Can encode/decode unsigned number field":
|
||||||
var proto = newProtoBuffer()
|
var proto = newProtoBuffer()
|
||||||
let num = 123151.uint
|
let num = 123151.uint
|
||||||
var bytesProcessed: int
|
var bytesProcessed: int
|
||||||
|
|
@ -65,7 +65,7 @@ suite "Test Varint Encoding":
|
||||||
assert decoded.value == num
|
assert decoded.value == num
|
||||||
assert decoded.index == 1
|
assert decoded.index == 1
|
||||||
|
|
||||||
test "Can encode/decode string":
|
test "Can encode/decode string field":
|
||||||
var proto = newProtoBuffer()
|
var proto = newProtoBuffer()
|
||||||
let str = "hey this is a string"
|
let str = "hey this is a string"
|
||||||
var bytesProcessed: int
|
var bytesProcessed: int
|
||||||
|
|
@ -80,7 +80,7 @@ suite "Test Varint Encoding":
|
||||||
assert decoded.value == str
|
assert decoded.value == str
|
||||||
assert decoded.index == 1
|
assert decoded.index == 1
|
||||||
|
|
||||||
test "Can encode/decode object":
|
test "Can encode/decode object field":
|
||||||
var proto = newProtoBuffer()
|
var proto = newProtoBuffer()
|
||||||
|
|
||||||
let obj = Test3(g: 300, h: 200, i: Test1(a: 100))
|
let obj = Test3(g: 300, h: 200, i: Test1(a: 100))
|
||||||
|
|
@ -92,3 +92,13 @@ suite "Test Varint Encoding":
|
||||||
let decoded = decodeField(output, Test3, offset, bytesProcessed)
|
let decoded = decodeField(output, Test3, offset, bytesProcessed)
|
||||||
assert decoded.value == obj
|
assert decoded.value == obj
|
||||||
assert decoded.index == 1
|
assert decoded.index == 1
|
||||||
|
|
||||||
|
test "Can encode/decode object":
|
||||||
|
var proto = newProtoBuffer()
|
||||||
|
|
||||||
|
let obj = Test3(g: 300, h: 200, i: Test1(a: 100))
|
||||||
|
|
||||||
|
proto.encode(obj)
|
||||||
|
var output = proto.output
|
||||||
|
let decoded = output.decode(Test3)
|
||||||
|
assert decoded == obj
|
||||||
Loading…
Add table
Add a link
Reference in a new issue