From ec0e5a190a4b165bf8b65801fa9e67fd9b15a60c Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 14 Mar 2020 21:00:19 -0600 Subject: [PATCH] Add tests, fix unsigned int --- protobuf_serialization.nim | 34 +++++++++++++------------- tests/config.nims | 2 +- tests/test_serialization.nim | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 tests/test_serialization.nim diff --git a/protobuf_serialization.nim b/protobuf_serialization.nim index 8cbf33b..e31be9a 100644 --- a/protobuf_serialization.nim +++ b/protobuf_serialization.nim @@ -41,6 +41,9 @@ proc encode*(): ProtoBuffer = proc decode*[T](source: ProtoBuffer): T = discard +proc output*(proto: ProtoBuffer): seq[byte] {.inline.} = + proto.outstream.getOutput + template wireType(firstByte: byte): ProtoWireType = (firstByte and 0b111).ProtoWireType @@ -73,11 +76,11 @@ proc encodeVarint(stream: OutputStreamVar, fieldNum: int, value: SomeVarint) {.i value = value shr 7 stream.append byte(value and 0b1111_1111) -proc encode(protobuf: ProtoBuffer, value: SomeVarint) {.inline.} = +proc encode*(protobuf: ProtoBuffer, value: SomeVarint) {.inline.} = protobuf.outstream.encodeVarint(protobuf.fieldNum, value) inc protobuf.fieldNum -proc decode[T: SomeVarint](bytes: var seq[byte], ty: typedesc[T], offset = 0): tuple[fieldNum: uint, value: T] {.inline.} = +proc decode*[T: SomeVarint](bytes: var seq[byte], ty: typedesc[T], offset = 0): tuple[fieldNum: uint, value: T, bytesProcessed: int] {.inline.} = # Only up to 128 bits supported by the spec assert (bytes.len - 1) <= 16 @@ -86,28 +89,25 @@ proc decode[T: SomeVarint](bytes: var seq[byte], ty: typedesc[T], offset = 0): t raise newException(Exception, "Not a varint!") result.fieldNum = fieldNumber(bytes[offset]) - result.value = cast[ty](0) + when T is enum: + var value: type(ord(result.value)) + else: + var value: T var shiftAmount = 0 var i = offset + 1 while true: - result.value += T(bytes[i] and 0b0111_1111) shl shiftAmount + value += type(value)(bytes[i] and 0b0111_1111) shl shiftAmount shiftAmount += 7 if (bytes[i] shr 7) == 0: break i += 1 + result.bytesProcessed = i + 1 + when ty is SomeSVarint: - if (result.value and T(1)) != T(0): - result.value = cast[T](not(result.value shr T(1))) + if (value and type(value)(1)) != type(value)(0): + result.value = cast[T](not(value shr type(value)(1))) else: - result.value = cast[T](result.value shr T(1)) - -proc main() = - let proto = newProtoBuffer() - proto.encode(-1500000) - var input: seq[byte] = proto.outstream.getOutput - echo input - - echo decode(input, int64) - -main() \ No newline at end of file + result.value = cast[T](value shr type(value)(1)) + else: + result.value = value \ No newline at end of file diff --git a/tests/config.nims b/tests/config.nims index 3bb69f8..e355636 100644 --- a/tests/config.nims +++ b/tests/config.nims @@ -1 +1 @@ -switch("path", "$projectDir/../src") \ No newline at end of file +switch("path", "$projectDir/../") \ No newline at end of file diff --git a/tests/test_serialization.nim b/tests/test_serialization.nim new file mode 100644 index 0000000..1ee0a57 --- /dev/null +++ b/tests/test_serialization.nim @@ -0,0 +1,46 @@ +import unittest + +import protobuf_serialization + +type + MyEnum = enum + ME1, ME2, ME3 + +suite "Test Varint Encoding": + test "Can encode enum": + let proto = newProtoBuffer() + proto.encode(ME3) + proto.encode(ME2) + var output = proto.output + assert output == @[8.byte, 4, 16, 2] + + let decodedME3 = decode(output, MyEnum) + assert decodedME3.value == ME3 + assert decodedME3.fieldNum == 1 + + let decodedME2 = decode(output, MyEnum, offset=decodedME3.bytesProcessed) + assert decodedME2.value == ME2 + assert decodedME2.fieldNum == 2 + + test "Can encode negative number": + let proto = newProtoBuffer() + let num = -153452 + proto.encode(num) + var output = proto.output + assert output == @[8.byte, 215, 221, 18] + + let decoded = decode(output, int) + assert decoded.value == num + assert decoded.fieldNum == 1 + + test "Can encode unsigned number": + let proto = newProtoBuffer() + let num = 123151.uint + proto.encode(num) + var output = proto.output + assert output == @[8.byte, 143, 194, 7] + + let decoded = decode(output, uint) + echo decoded.value + assert decoded.value == num + assert decoded.fieldNum == 1 \ No newline at end of file