diff options
author | Tony Garnock-Jones <tonyg@lshift.net> | 2009-11-16 17:25:01 +0000 |
---|---|---|
committer | Tony Garnock-Jones <tonyg@lshift.net> | 2009-11-16 17:25:01 +0000 |
commit | f861a8286e852758896fd75fc7916c1d295c5abf (patch) | |
tree | ca9e0de1c02ea27767f1cab3b8ef0b0f7f7dd506 | |
parent | 369116dc6a78b5b3f099ddc6d5bafed3de13c4ef (diff) | |
parent | 3281811ad1d2a066241ed670fbfe6ea76738058d (diff) | |
download | rabbitmq-server-f861a8286e852758896fd75fc7916c1d295c5abf.tar.gz |
Merge bug21929 into default
-rw-r--r-- | src/rabbit_binary_generator.erl | 95 | ||||
-rw-r--r-- | src/rabbit_binary_parser.erl | 65 | ||||
-rw-r--r-- | src/rabbit_tests.erl | 53 |
3 files changed, 130 insertions, 83 deletions
diff --git a/src/rabbit_binary_generator.erl b/src/rabbit_binary_generator.erl index 6cfa9e6d..01ac4f02 100644 --- a/src/rabbit_binary_generator.erl +++ b/src/rabbit_binary_generator.erl @@ -132,52 +132,66 @@ create_frame(TypeInt, ChannelInt, Payload) -> %% I, D, T and F, as well as the QPid extensions b, d, f, l, s, t, x, %% and V. -table_field_to_binary({FName, longstr, Value}) -> - [short_string_to_binary(FName), "S", long_string_to_binary(Value)]; +table_field_to_binary({FName, Type, Value}) -> + [short_string_to_binary(FName) | field_value_to_binary(Type, Value)]. -table_field_to_binary({FName, signedint, Value}) -> - [short_string_to_binary(FName), "I", <<Value:32/signed>>]; +field_value_to_binary(longstr, Value) -> + ["S", long_string_to_binary(Value)]; -table_field_to_binary({FName, decimal, {Before, After}}) -> - [short_string_to_binary(FName), "D", Before, <<After:32>>]; +field_value_to_binary(signedint, Value) -> + ["I", <<Value:32/signed>>]; -table_field_to_binary({FName, timestamp, Value}) -> - [short_string_to_binary(FName), "T", <<Value:64>>]; +field_value_to_binary(decimal, {Before, After}) -> + ["D", Before, <<After:32>>]; -table_field_to_binary({FName, table, Value}) -> - [short_string_to_binary(FName), "F", table_to_binary(Value)]; +field_value_to_binary(timestamp, Value) -> + ["T", <<Value:64>>]; -table_field_to_binary({FName, byte, Value}) -> - [short_string_to_binary(FName), "b", <<Value:8/unsigned>>]; +field_value_to_binary(table, Value) -> + ["F", table_to_binary(Value)]; -table_field_to_binary({FName, double, Value}) -> - [short_string_to_binary(FName), "d", <<Value:64/float>>]; +field_value_to_binary(array, Value) -> + ["A", array_to_binary(Value)]; -table_field_to_binary({FName, float, Value}) -> - [short_string_to_binary(FName), "f", <<Value:32/float>>]; +field_value_to_binary(byte, Value) -> + ["b", <<Value:8/unsigned>>]; -table_field_to_binary({FName, long, Value}) -> - [short_string_to_binary(FName), "l", <<Value:64/signed>>]; +field_value_to_binary(double, Value) -> + ["d", <<Value:64/float>>]; -table_field_to_binary({FName, short, Value}) -> - [short_string_to_binary(FName), "s", <<Value:16/signed>>]; +field_value_to_binary(float, Value) -> + ["f", <<Value:32/float>>]; -table_field_to_binary({FName, bool, Value}) -> - [short_string_to_binary(FName), "t", if Value -> 1; true -> 0 end]; +field_value_to_binary(long, Value) -> + ["l", <<Value:64/signed>>]; -table_field_to_binary({FName, binary, Value}) -> - [short_string_to_binary(FName), "x", long_string_to_binary(Value)]; +field_value_to_binary(short, Value) -> + ["s", <<Value:16/signed>>]; -table_field_to_binary({FName, void, _Value}) -> - [short_string_to_binary(FName), "V"]. +field_value_to_binary(bool, Value) -> + ["t", if Value -> 1; true -> 0 end]; + +field_value_to_binary(binary, Value) -> + ["x", long_string_to_binary(Value)]; + +field_value_to_binary(void, _Value) -> + ["V"]. table_to_binary(Table) when is_list(Table) -> BinTable = generate_table(Table), [<<(size(BinTable)):32>>, BinTable]. +array_to_binary(Array) when is_list(Array) -> + BinArray = generate_array(Array), + [<<(size(BinArray)):32>>, BinArray]. + generate_table(Table) when is_list(Table) -> list_to_binary(lists:map(fun table_field_to_binary/1, Table)). +generate_array(Array) when is_list(Array) -> + list_to_binary(lists:map( + fun ({Type, Value}) -> field_value_to_binary(Type, Value) end, + Array)). short_string_to_binary(String) when is_binary(String) and (size(String) < 256) -> [<<(size(String)):8>>, String]; @@ -186,13 +200,11 @@ short_string_to_binary(String) -> true = (StringLength < 256), % assertion [<<StringLength:8>>, String]. - long_string_to_binary(String) when is_binary(String) -> [<<(size(String)):32>>, String]; long_string_to_binary(String) -> [<<(length(String)):32>>, String]. - encode_properties([], []) -> <<0, 0>>; encode_properties(TypeList, ValueList) -> @@ -238,32 +250,7 @@ encode_property(longlongint, Int) -> encode_property(timestamp, Int) -> <<Int:64/unsigned>>; encode_property(table, Table) -> - encode_table(Table). - - -encode_table(Table) -> - TableBin = list_to_binary(lists:map(fun encode_table_entry/1, Table)), - Len = size(TableBin), - <<Len:32/unsigned, TableBin:Len/binary>>. - - -encode_table_entry({Name, longstr, Value}) -> - NLen = size(Name), - VLen = size(Value), - <<NLen:8/unsigned, Name:NLen/binary, "S", VLen:32/unsigned, Value:VLen/binary>>; -encode_table_entry({Name, signedint, Value}) -> - NLen = size(Name), - <<NLen:8/unsigned, Name:NLen/binary, "I", Value:32/signed>>; -encode_table_entry({Name, decimal, {Before, After}}) -> - NLen = size(Name), - <<NLen:8/unsigned, Name:NLen/binary, "D", Before:8/unsigned, After:32/unsigned>>; -encode_table_entry({Name, timestamp, Value}) -> - NLen = size(Name), - <<NLen:8/unsigned, Name:NLen/binary, "T", Value:64/unsigned>>; -encode_table_entry({Name, table, Value}) -> - NLen = size(Name), - TableBin = encode_table(Value), - <<NLen:8/unsigned, Name:NLen/binary, "F", TableBin/binary>>. + table_to_binary(Table). check_empty_content_body_frame_size() -> %% Intended to ensure that EMPTY_CONTENT_BODY_FRAME_SIZE is diff --git a/src/rabbit_binary_parser.erl b/src/rabbit_binary_parser.erl index 4ef382aa..506e87ec 100644 --- a/src/rabbit_binary_parser.erl +++ b/src/rabbit_binary_parser.erl @@ -56,45 +56,57 @@ parse_table(<<>>) -> []; +parse_table(<<NLen:8/unsigned, NameString:NLen/binary, ValueAndRest/binary>>) -> + {Type, Value, Rest} = parse_field_value(ValueAndRest), + [{NameString, Type, Value} | parse_table(Rest)]. -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "S", VLen:32/unsigned, ValueString:VLen/binary, Rest/binary>>) -> - [{NameString, longstr, ValueString} | parse_table(Rest)]; +parse_array(<<>>) -> + []; +parse_array(<<ValueAndRest/binary>>) -> + {Type, Value, Rest} = parse_field_value(ValueAndRest), + [{Type, Value} | parse_array(Rest)]. + +parse_field_value(<<"S", VLen:32/unsigned, ValueString:VLen/binary, Rest/binary>>) -> + {longstr, ValueString, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "I", Value:32/signed, Rest/binary>>) -> - [{NameString, signedint, Value} | parse_table(Rest)]; +parse_field_value(<<"I", Value:32/signed, Rest/binary>>) -> + {signedint, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "D", Before:8/unsigned, After:32/unsigned, Rest/binary>>) -> - [{NameString, decimal, {Before, After}} | parse_table(Rest)]; +parse_field_value(<<"D", Before:8/unsigned, After:32/unsigned, Rest/binary>>) -> + {decimal, {Before, After}, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "T", Value:64/unsigned, Rest/binary>>) -> - [{NameString, timestamp, Value} | parse_table(Rest)]; +parse_field_value(<<"T", Value:64/unsigned, Rest/binary>>) -> + {timestamp, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "F", VLen:32/unsigned, Table:VLen/binary, Rest/binary>>) -> - [{NameString, table, parse_table(Table)} | parse_table(Rest)]; +parse_field_value(<<"F", VLen:32/unsigned, Table:VLen/binary, Rest/binary>>) -> + {table, parse_table(Table), Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "b", Value:8/unsigned, Rest/binary>>) -> - [{NameString, byte, Value} | parse_table(Rest)]; +parse_field_value(<<"A", VLen:32/unsigned, Array:VLen/binary, Rest/binary>>) -> + {array, parse_array(Array), Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "d", Value:64/float, Rest/binary>>) -> - [{NameString, double, Value} | parse_table(Rest)]; +parse_field_value(<<"b", Value:8/unsigned, Rest/binary>>) -> + {byte, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "f", Value:32/float, Rest/binary>>) -> - [{NameString, float, Value} | parse_table(Rest)]; +parse_field_value(<<"d", Value:64/float, Rest/binary>>) -> + {double, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "l", Value:64/signed, Rest/binary>>) -> - [{NameString, long, Value} | parse_table(Rest)]; +parse_field_value(<<"f", Value:32/float, Rest/binary>>) -> + {float, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "s", Value:16/signed, Rest/binary>>) -> - [{NameString, short, Value} | parse_table(Rest)]; +parse_field_value(<<"l", Value:64/signed, Rest/binary>>) -> + {long, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "t", Value:8/unsigned, Rest/binary>>) -> - [{NameString, bool, (Value /= 0)} | parse_table(Rest)]; +parse_field_value(<<"s", Value:16/signed, Rest/binary>>) -> + {short, Value, Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "x", VLen:32/unsigned, ValueString:VLen/binary, Rest/binary>>) -> - [{NameString, binary, ValueString} | parse_table(Rest)]; +parse_field_value(<<"t", Value:8/unsigned, Rest/binary>>) -> + {bool, (Value /= 0), Rest}; -parse_table(<<NLen:8/unsigned, NameString:NLen/binary, "V", Rest/binary>>) -> - [{NameString, void, undefined} | parse_table(Rest)]. +parse_field_value(<<"x", VLen:32/unsigned, ValueString:VLen/binary, Rest/binary>>) -> + {binary, ValueString, Rest}; + +parse_field_value(<<"V", Rest/binary>>) -> + {void, undefined, Rest}. parse_properties([], _PropBin) -> @@ -147,7 +159,6 @@ parse_property(bit, Rest) -> parse_property(table, <<Len:32/unsigned, Table:Len/binary, Rest/binary>>) -> {parse_table(Table), Rest}. - ensure_content_decoded(Content = #content{properties = Props}) when Props =/= 'none' -> Content; diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl index c5a7d05e..ba048184 100644 --- a/src/rabbit_tests.erl +++ b/src/rabbit_tests.erl @@ -193,6 +193,7 @@ test_unfold() -> test_parsing() -> passed = test_content_properties(), + passed = test_field_values(), passed. test_content_properties() -> @@ -218,9 +219,12 @@ test_content_properties() -> [{<<"one">>, signedint, 1}, {<<"two">>, signedint, 2}]}]}], << - 16#8000:16, % flags - % properties: + % property-flags + 16#8000:16, + % property-list: + + % table 117:32, % table length in bytes 11,"a signedint", % name @@ -249,6 +253,51 @@ test_content_properties() -> V -> exit({got_success_but_expected_failure, V}) end. +test_field_values() -> + %% FIXME this does not test inexact numbers (double and float) yet, + %% because they won't pass the equality assertions + test_content_prop_roundtrip( + [{table, [{<<"longstr">>, longstr, <<"Here is a long string">>}, + {<<"signedint">>, signedint, 12345}, + {<<"decimal">>, decimal, {3, 123456}}, + {<<"timestamp">>, timestamp, 109876543209876}, + {<<"table">>, table, [{<<"one">>, signedint, 54321}, + {<<"two">>, longstr, <<"A long string">>}]}, + {<<"byte">>, byte, 255}, + {<<"long">>, long, 1234567890}, + {<<"short">>, short, 655}, + {<<"bool">>, bool, true}, + {<<"binary">>, binary, <<"a binary string">>}, + {<<"void">>, void, undefined}, + {<<"array">>, array, [{signedint, 54321}, + {longstr, <<"A long string">>}]} + + ]}], + << + % property-flags + 16#8000:16, + % table length in bytes + 228:32, + + 7,"longstr", "S", 21:32, "Here is a long string", % = 34 + 9,"signedint", "I", 12345:32/signed, % + 15 = 49 + 7,"decimal", "D", 3, 123456:32, % + 14 = 63 + 9,"timestamp", "T", 109876543209876:64, % + 19 = 82 + 5,"table", "F", 31:32, % length of table % + 11 = 93 + 3,"one", "I", 54321:32, % + 9 = 102 + 3,"two", "S", 13:32, "A long string",% + 22 = 124 + 4,"byte", "b", 255:8, % + 7 = 131 + 4,"long", "l", 1234567890:64, % + 14 = 145 + 5,"short", "s", 655:16, % + 9 = 154 + 4,"bool", "t", 1, % + 7 = 161 + 6,"binary", "x", 15:32, "a binary string", % + 27 = 188 + 4,"void", "V", % + 6 = 194 + 5,"array", "A", 23:32, % + 11 = 205 + "I", 54321:32, % + 5 = 210 + "S", 13:32, "A long string" % + 18 = 228 + >>), + passed. + test_topic_match(P, R) -> test_topic_match(P, R, true). |