diff --git a/src/aprotobuf_decoder.erl b/src/aprotobuf_decoder.erl index b42e52e..ea2b16e 100644 --- a/src/aprotobuf_decoder.erl +++ b/src/aprotobuf_decoder.erl @@ -88,10 +88,10 @@ parse(Bin, Schema, What, Acc) -> parse(Rest, Schema, tag, NewAcc) end. -parse_varint(<<0:1, IntValue:7, Rest/binary>>, IntAcc, Bytes, Next, Schema, Acc) when Bytes =< 10 -> +parse_varint(<<0:1, IntValue:7, Rest/binary>>, IntAcc, Bytes, Next, Schema, Acc) when Bytes =< 9 -> VarInt = (IntValue bsl 7 * Bytes) bor IntAcc, parse(Rest, Schema, Next, [VarInt | Acc]); -parse_varint(<<1:1, IntValue:7, Rest/binary>>, IntAcc, Bytes, Next, Schema, Acc) when Bytes =< 10 -> +parse_varint(<<1:1, IntValue:7, Rest/binary>>, IntAcc, Bytes, Next, Schema, Acc) when Bytes =< 9 -> VarInt = (IntValue bsl 7 * Bytes) bor IntAcc, parse_varint(Rest, VarInt, Bytes + 1, Next, Schema, Acc); parse_varint(Bin, _IntAcc, _Bytes, _Next, _Schema, Acc) -> @@ -104,7 +104,23 @@ parse_fixed64(<>, Next, Schema, Acc) -> parse(Rest, Schema, Next, [Fixed64 | Acc]). cast(Value, int32) -> + case Value bsr 63 of + 0 -> Value; + _ -> Value - (1 bsl 64) + end; +cast(Value, int64) -> + case Value bsr 63 of + 0 -> Value; + _ -> Value - (1 bsl 64) + end; +cast(Value, uint32) -> + Value; +cast(Value, uint64) -> Value; +cast(Value, sint32) -> + (Value bsr 1) bxor -(Value band 1); +cast(Value, sint64) -> + (Value bsr 1) bxor -(Value band 1); cast(Value, {enum, IntToLabels}) -> case maps:find(Value, IntToLabels) of {ok, Label} -> Label; @@ -114,6 +130,10 @@ cast(<>, fixed32) -> Value; cast(<>, sfixed32) -> Value; +cast(<>, fixed64) -> + Value; +cast(<>, sfixed64) -> + Value; cast(<>, float) -> Value; cast(Value, undefined) -> diff --git a/src/aprotobuf_encoder.erl b/src/aprotobuf_encoder.erl index 0573afa..de0231e 100644 --- a/src/aprotobuf_encoder.erl +++ b/src/aprotobuf_encoder.erl @@ -23,6 +23,7 @@ -define(LEN_TAG, 2). -define(FIXED32_TAG, 5). +-define(FIXED64_TAG, 1). encode(Map, Schema) -> Iterator = maps:iterator(Map), @@ -43,10 +44,50 @@ encode_field(FieldNum, V, string) -> encode_field(FieldNum, V, {enum, LabelsToInt}) -> IntVal = maps:get(V, LabelsToInt), [encode_varint(FieldNum bsl 3), encode_varint(IntVal)]; -encode_field(FieldNum, V, int32) -> +encode_field(FieldNum, V, int32) when is_integer(V), V >= 0, V < (1 bsl 31) -> [encode_varint(FieldNum bsl 3), encode_varint(V)]; +encode_field(FieldNum, V, int32) when is_integer(V), V < 0, V >= -(1 bsl 31) -> + [encode_varint(FieldNum bsl 3), encode_varint(V band 16#FFFFFFFFFFFFFFFF)]; +encode_field(_FieldNum, _V, int32) -> + error(badarg); +encode_field(FieldNum, V, int64) when is_integer(V), V >= 0, V < (1 bsl 63) -> + [encode_varint(FieldNum bsl 3), encode_varint(V)]; +encode_field(FieldNum, V, int64) when is_integer(V), V < 0, V >= -(1 bsl 63) -> + [encode_varint(FieldNum bsl 3), encode_varint(V band 16#FFFFFFFFFFFFFFFF)]; +encode_field(_FieldNum, _V, int64) -> + error(badarg); +encode_field(FieldNum, V, uint32) when is_integer(V), V >= 0, V < (1 bsl 32) -> + [encode_varint(FieldNum bsl 3), encode_varint(V)]; +encode_field(_FieldNum, _V, uint32) -> + error(badarg); +encode_field(FieldNum, V, uint64) when is_integer(V), V >= 0, V < (1 bsl 64) -> + [encode_varint(FieldNum bsl 3), encode_varint(V)]; +encode_field(_FieldNum, _V, uint64) -> + error(badarg); +encode_field(FieldNum, V, sint32) when is_integer(V), V >= -(1 bsl 31), V < (1 bsl 31) -> + Z = ((V bsl 1) bxor (V bsr 31)) band 16#FFFFFFFF, + [encode_varint(FieldNum bsl 3), encode_varint(Z)]; +encode_field(_FieldNum, _V, sint32) -> + error(badarg); +encode_field(FieldNum, V, sint64) when is_integer(V), V >= -(1 bsl 63), V < (1 bsl 63) -> + Z = ((V bsl 1) bxor (V bsr 63)) band 16#FFFFFFFFFFFFFFFF, + [encode_varint(FieldNum bsl 3), encode_varint(Z)]; +encode_field(_FieldNum, _V, sint64) -> + error(badarg); encode_field(FieldNum, V, sfixed32) -> [encode_varint((FieldNum bsl 3) bor ?FIXED32_TAG), encode_sfixed32(V)]; +encode_field(FieldNum, V, fixed32) when is_integer(V), V >= 0, V < (1 bsl 32) -> + [encode_varint((FieldNum bsl 3) bor ?FIXED32_TAG), encode_fixed32(V)]; +encode_field(_FieldNum, _V, fixed32) -> + error(badarg); +encode_field(FieldNum, V, fixed64) when is_integer(V), V >= 0, V < (1 bsl 64) -> + [encode_varint((FieldNum bsl 3) bor ?FIXED64_TAG), encode_fixed64(V)]; +encode_field(_FieldNum, _V, fixed64) -> + error(badarg); +encode_field(FieldNum, V, sfixed64) when is_integer(V), V >= -(1 bsl 63), V < (1 bsl 63) -> + [encode_varint((FieldNum bsl 3) bor ?FIXED64_TAG), encode_sfixed64(V)]; +encode_field(_FieldNum, _V, sfixed64) -> + error(badarg); encode_field(FieldNum, V, MapSchema) when is_map(MapSchema) -> Encoded = encode(V, MapSchema), Len = erlang:iolist_size(Encoded), @@ -57,37 +98,23 @@ encode_field(_FiledNum, _V, _Type) -> encode_sfixed32(Int) -> <>. -% TODO: right now we focus to positive ints up to UINT32_MAX and something -encode_varint(Int) when Int < 0 -> - error(badarg); -% 2^7 - 1 -encode_varint(Int) when Int =< 127 -> +encode_fixed32(Int) -> + <>. + +encode_fixed64(Int) -> + <>. + +encode_sfixed64(Int) -> + <>. + +encode_varint(Int) when is_integer(Int), Int >= 0, Int < 128 -> [Int]; -% 2^14 - 1 -encode_varint(Int) when Int =< 16383 -> - Int0 = Int band 16#7F, - Int1 = Int bsr 7, - <<1:1, Int0:7, 0:1, Int1:7>>; -% 2^21 - 1 -encode_varint(Int) when Int =< 2097151 -> - Int0 = Int band 16#7F, - Int1 = (Int bsr 7) band 16#7F, - Int2 = Int bsr 14, - <<1:1, Int0:7, 1:1, Int1:7, 0:1, Int2:7>>; -% 2^28 - 1 -encode_varint(Int) when Int =< 268435456 -> - Int0 = Int band 16#7F, - Int1 = (Int bsr 7) band 16#7F, - Int2 = (Int bsr 14) band 16#7F, - Int3 = Int bsr 21, - <<1:1, Int0:7, 0:1, Int1:7, 0:1, Int2:7, 0:1, Int3:7>>; -% 2^35 - 1 -encode_varint(Int) when Int =< 34359738367 -> - Int0 = Int band 16#7F, - Int1 = (Int bsr 7) band 16#7F, - Int2 = (Int bsr 14) band 16#7F, - Int3 = (Int bsr 21) band 16#7F, - Int4 = Int bsr 28, - <<1:1, Int0:7, 1:1, Int1:7, 1:1, Int2:7, 1:1, Int3:7, 0:1, Int4:7>>; +encode_varint(Int) when is_integer(Int), Int >= 128, Int < (1 bsl 64) -> + encode_varint_more(Int); encode_varint(_Int) -> error(badarg). + +encode_varint_more(Int) when Int < 128 -> + [Int]; +encode_varint_more(Int) -> + [(Int band 16#7F) bor 16#80 | encode_varint_more(Int bsr 7)]. diff --git a/test/aprotobuf_decoder_test.erl b/test/aprotobuf_decoder_test.erl index ad57479..ffb633a 100644 --- a/test/aprotobuf_decoder_test.erl +++ b/test/aprotobuf_decoder_test.erl @@ -98,3 +98,677 @@ decode_int32_string_int32_message_test() -> #{b => 5, c => <<"Hello World">>, d => 1989}, aprotobuf_decoder:parse(Encoded, DecoderSchema) ). + +decode_int32_max_test() -> + Schema = #{ + a => {1, int32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 2147483647}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#07>>, DecoderSchema + ) + ). + +decode_int32_minus_one_test() -> + Schema = #{ + a => {1, int32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_int32_minus_42_test() -> + Schema = #{ + a => {1, int32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -42}, + aprotobuf_decoder:parse( + <<16#08, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_int32_min_test() -> + Schema = #{ + a => {1, int32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -2147483648}, + aprotobuf_decoder:parse( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#F8, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_int64_two_to_31_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 2147483648}, + aprotobuf_decoder:parse( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#08>>, DecoderSchema + ) + ). + +decode_int64_max_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 9223372036854775807}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#7F>>, + DecoderSchema + ) + ). + +decode_int64_minus_one_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_int64_minus_42_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -42}, + aprotobuf_decoder:parse( + <<16#08, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_int64_min_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -9223372036854775808}, + aprotobuf_decoder:parse( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#01>>, + DecoderSchema + ) + ). + +decode_int64_complex_test() -> + Schema = #{ + a => {1, int64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -16#ABCD1234560CAFE}, + aprotobuf_decoder:parse( + <<16#08, 16#82, 16#EA, 16#FC, 16#D4, 16#CB, 16#DB, 16#CB, 16#A1, 16#F5, 16#01>>, + DecoderSchema + ) + ). + +decode_uint32_small_test() -> + Schema = #{ + a => {1, uint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 42}, aprotobuf_decoder:parse(<<16#08, 16#2A>>, DecoderSchema)). + +decode_uint32_two_to_31_test() -> + Schema = #{ + a => {1, uint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 2147483648}, + aprotobuf_decoder:parse( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#08>>, DecoderSchema + ) + ). + +decode_uint32_max_test() -> + Schema = #{ + a => {1, uint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 4294967295}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#0F>>, DecoderSchema + ) + ). + +decode_uint64_small_test() -> + Schema = #{ + a => {1, uint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 42}, aprotobuf_decoder:parse(<<16#08, 16#2A>>, DecoderSchema)). + +decode_uint64_two_to_32_test() -> + Schema = #{ + a => {1, uint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 4294967296}, + aprotobuf_decoder:parse( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#10>>, DecoderSchema + ) + ). + +decode_uint64_max_test() -> + Schema = #{ + a => {1, uint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 18446744073709551615}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_uint64_complex_test() -> + Schema = #{ + a => {1, uint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 16#ABCD1234560CAFE}, + aprotobuf_decoder:parse( + <<16#08, 16#FE, 16#95, 16#83, 16#AB, 16#B4, 16#A4, 16#B4, 16#DE, 16#0A>>, + DecoderSchema + ) + ). + +decode_sint32_minus_one_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => -1}, aprotobuf_decoder:parse(<<16#08, 16#01>>, DecoderSchema)). + +decode_sint32_minus_42_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => -42}, aprotobuf_decoder:parse(<<16#08, 16#53>>, DecoderSchema)). + +decode_sint32_max_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 2147483647}, + aprotobuf_decoder:parse( + <<16#08, 16#FE, 16#FF, 16#FF, 16#FF, 16#0F>>, DecoderSchema + ) + ). + +decode_sint32_min_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -2147483648}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#0F>>, DecoderSchema + ) + ). + +decode_sint32_complex_pos_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 16#6CAFE123}, + aprotobuf_decoder:parse( + <<16#08, 16#C6, 16#84, 16#FF, 16#CA, 16#0D>>, DecoderSchema + ) + ). + +decode_sint32_complex_neg_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -16#11CAFE01}, + aprotobuf_decoder:parse( + <<16#08, 16#81, 16#F8, 16#D7, 16#9C, 16#02>>, DecoderSchema + ) + ). + +decode_sint32_zero_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 0}, aprotobuf_decoder:parse(<<16#08, 16#00>>, DecoderSchema)). + +decode_sint32_one_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 1}, aprotobuf_decoder:parse(<<16#08, 16#02>>, DecoderSchema)). + +decode_sint32_42_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 42}, aprotobuf_decoder:parse(<<16#08, 16#54>>, DecoderSchema)). + +decode_sint32_1000_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 1000}, + aprotobuf_decoder:parse(<<16#08, 16#D0, 16#0F>>, DecoderSchema) + ). + +decode_sint32_minus_1000_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1000}, + aprotobuf_decoder:parse(<<16#08, 16#CF, 16#0F>>, DecoderSchema) + ). + +decode_sint32_66000_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 66000}, + aprotobuf_decoder:parse(<<16#08, 16#A0, 16#87, 16#08>>, DecoderSchema) + ). + +decode_sint32_minus_66000_test() -> + Schema = #{ + a => {1, sint32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -66000}, + aprotobuf_decoder:parse(<<16#08, 16#9F, 16#87, 16#08>>, DecoderSchema) + ). + +decode_sint64_minus_one_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => -1}, aprotobuf_decoder:parse(<<16#08, 16#01>>, DecoderSchema)). + +decode_sint64_minus_42_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => -42}, aprotobuf_decoder:parse(<<16#08, 16#53>>, DecoderSchema)). + +decode_sint64_max_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 9223372036854775807}, + aprotobuf_decoder:parse( + <<16#08, 16#FE, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_sint64_min_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -9223372036854775808}, + aprotobuf_decoder:parse( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + DecoderSchema + ) + ). + +decode_sint64_complex_pos_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 16#6543CAFE1234ABCD}, + aprotobuf_decoder:parse( + <<16#08, 16#9A, 16#AF, 16#A5, 16#A3, 16#C2, 16#BF, 16#E5, 16#C3, 16#CA, 16#01>>, + DecoderSchema + ) + ). + +decode_sint64_complex_neg_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -16#1234CAFE9876ABCD}, + aprotobuf_decoder:parse( + <<16#08, 16#99, 16#AF, 16#B5, 16#87, 16#D3, 16#BF, 16#E5, 16#B4, 16#24>>, + DecoderSchema + ) + ). + +decode_sint64_zero_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 0}, aprotobuf_decoder:parse(<<16#08, 16#00>>, DecoderSchema)). + +decode_sint64_one_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 1}, aprotobuf_decoder:parse(<<16#08, 16#02>>, DecoderSchema)). + +decode_sint64_42_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual(#{a => 42}, aprotobuf_decoder:parse(<<16#08, 16#54>>, DecoderSchema)). + +decode_sint64_1000_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 1000}, + aprotobuf_decoder:parse(<<16#08, 16#D0, 16#0F>>, DecoderSchema) + ). + +decode_sint64_minus_1000_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1000}, + aprotobuf_decoder:parse(<<16#08, 16#CF, 16#0F>>, DecoderSchema) + ). + +decode_sint64_66000_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 66000}, + aprotobuf_decoder:parse(<<16#08, 16#A0, 16#87, 16#08>>, DecoderSchema) + ). + +decode_sint64_minus_66000_test() -> + Schema = #{ + a => {1, sint64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -66000}, + aprotobuf_decoder:parse(<<16#08, 16#9F, 16#87, 16#08>>, DecoderSchema) + ). + +decode_fixed32_zero_test() -> + Schema = #{ + a => {1, fixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 0}, + aprotobuf_decoder:parse(<<16#0D, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema) + ). + +decode_fixed32_small_test() -> + Schema = #{ + a => {1, fixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 42}, + aprotobuf_decoder:parse(<<16#0D, 16#2A, 16#00, 16#00, 16#00>>, DecoderSchema) + ). + +decode_fixed32_max_test() -> + Schema = #{ + a => {1, fixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 4294967295}, + aprotobuf_decoder:parse(<<16#0D, 16#FF, 16#FF, 16#FF, 16#FF>>, DecoderSchema) + ). + +decode_fixed32_complex_test() -> + Schema = #{ + a => {1, fixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 16#DEADBEEF}, + aprotobuf_decoder:parse(<<16#0D, 16#EF, 16#BE, 16#AD, 16#DE>>, DecoderSchema) + ). + +decode_sfixed32_zero_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 0}, + aprotobuf_decoder:parse(<<16#0D, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema) + ). + +decode_sfixed32_small_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 42}, + aprotobuf_decoder:parse(<<16#0D, 16#2A, 16#00, 16#00, 16#00>>, DecoderSchema) + ). + +decode_sfixed32_minus_one_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1}, + aprotobuf_decoder:parse(<<16#0D, 16#FF, 16#FF, 16#FF, 16#FF>>, DecoderSchema) + ). + +decode_sfixed32_minus_42_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -42}, + aprotobuf_decoder:parse(<<16#0D, 16#D6, 16#FF, 16#FF, 16#FF>>, DecoderSchema) + ). + +decode_sfixed32_max_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 2147483647}, + aprotobuf_decoder:parse(<<16#0D, 16#FF, 16#FF, 16#FF, 16#7F>>, DecoderSchema) + ). + +decode_sfixed32_min_test() -> + Schema = #{ + a => {1, sfixed32} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -2147483648}, + aprotobuf_decoder:parse(<<16#0D, 16#00, 16#00, 16#00, 16#80>>, DecoderSchema) + ). + +decode_fixed64_zero_test() -> + Schema = #{ + a => {1, fixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 0}, + aprotobuf_decoder:parse( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema + ) + ). + +decode_fixed64_small_test() -> + Schema = #{ + a => {1, fixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 42}, + aprotobuf_decoder:parse( + <<16#09, 16#2A, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema + ) + ). + +decode_fixed64_max_test() -> + Schema = #{ + a => {1, fixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 18446744073709551615}, + aprotobuf_decoder:parse( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, DecoderSchema + ) + ). + +decode_fixed64_complex_test() -> + Schema = #{ + a => {1, fixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 16#DEADBEEFCAFE1234}, + aprotobuf_decoder:parse( + <<16#09, 16#34, 16#12, 16#FE, 16#CA, 16#EF, 16#BE, 16#AD, 16#DE>>, DecoderSchema + ) + ). + +decode_sfixed64_zero_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 0}, + aprotobuf_decoder:parse( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema + ) + ). + +decode_sfixed64_small_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 42}, + aprotobuf_decoder:parse( + <<16#09, 16#2A, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, DecoderSchema + ) + ). + +decode_sfixed64_minus_one_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -1}, + aprotobuf_decoder:parse( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, DecoderSchema + ) + ). + +decode_sfixed64_minus_42_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -42}, + aprotobuf_decoder:parse( + <<16#09, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, DecoderSchema + ) + ). + +decode_sfixed64_max_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => 9223372036854775807}, + aprotobuf_decoder:parse( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#7F>>, DecoderSchema + ) + ). + +decode_sfixed64_min_test() -> + Schema = #{ + a => {1, sfixed64} + }, + DecoderSchema = aprotobuf_decoder:transform_schema(Schema), + ?assertEqual( + #{a => -9223372036854775808}, + aprotobuf_decoder:parse( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#80>>, DecoderSchema + ) + ). diff --git a/test/aprotobuf_encoder_test.erl b/test/aprotobuf_encoder_test.erl new file mode 100644 index 0000000..262e630 --- /dev/null +++ b/test/aprotobuf_encoder_test.erl @@ -0,0 +1,722 @@ +% +% This file is part of aprotobuf. +% +% Copyright 2023 Davide Bettio +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. +% +% SPDX-License-Identifier: Apache-2.0 +% + +-module(aprotobuf_encoder_test). + +-include_lib("eunit/include/eunit.hrl"). + +encode_int32_small_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#2A>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_int32_two_to_21_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 2097152}, Schema)) + ). + +encode_int32_two_to_28_minus_one_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#7F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 268435455}, Schema)) + ). + +encode_int32_two_to_28_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 268435456}, Schema)) + ). + +encode_int32_minus_one_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_int32_minus_42_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_int32_min_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#F8, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -2147483648}, Schema)) + ). + +encode_int32_overflow_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 2147483648}, Schema)). + +encode_int32_underflow_test() -> + Schema = #{ + a => {1, int32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -2147483649}, Schema)). + +encode_int64_small_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#2A>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_int64_two_to_31_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 2147483648}, Schema)) + ). + +encode_int64_max_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#7F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 9223372036854775807}, Schema)) + ). + +encode_int64_minus_one_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_int64_minus_42_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_int64_min_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#80, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -9223372036854775808}, Schema)) + ). + +encode_int64_overflow_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 9223372036854775808}, Schema)). + +encode_int64_underflow_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -9223372036854775809}, Schema)). + +encode_int64_complex_test() -> + Schema = #{ + a => {1, int64} + }, + ?assertEqual( + <<16#08, 16#82, 16#EA, 16#FC, 16#D4, 16#CB, 16#DB, 16#CB, 16#A1, 16#F5, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -16#ABCD1234560CAFE}, Schema)) + ). + +encode_uint32_small_test() -> + Schema = #{ + a => {1, uint32} + }, + ?assertEqual( + <<16#08, 16#2A>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_uint32_two_to_31_test() -> + Schema = #{ + a => {1, uint32} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 2147483648}, Schema)) + ). + +encode_uint32_max_test() -> + Schema = #{ + a => {1, uint32} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 4294967295}, Schema)) + ). + +encode_uint32_overflow_test() -> + Schema = #{ + a => {1, uint32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 4294967296}, Schema)). + +encode_uint32_underflow_test() -> + Schema = #{ + a => {1, uint32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -1}, Schema)). + +encode_uint64_small_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertEqual( + <<16#08, 16#2A>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_uint64_two_to_32_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertEqual( + <<16#08, 16#80, 16#80, 16#80, 16#80, 16#10>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 4294967296}, Schema)) + ). + +encode_uint64_max_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 18446744073709551615}, Schema)) + ). + +encode_uint64_overflow_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 18446744073709551616}, Schema)). + +encode_uint64_underflow_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -1}, Schema)). + +encode_uint64_complex_test() -> + Schema = #{ + a => {1, uint64} + }, + ?assertEqual( + <<16#08, 16#FE, 16#95, 16#83, 16#AB, 16#B4, 16#A4, 16#B4, 16#DE, 16#0A>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 16#ABCD1234560CAFE}, Schema)) + ). + +encode_sint32_small_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#54>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_sint32_minus_one_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_sint32_minus_42_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#53>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_sint32_max_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#FE, 16#FF, 16#FF, 16#FF, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 2147483647}, Schema)) + ). + +encode_sint32_min_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -2147483648}, Schema)) + ). + +encode_sint32_overflow_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 2147483648}, Schema)). + +encode_sint32_underflow_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -2147483649}, Schema)). + +encode_sint32_complex_pos_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#C6, 16#84, 16#FF, 16#CA, 16#0D>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 16#6CAFE123}, Schema)) + ). + +encode_sint32_complex_neg_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#81, 16#F8, 16#D7, 16#9C, 16#02>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -16#11CAFE01}, Schema)) + ). + +encode_sint32_zero_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_sint32_one_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#02>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 1}, Schema)) + ). + +encode_sint32_1000_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#D0, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 1000}, Schema)) + ). + +encode_sint32_minus_1000_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#CF, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1000}, Schema)) + ). + +encode_sint32_66000_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#A0, 16#87, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 66000}, Schema)) + ). + +encode_sint32_minus_66000_test() -> + Schema = #{ + a => {1, sint32} + }, + ?assertEqual( + <<16#08, 16#9F, 16#87, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -66000}, Schema)) + ). + +encode_sint64_small_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#54>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_sint64_minus_one_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_sint64_minus_42_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#53>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_sint64_max_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#FE, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 9223372036854775807}, Schema)) + ). + +encode_sint64_min_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -9223372036854775808}, Schema)) + ). + +encode_sint64_overflow_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 9223372036854775808}, Schema)). + +encode_sint64_underflow_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -9223372036854775809}, Schema)). + +encode_sint64_complex_pos_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#9A, 16#AF, 16#A5, 16#A3, 16#C2, 16#BF, 16#E5, 16#C3, 16#CA, 16#01>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 16#6543CAFE1234ABCD}, Schema)) + ). + +encode_sint64_complex_neg_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#99, 16#AF, 16#B5, 16#87, 16#D3, 16#BF, 16#E5, 16#B4, 16#24>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -16#1234CAFE9876ABCD}, Schema)) + ). + +encode_sint64_zero_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_sint64_one_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#02>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 1}, Schema)) + ). + +encode_sint64_1000_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#D0, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 1000}, Schema)) + ). + +encode_sint64_minus_1000_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#CF, 16#0F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1000}, Schema)) + ). + +encode_sint64_66000_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#A0, 16#87, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 66000}, Schema)) + ). + +encode_sint64_minus_66000_test() -> + Schema = #{ + a => {1, sint64} + }, + ?assertEqual( + <<16#08, 16#9F, 16#87, 16#08>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -66000}, Schema)) + ). + +encode_fixed32_zero_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertEqual( + <<16#0D, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_fixed32_small_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertEqual( + <<16#0D, 16#2A, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_fixed32_max_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertEqual( + <<16#0D, 16#FF, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 4294967295}, Schema)) + ). + +encode_fixed32_complex_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertEqual( + <<16#0D, 16#EF, 16#BE, 16#AD, 16#DE>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 16#DEADBEEF}, Schema)) + ). + +encode_fixed32_overflow_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 4294967296}, Schema)). + +encode_fixed32_underflow_test() -> + Schema = #{ + a => {1, fixed32} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -1}, Schema)). + +encode_sfixed32_zero_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_sfixed32_small_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#2A, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_sfixed32_minus_one_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#FF, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_sfixed32_minus_42_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#D6, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_sfixed32_max_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#FF, 16#FF, 16#FF, 16#7F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 2147483647}, Schema)) + ). + +encode_sfixed32_min_test() -> + Schema = #{ + a => {1, sfixed32} + }, + ?assertEqual( + <<16#0D, 16#00, 16#00, 16#00, 16#80>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -2147483648}, Schema)) + ). + +encode_fixed64_zero_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertEqual( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_fixed64_small_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertEqual( + <<16#09, 16#2A, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_fixed64_max_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertEqual( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 18446744073709551615}, Schema)) + ). + +encode_fixed64_complex_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertEqual( + <<16#09, 16#34, 16#12, 16#FE, 16#CA, 16#EF, 16#BE, 16#AD, 16#DE>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 16#DEADBEEFCAFE1234}, Schema)) + ). + +encode_fixed64_overflow_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => 18446744073709551616}, Schema)). + +encode_fixed64_underflow_test() -> + Schema = #{ + a => {1, fixed64} + }, + ?assertError(badarg, aprotobuf_encoder:encode(#{a => -1}, Schema)). + +encode_sfixed64_zero_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 0}, Schema)) + ). + +encode_sfixed64_small_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#2A, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 42}, Schema)) + ). + +encode_sfixed64_minus_one_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -1}, Schema)) + ). + +encode_sfixed64_minus_42_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#D6, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -42}, Schema)) + ). + +encode_sfixed64_max_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#7F>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => 9223372036854775807}, Schema)) + ). + +encode_sfixed64_min_test() -> + Schema = #{ + a => {1, sfixed64} + }, + ?assertEqual( + <<16#09, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#80>>, + iolist_to_binary(aprotobuf_encoder:encode(#{a => -9223372036854775808}, Schema)) + ).