@@ -379,7 +379,7 @@ encode_tags([]) ->
379379encode_tags (Tags ) ->
380380 EncodedBlocks = lists :flatmap (
381381 fun ({Name , Value }) ->
382- Res = [encode_avro_string (Name ), encode_avro_string (Value )],
382+ Res = [encode_avro_name (Name ), encode_avro_value (Value )],
383383 case lists :member (error , Res ) of
384384 true ->
385385 throw ({cannot_encode_empty_string , Name , Value });
@@ -394,14 +394,22 @@ encode_tags(Tags) ->
394394 <<ZigZagCount /binary , (list_to_binary (EncodedBlocks ))/binary , 0 >>.
395395
396396% % @doc Encode a string for Avro using ZigZag and VInt encoding.
397- encode_avro_string (<<>>) ->
398- % Zero length strings are treated as a special case, due to the Avro encoder.
397+ encode_avro_name (<<>>) ->
398+ % Zero length names are treated as a special case, due to the Avro encoder.
399399 << 0 >>;
400- encode_avro_string (String ) ->
401- StringBytes = unicode : characters_to_binary (String , utf8 ),
400+ encode_avro_name (String ) ->
401+ StringBytes = utf8_encoded (String ),
402402 Length = byte_size (StringBytes ),
403403 <<(encode_zigzag (Length ))/binary , StringBytes /binary >>.
404404
405+ encode_avro_value (<<>>) ->
406+ % Zero length values are treated as a special case, due to the Avro encoder.
407+ << 0 >>;
408+ encode_avro_value (Value ) when is_binary (Value ) ->
409+ % Tag values can be raw binaries
410+ Length = byte_size (Value ),
411+ <<(encode_zigzag (Length ))/binary , Value /binary >>.
412+
405413% % @doc Encode an integer using ZigZag encoding.
406414encode_zigzag (Int ) when Int >= 0 ->
407415 encode_vint (Int bsl 1 );
@@ -635,9 +643,45 @@ ar_bundles_test_() ->
635643 {timeout , 30 , fun test_basic_member_id /0 },
636644 {timeout , 30 , fun test_deep_member /0 },
637645 {timeout , 30 , fun test_extremely_large_bundle /0 },
638- {timeout , 30 , fun test_serialize_deserialize_deep_signed_bundle /0 }
646+ {timeout , 30 , fun test_serialize_deserialize_deep_signed_bundle /0 },
647+ {timeout , 30 , fun test_encode_tags /0 }
639648 ].
640649
650+ test_encode_tags () ->
651+ BinValue = <<1 , 2 , 3 , 255 , 254 >>,
652+ TestCases = [
653+ {simple_string_tags , [{<<" tag1" >>, <<" value1" >>}]},
654+ {binary_value_tag , [{<<" binary-tag" >>, BinValue }]},
655+ {mixed_tags ,
656+ [
657+ {<<" string-tag" >>, <<" string-value" >>},
658+ {<<" binary-tag" >>, BinValue }
659+ ]
660+ },
661+ {empty_value_tag , [{<<" empty-value-tag" >>, <<>>}]},
662+ {unicode_tag , [{<<" unicode-tag" >>, <<" 你好世界" >>}]}
663+ ],
664+ lists :foreach (
665+ fun ({Label , InputTags }) ->
666+ Encoded = encode_tags (InputTags ),
667+ Wrapped =
668+ <<
669+ (length (InputTags )):64 /little ,
670+ (byte_size (Encoded )):64 /little ,
671+ Encoded /binary
672+ >>,
673+ {DecodedTags , <<>>} = decode_tags (Wrapped ),
674+ ? assertEqual (InputTags , DecodedTags , Label )
675+ end ,
676+ TestCases
677+ ),
678+ % Test case: Empty tags list
679+ EmptyTags = [],
680+ EncodedEmpty = encode_tags (EmptyTags ),
681+ ? assertEqual (<<>>, EncodedEmpty ),
682+ WrappedEmpty = <<0 :64 /little , 0 :64 /little >>,
683+ {[], <<>>} = decode_tags (WrappedEmpty ).
684+
641685run_test () ->
642686 test_with_zero_length_tag ().
643687
@@ -648,12 +692,9 @@ test_no_tags() ->
648692 Anchor = crypto :strong_rand_bytes (32 ),
649693 DataItem = new_item (Target , Anchor , [], <<" data" >>),
650694 SignedDataItem = sign_item (DataItem , {Priv , Pub }),
651-
652695 ? assertEqual (true , verify_item (SignedDataItem )),
653696 assert_data_item (KeyType , Owner , Target , Anchor , [], <<" data" >>, SignedDataItem ),
654-
655697 SignedDataItem2 = deserialize (serialize (SignedDataItem )),
656-
657698 ? assertEqual (SignedDataItem , SignedDataItem2 ),
658699 ? assertEqual (true , verify_item (SignedDataItem2 )),
659700 assert_data_item (KeyType , Owner , Target , Anchor , [], <<" data" >>, SignedDataItem2 ).
@@ -666,12 +707,9 @@ test_with_tags() ->
666707 Tags = [{<<" tag1" >>, <<" value1" >>}, {<<" tag2" >>, <<" value2" >>}],
667708 DataItem = new_item (Target , Anchor , Tags , <<" taggeddata" >>),
668709 SignedDataItem = sign_item (DataItem , {Priv , Pub }),
669-
670710 ? assertEqual (true , verify_item (SignedDataItem )),
671711 assert_data_item (KeyType , Owner , Target , Anchor , Tags , <<" taggeddata" >>, SignedDataItem ),
672-
673712 SignedDataItem2 = deserialize (serialize (SignedDataItem )),
674-
675713 ? assertEqual (SignedDataItem , SignedDataItem2 ),
676714 ? assertEqual (true , verify_item (SignedDataItem2 )),
677715 assert_data_item (KeyType , Owner , Target , Anchor , Tags , <<" taggeddata" >>, SignedDataItem2 ).
0 commit comments