Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Byte conversion support #579

Merged
merged 4 commits into from
Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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':
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading

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:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing

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",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some exception details

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