Skip to content

Commit daf6e7a

Browse files
author
Vlad Ionescu
committed
merging bug21965 into default
2 parents d147670 + 329c0dd commit daf6e7a

File tree

2 files changed

+150
-89
lines changed

2 files changed

+150
-89
lines changed

projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs

Lines changed: 143 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public static decimal ReadDecimal(NetworkBinaryReader reader)
128128
///<remarks>
129129
/// Supports the AMQP 0-8/0-9 standard entry types S, I, D, T
130130
/// and F, as well as the QPid-0-8 specific b, d, f, l, s, t,
131-
/// x and V types.
131+
/// x and V types and the AMQP 0-9-1 A type.
132132
///</remarks>
133133
public static IDictionary ReadTable(NetworkBinaryReader reader)
134134
{
@@ -140,10 +140,36 @@ public static IDictionary ReadTable(NetworkBinaryReader reader)
140140
while ((backingStream.Position - startPosition) < tableLength)
141141
{
142142
string key = ReadShortstr(reader);
143-
object value = null;
143+
object value = ReadFieldValue(reader);
144+
145+
if (!table.ContainsKey(key))
146+
{
147+
table[key] = value;
148+
}
149+
}
144150

145-
byte discriminator = reader.ReadByte();
146-
switch ((char)discriminator)
151+
return table;
152+
}
153+
154+
public static IList ReadArray(NetworkBinaryReader reader)
155+
{
156+
IList array = new ArrayList();
157+
long arrayLength = reader.ReadUInt32();
158+
Stream backingStream = reader.BaseStream;
159+
long startPosition = backingStream.Position;
160+
while ((backingStream.Position - startPosition) < arrayLength)
161+
{
162+
object value = ReadFieldValue(reader);
163+
array.Add(value);
164+
}
165+
return array;
166+
}
167+
168+
public static object ReadFieldValue(NetworkBinaryReader reader)
169+
{
170+
object value = null;
171+
byte discriminator = reader.ReadByte();
172+
switch ((char)discriminator)
147173
{
148174
case 'S':
149175
value = ReadLongstr(reader);
@@ -161,6 +187,9 @@ public static IDictionary ReadTable(NetworkBinaryReader reader)
161187
value = ReadTable(reader);
162188
break;
163189

190+
case 'A':
191+
value = ReadArray(reader);
192+
break;
164193
case 'b':
165194
value = ReadOctet(reader);
166195
break;
@@ -190,16 +219,9 @@ public static IDictionary ReadTable(NetworkBinaryReader reader)
190219
throw new SyntaxError("Unrecognised type in table: " +
191220
(char) discriminator);
192221
}
193-
194-
if (!table.ContainsKey(key))
195-
{
196-
table[key] = value;
197-
}
198-
}
199-
200-
return table;
222+
return value;
201223
}
202-
224+
203225
public static AmqpTimestamp ReadTimestamp(NetworkBinaryReader reader)
204226
{
205227
ulong stamp = ReadLonglong(reader);
@@ -290,7 +312,7 @@ public static void WriteDecimal(NetworkBinaryWriter writer, decimal value)
290312
///<para>
291313
/// Supports the AMQP 0-8/0-9 standard entry types S, I, D, T
292314
/// and F, as well as the QPid-0-8 specific b, d, f, l, s, t
293-
/// x and V types.
315+
/// x and V types and the AMQP 0-9-1 A type.
294316
///</para>
295317
///</remarks>
296318
public static void WriteTable(NetworkBinaryWriter writer, IDictionary val)
@@ -309,81 +331,7 @@ public static void WriteTable(NetworkBinaryWriter writer, IDictionary val)
309331
{
310332
WriteShortstr(writer, (string)entry.Key);
311333
object value = entry.Value;
312-
313-
if (value == null)
314-
{
315-
WriteOctet(writer, (byte)'V');
316-
}
317-
else if (value is string)
318-
{
319-
WriteOctet(writer, (byte)'S');
320-
WriteLongstr(writer, Encoding.UTF8.GetBytes((string)value));
321-
}
322-
else if (value is byte[])
323-
{
324-
WriteOctet(writer, (byte)'S');
325-
WriteLongstr(writer, (byte[])value);
326-
}
327-
else if (value is int)
328-
{
329-
WriteOctet(writer, (byte)'I');
330-
writer.Write((int)value);
331-
}
332-
else if (value is decimal)
333-
{
334-
WriteOctet(writer, (byte)'D');
335-
WriteDecimal(writer, (decimal)value);
336-
}
337-
else if (value is AmqpTimestamp)
338-
{
339-
WriteOctet(writer, (byte)'T');
340-
WriteTimestamp(writer, (AmqpTimestamp)value);
341-
}
342-
else if (value is IDictionary)
343-
{
344-
WriteOctet(writer, (byte)'F');
345-
WriteTable(writer, (IDictionary)value);
346-
}
347-
else if (value is byte)
348-
{
349-
WriteOctet(writer, (byte)'b');
350-
WriteOctet(writer, (byte)value);
351-
}
352-
else if (value is double)
353-
{
354-
WriteOctet(writer, (byte)'d');
355-
writer.Write((double)value);
356-
}
357-
else if (value is float)
358-
{
359-
WriteOctet(writer, (byte)'f');
360-
writer.Write((float)value);
361-
}
362-
else if (value is long)
363-
{
364-
WriteOctet(writer, (byte)'l');
365-
writer.Write((long)value);
366-
}
367-
else if (value is short)
368-
{
369-
WriteOctet(writer, (byte)'s');
370-
writer.Write((short)value);
371-
}
372-
else if (value is bool)
373-
{
374-
WriteOctet(writer, (byte)'t');
375-
WriteOctet(writer, (byte)(((bool)value) ? 1 : 0));
376-
}
377-
else if (value is BinaryTableValue)
378-
{
379-
WriteOctet(writer, (byte)'x');
380-
WriteLongstr(writer, ((BinaryTableValue)value).Bytes);
381-
}
382-
else
383-
{
384-
throw new WireFormattingException("Value cannot appear as table value",
385-
value);
386-
}
334+
WriteFieldValue(writer, value);
387335
}
388336

389337
// Now, backpatch the table length.
@@ -395,6 +343,112 @@ public static void WriteTable(NetworkBinaryWriter writer, IDictionary val)
395343
}
396344
}
397345

