summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Garnock-Jones <tonyg@lshift.net>2009-11-16 17:25:01 +0000
committerTony Garnock-Jones <tonyg@lshift.net>2009-11-16 17:25:01 +0000
commitf861a8286e852758896fd75fc7916c1d295c5abf (patch)
treeca9e0de1c02ea27767f1cab3b8ef0b0f7f7dd506
parent369116dc6a78b5b3f099ddc6d5bafed3de13c4ef (diff)
parent3281811ad1d2a066241ed670fbfe6ea76738058d (diff)
downloadrabbitmq-server-f861a8286e852758896fd75fc7916c1d295c5abf.tar.gz
Merge bug21929 into default
-rw-r--r--src/rabbit_binary_generator.erl95
-rw-r--r--src/rabbit_binary_parser.erl65
-rw-r--r--src/rabbit_tests.erl53
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).