Skip to content

Commit

Permalink
Merge pull request #579 from sergeyshaykhullin/byte_conversion_support
Browse files Browse the repository at this point in the history
Byte conversion support

(cherry picked from commit c343098)
  • Loading branch information
michaelklishin committed Mar 20, 2019
1 parent cf6156b commit 54bdc24
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 102 deletions.
199 changes: 98 additions & 101 deletions projects/client/RabbitMQ.Client/src/client/impl/WireFormatting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,17 @@ public static decimal AmqpToDecimal(byte scale, uint unsignedMantissa)
throw new SyntaxError("Unrepresentable AMQP decimal table field: " +
"scale=" + scale);
}
return new decimal((int)(unsignedMantissa & 0x7FFFFFFF),
0,
0,
((unsignedMantissa & 0x80000000) == 0) ? false : true,
scale);

return new decimal(
// The low 32 bits of a 96-bit integer
lo: (int)(unsignedMantissa & 0x7FFFFFFF),
// The middle 32 bits of a 96-bit integer.
mid: 0,
// The high 32 bits of a 96-bit integer.
hi: 0,
isNegative: (unsignedMantissa & 0x80000000) != 0,
// A power of 10 ranging from 0 to 28.
scale: scale);
}

public static void DecimalToAmqp(decimal value, out byte scale, out int mantissa)
Expand Down Expand Up @@ -91,7 +97,7 @@ public static IList ReadArray(NetworkBinaryReader reader)
{
IList array = new List<object>();
long arrayLength = reader.ReadUInt32();
Stream backingStream = reader.BaseStream;
var backingStream = reader.BaseStream;
long startPosition = backingStream.Position;
while ((backingStream.Position - startPosition) < arrayLength)
{
Expand Down Expand Up @@ -129,10 +135,12 @@ public static object ReadFieldValue(NetworkBinaryReader reader)
case 'F':
value = ReadTable(reader);
break;

case 'A':
value = ReadArray(reader);
break;
case 'B':
value = reader.ReadByte();
break;
case 'b':
value = reader.ReadSByte();
break;
Expand Down Expand Up @@ -215,7 +223,7 @@ public static IDictionary<string, object> ReadTable(NetworkBinaryReader reader)
IDictionary<string, object> table = new Dictionary<string, object>();
long tableLength = reader.ReadUInt32();

Stream backingStream = reader.BaseStream;
var backingStream = reader.BaseStream;
long startPosition = backingStream.Position;
while ((backingStream.Position - startPosition) < tableLength)
{
Expand Down Expand Up @@ -247,7 +255,7 @@ public static void WriteArray(NetworkBinaryWriter writer, IList val)
}
else
{
Stream backingStream = writer.BaseStream;
var backingStream = writer.BaseStream;
long patchPosition = backingStream.Position;
writer.Write((uint)0); // length of table - will be backpatched
foreach (object entry in val)
Expand All @@ -264,93 +272,82 @@ public static void WriteArray(NetworkBinaryWriter writer, IList val)

public static void WriteDecimal(NetworkBinaryWriter writer, decimal value)
{
byte scale;
int mantissa;
DecimalToAmqp(value, out scale, out mantissa);
DecimalToAmqp(value, out var scale, out var mantissa);
WriteOctet(writer, scale);
WriteLong(writer, (uint)mantissa);
}

public static void WriteFieldValue(NetworkBinaryWriter writer, object value)
{
if (value == null)
{
WriteOctet(writer, (byte)'V');
}
else if (value is string)
{
WriteOctet(writer, (byte)'S');
WriteLongstr(writer, Encoding.UTF8.GetBytes((string)value));
}
else if (value is byte[])
{
WriteOctet(writer, (byte)'S');
WriteLongstr(writer, (byte[])value);
}
else if (value is int)
{
WriteOctet(writer, (byte)'I');
writer.Write((int)value);
}
else if (value is decimal)
{
WriteOctet(writer, (byte)'D');
WriteDecimal(writer, (decimal)value);
}
else if (value is AmqpTimestamp)
{
WriteOctet(writer, (byte)'T');
WriteTimestamp(writer, (AmqpTimestamp)value);
}
else if (value is IDictionary)
{
WriteOctet(writer, (byte)'F');
WriteTable(writer, (IDictionary)value);
}
else if (value is IList)
{
WriteOctet(writer, (byte)'A');
WriteArray(writer, (IList)value);
}
else if (value is sbyte)
{
WriteOctet(writer, (byte)'b');
writer.Write((sbyte)value);
}
else if (value is double)
{
WriteOctet(writer, (byte)'d');
writer.Write((double)value);
}
else if (value is float)
{
WriteOctet(writer, (byte)'f');
writer.Write((float)value);
}
else if (value is long)
{
WriteOctet(writer, (byte)'l');
writer.Write((long)value);
}
else if (value is short)
{
WriteOctet(writer, (byte)'s');
writer.Write((short)value);
}
else if (value is bool)
switch (value)
{
WriteOctet(writer, (byte)'t');
WriteOctet(writer, (byte)(((bool)value) ? 1 : 0));
}
else if (value is BinaryTableValue)
{
WriteOctet(writer, (byte)'x');
WriteLongstr(writer, ((BinaryTableValue)value).Bytes);
}
else
{
throw new WireFormattingException("Value cannot appear as table value",
value);
case null:
WriteOctet(writer, (byte)'V');
break;
case string val:
WriteOctet(writer, (byte)'S');
WriteLongstr(writer, Encoding.UTF8.GetBytes(val));
break;
case byte[] val:
WriteOctet(writer, (byte)'S');
WriteLongstr(writer, val);
break;
case int val:
WriteOctet(writer, (byte)'I');
writer.Write(val);
break;
case decimal val:
WriteOctet(writer, (byte)'D');
WriteDecimal(writer, val);
break;
case AmqpTimestamp val:
WriteOctet(writer, (byte)'T');
WriteTimestamp(writer, val);
break;
case IDictionary val:
WriteOctet(writer, (byte)'F');
WriteTable(writer, val);
break;
case IList val:
WriteOctet(writer, (byte)'A');
WriteArray(writer, val);
break;
case byte val:
WriteOctet(writer, (byte)'B');
writer.Write(val);
break;
case sbyte val:
WriteOctet(writer, (byte)'b');
writer.Write(val);
break;
case double val:
WriteOctet(writer, (byte)'d');
writer.Write(val);
break;
case float val:
WriteOctet(writer, (byte)'f');
writer.Write(val);
break;
case long val:
WriteOctet(writer, (byte)'l');
writer.Write(val);
break;
case short val:
WriteOctet(writer, (byte)'s');
writer.Write(val);
break;
case bool val:
WriteOctet(writer, (byte)'t');
WriteOctet(writer, (byte)(val ? 1 : 0));
break;
case BinaryTableValue val:
WriteOctet(writer, (byte)'x');
WriteLongstr(writer, val.Bytes);
break;
default:
throw new WireFormattingException(
$"Value of type '{value.GetType().Name}' cannot appear as table value",
value);
}
}

Expand Down Expand Up @@ -382,14 +379,16 @@ public static void WriteShort(NetworkBinaryWriter writer, ushort val)

public static void WriteShortstr(NetworkBinaryWriter writer, string val)
{
byte[] bytes = Encoding.UTF8.GetBytes(val);
int len = bytes.Length;
if (len > 255)
var bytes = Encoding.UTF8.GetBytes(val);
var length = bytes.Length;

if (length > 255)
{
throw new WireFormattingException("Short string too long; " +
"UTF-8 encoded length=" + len + ", max=255");
"UTF-8 encoded length=" + length + ", max=255");
}
writer.Write((byte)len);

writer.Write((byte)length);
writer.Write(bytes);
}

Expand All @@ -415,15 +414,14 @@ public static void WriteTable(NetworkBinaryWriter writer, IDictionary val)
}
else
{
Stream backingStream = writer.BaseStream;
var backingStream = writer.BaseStream;
long patchPosition = backingStream.Position;
writer.Write((uint)0); // length of table - will be backpatched

foreach (DictionaryEntry entry in val)
{
WriteShortstr(writer, entry.Key.ToString());
object value = entry.Value;
WriteFieldValue(writer, value);
WriteFieldValue(writer, entry.Value);
}

// Now, backpatch the table length.
Expand Down Expand Up @@ -457,15 +455,14 @@ public static void WriteTable(NetworkBinaryWriter writer, IDictionary<string, ob
}
else
{
Stream backingStream = writer.BaseStream;
var backingStream = writer.BaseStream;
long patchPosition = backingStream.Position;
writer.Write((uint)0); // length of table - will be backpatched

foreach (KeyValuePair<string, object> entry in val)
foreach (var entry in val)
{
WriteShortstr(writer, entry.Key);
object value = entry.Value;
WriteFieldValue(writer, value);
WriteFieldValue(writer, entry.Value);
}

// Now, backpatch the table length.
Expand Down
4 changes: 3 additions & 1 deletion projects/client/Unit/src/unit/TestFieldTableFormatting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,19 @@ public void TestQpidJmsTypes()
{
NetworkBinaryWriter w = Writer();
Hashtable t = new Hashtable();
t["B"] = (byte)255;
t["b"] = (sbyte)-128;
t["d"] = (double)123;
t["f"] = (float)123;
t["l"] = (long)123;
t["s"] = (short)123;
t["t"] = true;
byte[] xbytes = new byte[] { 0xaa, 0x55 };
byte[] xbytes = { 0xaa, 0x55 };
t["x"] = new BinaryTableValue(xbytes);
t["V"] = null;
WireFormatting.WriteTable(w, t);
IDictionary nt = (IDictionary)WireFormatting.ReadTable(Reader(Contents(w)));
Assert.AreEqual(typeof(byte), nt["B"].GetType()); Assert.AreEqual((byte)255, nt["B"]);
Assert.AreEqual(typeof(sbyte), nt["b"].GetType()); Assert.AreEqual((sbyte)-128, nt["b"]);
Assert.AreEqual(typeof(double), nt["d"].GetType()); Assert.AreEqual((double)123, nt["d"]);
Assert.AreEqual(typeof(float), nt["f"].GetType()); Assert.AreEqual((float)123, nt["f"]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public void TestQpidJmsTypes()
{
NetworkBinaryWriter w = Writer();
IDictionary<string, object> t = new Dictionary<string, object>();
t["B"] = (byte)255;
t["b"] = (sbyte)-128;
t["d"] = (double)123;
t["f"] = (float)123;
Expand All @@ -130,6 +131,7 @@ public void TestQpidJmsTypes()
t["V"] = null;
WireFormatting.WriteTable(w, t);
IDictionary nt = (IDictionary)WireFormatting.ReadTable(Reader(Contents(w)));
Assert.AreEqual(typeof(byte), nt["B"].GetType()); Assert.AreEqual((byte)255, nt["B"]);
Assert.AreEqual(typeof(sbyte), nt["b"].GetType()); Assert.AreEqual((sbyte)-128, nt["b"]);
Assert.AreEqual(typeof(double), nt["d"].GetType()); Assert.AreEqual((double)123, nt["d"]);
Assert.AreEqual(typeof(float), nt["f"].GetType()); Assert.AreEqual((float)123, nt["f"]);
Expand Down

0 comments on commit 54bdc24

Please sign in to comment.