Skip to content

Commit

Permalink
Fix integer wire format for packed arrays
Browse files Browse the repository at this point in the history
Fix #23
  • Loading branch information
dcarp committed Jun 17, 2019
1 parent 5f57d7d commit 9342e90
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
28 changes: 20 additions & 8 deletions src/google/protobuf/decoding.d
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,21 @@ if (isInputRange!R && isArray!T && !is(T == string) && !is(T == bytes))
return result.data;
}

unittest
{
import std.array : array;
import google.protobuf.encoding : toProtobuf;

auto buffer = [false, false, true].toProtobuf.array;
assert(buffer.fromProtobuf!(bool[]) == [false, false, true]);
buffer = [1, 2].toProtobuf!(Wire.fixed).array;
assert(buffer.fromProtobuf!(int[], Wire.fixed) == [1, 2]);
buffer = [1, 2].toProtobuf.array;
assert(buffer.fromProtobuf!(int[]) == [1, 2]);
buffer = [-54L, 54L].toProtobuf!(Wire.zigzag).array;
assert(buffer.fromProtobuf!(long[], Wire.zigzag) == [-54L, 54L]);
}

T fromProtobuf(T, R)(ref R inputRange, T result = protoDefaultValue!T)
if (isInputRange!R && (is(T == class) || is(T == struct)))
{
Expand Down Expand Up @@ -239,7 +254,7 @@ unittest
struct Foo
{
@Proto(1) int[] bar = protoDefaultValue!(int[]);
@Proto(2, Wire.none, Yes.packed) int[] baz = protoDefaultValue!(int[]);
@Proto(2, Wire.zigzag, Yes.packed) int[] baz = protoDefaultValue!(int[]);
}

Foo foo;
Expand Down Expand Up @@ -288,8 +303,7 @@ if (isInputRange!R && isIntegral!T)
static assert(is(ElementType!R == ubyte), "Input range should be an ubyte range");
static assert(validateProto!(proto, T));

enum wire = proto.wire;
field = inputRange.fromProtobuf!(T, wire);
field = inputRange.fromProtobuf!(T, proto.wire);
}

private void fromProtobufByProto(Proto proto, T, R)(ref R inputRange, ref T field)
Expand All @@ -298,7 +312,7 @@ if (isInputRange!R && isArray!T && !is(T == string) && !is(T == bytes) && proto.
static assert(is(ElementType!R == ubyte), "Input range should be an ubyte range");
static assert(validateProto!(proto, T));

field ~= inputRange.fromProtobuf!T;
field ~= inputRange.fromProtobuf!(T, proto.wire);
}

private void fromProtobufByProto(Proto proto, T, R)(ref R inputRange, ref T field)
Expand Down Expand Up @@ -346,8 +360,7 @@ if (isInputRange!R && isAssociativeArray!T)
{
static assert(isIntegral!(KeyType!T), "Cannot specify wire format for non-integral map key");

enum wire = keyProto.wire;
key = fieldRange.fromProtobuf!(KeyType!T, wire);
key = fieldRange.fromProtobuf!(KeyType!T, keyProto.wire);
}
break;
case MapFieldTag.value:
Expand All @@ -363,8 +376,7 @@ if (isInputRange!R && isAssociativeArray!T)
{
static assert(isIntegral!(ValueType!T), "Cannot specify wire format for non-integral map value");

enum wire = valueProto.wire;
value = fieldRange.fromProtobuf!(ValueType!T, wire);
value = fieldRange.fromProtobuf!(ValueType!T, valueProto.wire);
}
break;
default:
Expand Down
14 changes: 11 additions & 3 deletions src/google/protobuf/encoding.d
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ unittest
assert([false, false, true].toProtobuf.array == [0x03, 0x00, 0x00, 0x01]);
assert([1, 2].toProtobuf!(Wire.fixed).array == [0x08, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00]);
assert([1, 2].toProtobuf.array == [0x02, 0x01, 0x02]);
assert([-54L, 54L].toProtobuf!(Wire.zigzag).array == [0x02, 0x6b, 0x6c]);
}

auto toProtobuf(T)(T value)
Expand Down Expand Up @@ -213,14 +214,14 @@ unittest
struct Foo
{
@Proto(1) int[] bar = protoDefaultValue!(int[]);
@Proto(2, Wire.none, Yes.packed) int[] baz = protoDefaultValue!(int[]);
@Proto(2, Wire.zigzag, Yes.packed) int[] baz = protoDefaultValue!(int[]);
}

Foo foo;
assert(foo.toProtobuf.empty);
foo.bar = [1, 2];
foo.baz = [3, 4];
assert(foo.toProtobuf.array == [0x08, 0x01, 0x08, 0x02, 0x12, 0x02, 0x03, 0x04]);
assert(foo.toProtobuf.array == [0x08, 0x01, 0x08, 0x02, 0x12, 0x02, 0x06, 0x08]);
}

unittest
Expand Down Expand Up @@ -322,7 +323,14 @@ if (isBoolean!T ||
{
static assert(validateProto!(proto, T));

return chain(encodeTag!(proto, T), value.toProtobuf);
static if (proto.wire == Wire.none)
{
return chain(encodeTag!(proto, T), value.toProtobuf);
}
else
{
return chain(encodeTag!(proto, T), value.toProtobuf!(proto.wire));
}
}

private auto toProtobufByProto(Proto proto, T)(T value)
Expand Down

0 comments on commit 9342e90

Please sign in to comment.