346+
public static void WriteArray(NetworkBinaryWriter writer, IList val)
347+
{
348+
if (val == null)
349+
{
350+
writer.Write((uint)0);
351+
}
352+
else
353+
{
354+
Stream backingStream = writer.BaseStream;
355+
long patchPosition = backingStream.Position;
356+
writer.Write((uint)0); // length of table - will be backpatched
357+
foreach (object entry in val)
358+
{
359+
WriteFieldValue(writer, entry);
360+
}
361+
long savedPosition = backingStream.Position;
362+
long tableLength = savedPosition - patchPosition - 4; // offset for length word
363+
backingStream.Seek(patchPosition, SeekOrigin.Begin);
364+
writer.Write((uint)tableLength);
365+
backingStream.Seek(savedPosition, SeekOrigin.Begin);
366+
}
367+
}
368+
369+
public static void WriteFieldValue(NetworkBinaryWriter writer, object value)
370+
{
371+
if (value == null)
372+
{
373+
WriteOctet(writer, (byte)'V');
374+
}
375+
else if (value is string)
376+
{
377+
WriteOctet(writer, (byte)'S');
378+
WriteLongstr(writer, Encoding.UTF8.GetBytes((string)value));
379+
}
380+
else if (value is byte[])
381+
{
382+
WriteOctet(writer, (byte)'S');
383+
WriteLongstr(writer, (byte[])value);
384+
}
385+
else if (value is int)
386+
{
387+
WriteOctet(writer, (byte)'I');
388+
writer.Write((int)value);
389+
}
390+
else if (value is decimal)
391+
{
392+
WriteOctet(writer, (byte)'D');
393+
WriteDecimal(writer, (decimal)value);
394+
}
395+
else if (value is AmqpTimestamp)
396+
{
397+
WriteOctet(writer, (byte)'T');
398+
WriteTimestamp(writer, (AmqpTimestamp)value);
399+
}
400+
else if (value is IDictionary)
401+
{
402+
WriteOctet(writer, (byte)'F');
403+
WriteTable(writer, (IDictionary)value);
404+
}
405+
else if (value is IList)
406+
{
407+
WriteOctet(writer, (byte)'A');
408+
WriteArray(writer, (IList)value);
409+
}
410+
else if (value is byte)
411+
{
412+
WriteOctet(writer, (byte)'b');
413+
WriteOctet(writer, (byte)value);
414+
}
415+
else if (value is double)
416+
{
417+
WriteOctet(writer, (byte)'d');
418+
writer.Write((double)value);
419+
}
420+
else if (value is float)
421+
{
422+
WriteOctet(writer, (byte)'f');
423+
writer.Write((float)value);
424+
}
425+
else if (value is long)
426+
{
427+
WriteOctet(writer, (byte)'l');
428+
writer.Write((long)value);
429+
}
430+
else if (value is short)
431+
{
432+
WriteOctet(writer, (byte)'s');
433+
writer.Write((short)value);
434+
}
435+
else if (value is bool)
436+
{
437+
WriteOctet(writer, (byte)'t');
438+
WriteOctet(writer, (byte)(((bool)value) ? 1 : 0));
439+
}
440+
else if (value is BinaryTableValue)
441+
{
442+
WriteOctet(writer, (byte)'x');
443+
WriteLongstr(writer, ((BinaryTableValue)value).Bytes);
444+
}
445+
else
446+
{
447+
throw new WireFormattingException("Value cannot appear as table value",
448+
value);
449+
}
450+
}
451+
398452
public static void WriteTimestamp(NetworkBinaryWriter writer, AmqpTimestamp val)
399453
{
400454
// 0-9 is afaict silent on the signedness of the timestamp.

projects/client/Unit/src/unit/TestFieldTableFormatting.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ public void TestStandardTypes()
8181
Hashtable t2 = new Hashtable();
8282
t["fieldtable"] = t2;
8383
t2["test"] = "test";
84+
IList array = new ArrayList();
85+
array.Add("longstring");
86+
array.Add(1234);
87+
t["fieldarray"] = array;
8488
WireFormatting.WriteTable(w, t);
8589
IDictionary nt = WireFormatting.ReadTable(Reader(Contents(w)));
8690
Assert.AreEqual(Encoding.UTF8.GetBytes("Hello"), nt["string"]);
@@ -89,6 +93,9 @@ public void TestStandardTypes()
8993
Assert.AreEqual(0, ((AmqpTimestamp)nt["timestamp"]).UnixTime);
9094
IDictionary nt2 = (IDictionary)nt["fieldtable"];
9195
Assert.AreEqual(Encoding.UTF8.GetBytes("test"), nt2["test"]);
96+
IList narray = (IList)nt["fieldarray"];
97+
Assert.AreEqual(Encoding.UTF8.GetBytes("longstring"), narray[0]);
98+
Assert.AreEqual(1234, narray[1]);
9299
}
93100

94101
[Test]

0 commit comments

Comments
 (0)