Add object encoding/decoding

This commit is contained in:
Joey Yakimowich-Payne 2020-04-03 19:13:11 -06:00
commit aae968ac3b
2 changed files with 32 additions and 17 deletions

View file

@ -38,13 +38,6 @@ type
proc newProtoBuffer*(): ProtoBuffer =
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.} =
proto.outstream.getOutput
@ -59,6 +52,8 @@ template protoHeader*(fieldNum: int, wire: ProtoWireType): byte =
((cast[uint](fieldNum) shl 3) or cast[uint](wire)).byte
template increaseBytesRead(amount = 1) =
## Convenience template for increasing
## all of the counts
mixin isSome
bytesRead += amount
outOffset += amount
@ -111,10 +106,14 @@ proc encodeField*(protobuf: var ProtoBuffer, value: SomeLengthDelimited) {.inlin
proc put(stream: OutputStreamVar, value: object) {.inline.}
proc encodeField(stream: OutputStreamVar, fieldNum: int, value: object) {.inline.} =
#TODO Encode generic objects
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()
objStream.put(value)
let objOutput = objStream.getOutput()
stream.put(len(objOutput).uint)
stream.put(objOutput)
@ -123,11 +122,17 @@ proc encodeField*(protobuf: var ProtoBuffer, value: object) {.inline.} =
protobuf.outstream.encodeField(protobuf.fieldNum, value)
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.} =
var fieldNum = 1
for field, val in value.fieldPairs:
stream.encodeField(fieldNum, val)
fieldNum += 1
inc fieldNum
proc getVarint[T: SomeVarint](
bytes: var seq[byte],
@ -320,7 +325,7 @@ proc decodeField*[T: object](
let bytesToRead = some(decodedSize.int)
for field, val in result.value.fieldPairs:
setField(result.value, index, outOffset, outBytesProcessed, bytesToRead, bytes)
index += 1
inc index
proc decode*[T: object](
bytes: var seq[byte],
@ -332,4 +337,4 @@ proc decode*[T: object](
var fieldNum = 1
for field, val in result.fieldPairs:
setField(result, fieldNum, offset, bytesRead, none(int), bytes)
fieldNum += 1
inc fieldNum

View file

@ -15,7 +15,7 @@ type
i: Test1
suite "Test Varint Encoding":
test "Can encode/decode enum":
test "Can encode/decode enum field":
var proto = newProtoBuffer()
var bytesProcessed: int
@ -35,7 +35,7 @@ suite "Test Varint Encoding":
assert decodedME2.value == ME2
assert decodedME2.index == 2
test "Can encode/decode negative number":
test "Can encode/decode negative number field":
var proto = newProtoBuffer()
let num = -153452
var bytesProcessed: int
@ -50,7 +50,7 @@ suite "Test Varint Encoding":
assert decoded.value == num
assert decoded.index == 1
test "Can encode/decode unsigned number":
test "Can encode/decode unsigned number field":
var proto = newProtoBuffer()
let num = 123151.uint
var bytesProcessed: int
@ -65,7 +65,7 @@ suite "Test Varint Encoding":
assert decoded.value == num
assert decoded.index == 1
test "Can encode/decode string":
test "Can encode/decode string field":
var proto = newProtoBuffer()
let str = "hey this is a string"
var bytesProcessed: int
@ -80,7 +80,7 @@ suite "Test Varint Encoding":
assert decoded.value == str
assert decoded.index == 1
test "Can encode/decode object":
test "Can encode/decode object field":
var proto = newProtoBuffer()
let obj = Test3(g: 300, h: 200, i: Test1(a: 100))
@ -91,4 +91,14 @@ suite "Test Varint Encoding":
var output = proto.output
let decoded = decodeField(output, Test3, offset, bytesProcessed)
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