Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions projects/client/RabbitMQ.Client/RabbitMQ.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
<PackageReference Include="System.Memory" Version="4.5.3" />
</ItemGroup>

<ItemGroup Condition=" '$(Configuration)' == 'SignedRelease' ">
Expand Down
90 changes: 17 additions & 73 deletions projects/client/RabbitMQ.Client/src/util/NetworkBinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
//---------------------------------------------------------------------------

using System;
using System.Buffers.Binary;
using System.IO;
using System.Text;

Expand All @@ -54,8 +56,6 @@ namespace RabbitMQ.Util
/// </remarks>
public class NetworkBinaryReader : BinaryReader
{
private static readonly Encoding s_encoding = new UTF8Encoding();

// Not particularly efficient. To be more efficient, we could
// reuse BinaryReader's implementation details: m_buffer and
// FillBuffer, if they weren't private
Expand All @@ -66,82 +66,41 @@ public class NetworkBinaryReader : BinaryReader
/// <summary>
/// Construct a NetworkBinaryReader over the given input stream.
/// </summary>
public NetworkBinaryReader(Stream input) : base(input, s_encoding)
{
}

/// <summary>
/// Construct a NetworkBinaryReader over the given input
/// stream, reading strings using the given encoding.
/// </summary>
public NetworkBinaryReader(Stream input, Encoding encoding) : base(input, encoding)
public NetworkBinaryReader(Stream input) : base(input, Encoding.UTF8)
{
}

///<summary>Helper method for constructing a temporary
///BinaryReader over a byte[].</summary>
public static BinaryReader TemporaryBinaryReader(byte[] bytes)
{
return new BinaryReader(new MemoryStream(bytes));
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override double ReadDouble()
{
byte[] bytes = ReadBytes(8);
byte temp = bytes[0];
bytes[0] = bytes[7];
bytes[7] = temp;
temp = bytes[1];
bytes[1] = bytes[6];
bytes[6] = temp;
temp = bytes[2];
bytes[2] = bytes[5];
bytes[5] = temp;
temp = bytes[3];
bytes[3] = bytes[4];
bytes[4] = temp;
return TemporaryBinaryReader(bytes).ReadDouble();
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's SO NICE to see this sort of code disappear 🎉

long val = BinaryPrimitives.ReadInt64BigEndian(ReadBytes(8));
return BitConverter.Int64BitsToDouble(val);
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override short ReadInt16()
{
uint i = base.ReadUInt16();
return (short)(((i & 0xFF00) >> 8) |
((i & 0x00FF) << 8));
return BinaryPrimitives.ReadInt16BigEndian(ReadBytes(2));
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override int ReadInt32()
{
uint i = base.ReadUInt32();
return (int)(((i & 0xFF000000) >> 24) |
((i & 0x00FF0000) >> 8) |
((i & 0x0000FF00) << 8) |
((i & 0x000000FF) << 24));
return BinaryPrimitives.ReadInt32BigEndian(ReadBytes(4));
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override long ReadInt64()
{
ulong i = base.ReadUInt64();
return (long)(((i & 0xFF00000000000000) >> 56) |
((i & 0x00FF000000000000) >> 40) |
((i & 0x0000FF0000000000) >> 24) |
((i & 0x000000FF00000000) >> 8) |
((i & 0x00000000FF000000) << 8) |
((i & 0x0000000000FF0000) << 24) |
((i & 0x000000000000FF00) << 40) |
((i & 0x00000000000000FF) << 56));
return BinaryPrimitives.ReadInt64BigEndian(ReadBytes(8));
}

/// <summary>
Expand All @@ -150,51 +109,36 @@ public override long ReadInt64()
public override float ReadSingle()
{
byte[] bytes = ReadBytes(4);
byte temp = bytes[0];
bytes[0] = bytes[3];
bytes[3] = temp;
temp = bytes[1];
bytes[1] = bytes[2];
bytes[2] = temp;
return TemporaryBinaryReader(bytes).ReadSingle();
if (BitConverter.IsLittleEndian)
{
bytes.AsSpan().Reverse();
}

return BitConverter.ToSingle(bytes, 0);
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override ushort ReadUInt16()
{
uint i = base.ReadUInt16();
return (ushort)(((i & 0xFF00) >> 8) |
((i & 0x00FF) << 8));
return BinaryPrimitives.ReadUInt16BigEndian(ReadBytes(2));
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override uint ReadUInt32()
{
uint i = base.ReadUInt32();
return ((i & 0xFF000000) >> 24) |
((i & 0x00FF0000) >> 8) |
((i & 0x0000FF00) << 8) |
((i & 0x000000FF) << 24);
return BinaryPrimitives.ReadUInt32BigEndian(ReadBytes(4));
}

/// <summary>
/// Override BinaryReader's method for network-order.
/// </summary>
public override ulong ReadUInt64()
{
ulong i = base.ReadUInt64();
return ((i & 0xFF00000000000000) >> 56) |
((i & 0x00FF000000000000) >> 40) |
((i & 0x0000FF0000000000) >> 24) |
((i & 0x000000FF00000000) >> 8) |
((i & 0x00000000FF000000) << 8) |
((i & 0x0000000000FF0000) << 24) |
((i & 0x000000000000FF00) << 40) |
((i & 0x00000000000000FF) << 56);
return BinaryPrimitives.ReadUInt64BigEndian(ReadBytes(8));
}
}
}
118 changes: 80 additions & 38 deletions projects/client/RabbitMQ.Client/src/util/NetworkBinaryWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
//---------------------------------------------------------------------------

using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;
using System.Text;

Expand Down Expand Up @@ -94,93 +97,132 @@ public static byte[] TemporaryContents(BinaryWriter w)
/// </summary>
public override void Write(short i)
{
Write((byte)((i & 0xFF00) >> 8));
Write((byte)(i & 0x00FF));
byte[] bytes = ArrayPool<byte>.Shared.Rent(2);
try
{
BinaryPrimitives.WriteInt16BigEndian(bytes, i);
Write(bytes, 0, 2);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(ushort i)
{
Write((byte)((i & 0xFF00) >> 8));
Write((byte)(i & 0x00FF));
byte[] bytes = ArrayPool<byte>.Shared.Rent(2);
try
{
BinaryPrimitives.WriteUInt16BigEndian(bytes, i);
Write(bytes, 0, 2);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(int i)
{
Write((byte)((i & 0xFF000000) >> 24));
Write((byte)((i & 0x00FF0000) >> 16));
Write((byte)((i & 0x0000FF00) >> 8));
Write((byte)(i & 0x000000FF));
byte[] bytes = ArrayPool<byte>.Shared.Rent(4);
try
{
BinaryPrimitives.WriteInt32BigEndian(bytes, i);
Write(bytes, 0, 4);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(uint i)
{
Write((byte)((i & 0xFF000000) >> 24));
Write((byte)((i & 0x00FF0000) >> 16));
Write((byte)((i & 0x0000FF00) >> 8));
Write((byte)(i & 0x000000FF));
byte[] bytes = ArrayPool<byte>.Shared.Rent(4);
try
{
BinaryPrimitives.WriteUInt32BigEndian(bytes, i);
Write(bytes, 0, 4);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(long i)
{
uint i1 = (uint)(i >> 32);
uint i2 = (uint)i;
Write(i1);
Write(i2);
byte[] bytes = ArrayPool<byte>.Shared.Rent(8);
try
{
BinaryPrimitives.WriteInt64BigEndian(bytes, i);
Write(bytes, 0, 8);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(ulong i)
{
uint i1 = (uint)(i >> 32);
uint i2 = (uint)i;
Write(i1);
Write(i2);
byte[] bytes = ArrayPool<byte>.Shared.Rent(8);
try
{
BinaryPrimitives.WriteUInt64BigEndian(bytes, i);
Write(bytes, 0, 8);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(float f)
{
BinaryWriter w = TemporaryBinaryWriter(4);
w.Write(f);
byte[] wrongBytes = TemporaryContents(w);
Write(wrongBytes[3]);
Write(wrongBytes[2]);
Write(wrongBytes[1]);
Write(wrongBytes[0]);
byte[] bytes = BitConverter.GetBytes(f);
if (BitConverter.IsLittleEndian)
{
bytes.AsSpan().Reverse();
}

Write(bytes);
}

/// <summary>
/// Override BinaryWriter's method for network-order.
/// </summary>
public override void Write(double d)
{
BinaryWriter w = TemporaryBinaryWriter(8);
w.Write(d);
byte[] wrongBytes = TemporaryContents(w);
Write(wrongBytes[7]);
Write(wrongBytes[6]);
Write(wrongBytes[5]);
Write(wrongBytes[4]);
Write(wrongBytes[3]);
Write(wrongBytes[2]);
Write(wrongBytes[1]);
Write(wrongBytes[0]);
byte[] bytes = ArrayPool<byte>.Shared.Rent(8);
try
{
BinaryPrimitives.WriteInt64BigEndian(bytes, BitConverter.DoubleToInt64Bits(d));
Write(bytes, 0, 8);
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2427,7 +2427,6 @@ namespace RabbitMQ.Util
public class NetworkBinaryReader : System.IO.BinaryReader
{
public NetworkBinaryReader(System.IO.Stream input) { }
public NetworkBinaryReader(System.IO.Stream input, System.Text.Encoding encoding) { }
public override double ReadDouble() { }
public override short ReadInt16() { }
public override int ReadInt32() { }
Expand All @@ -2436,7 +2435,6 @@ namespace RabbitMQ.Util
public override ushort ReadUInt16() { }
public override uint ReadUInt32() { }
public override ulong ReadUInt64() { }
public static System.IO.BinaryReader TemporaryBinaryReader(byte[] bytes) { }
}
public class NetworkBinaryWriter : System.IO.BinaryWriter
{
Expand Down