diff --git a/projects/RabbitMQ.Client/util/NetworkOrderDeserializer.cs b/projects/RabbitMQ.Client/util/NetworkOrderDeserializer.cs index 3de2cce2d0..95ff99b0e3 100644 --- a/projects/RabbitMQ.Client/util/NetworkOrderDeserializer.cs +++ b/projects/RabbitMQ.Client/util/NetworkOrderDeserializer.cs @@ -1,13 +1,14 @@ using System; -using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace RabbitMQ.Util { internal static class NetworkOrderDeserializer { + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double ReadDouble(ReadOnlyMemory memory) => ReadDouble(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double ReadDouble(ReadOnlySpan span) { if (span.Length < 8) @@ -15,12 +16,14 @@ internal static double ReadDouble(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode Double from memory."); } - long val = BinaryPrimitives.ReadInt64BigEndian(span); - return Unsafe.As(ref val); + ulong val = ReadUInt64(span); + return Unsafe.As(ref val); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static short ReadInt16(ReadOnlyMemory memory) => ReadInt16(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static short ReadInt16(ReadOnlySpan span) { if (span.Length < 2) @@ -28,11 +31,13 @@ internal static short ReadInt16(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode Int16 from memory."); } - return BinaryPrimitives.ReadInt16BigEndian(span); + return (short)ReadUInt16(span); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int ReadInt32(ReadOnlyMemory memory) => ReadInt32(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int ReadInt32(ReadOnlySpan span) { if (span.Length < 4) @@ -40,11 +45,13 @@ internal static int ReadInt32(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode Int32 from memory."); } - return BinaryPrimitives.ReadInt32BigEndian(span); + return (int)ReadUInt32(span); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static long ReadInt64(ReadOnlyMemory memory) => ReadInt64(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static long ReadInt64(ReadOnlySpan span) { if (span.Length < 8) @@ -52,11 +59,13 @@ internal static long ReadInt64(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode Int64 from memory."); } - return BinaryPrimitives.ReadInt64BigEndian(span); + return (long)ReadUInt64(span); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static float ReadSingle(ReadOnlyMemory memory) => ReadSingle(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static float ReadSingle(ReadOnlySpan span) { if (span.Length < 4) @@ -64,12 +73,14 @@ internal static float ReadSingle(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode Single from memory."); } - int num = BinaryPrimitives.ReadInt32BigEndian(span); - return Unsafe.As(ref num); + uint num = ReadUInt32(span); + return Unsafe.As(ref num); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ushort ReadUInt16(ReadOnlyMemory memory) => ReadUInt16(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ushort ReadUInt16(ReadOnlySpan span) { if (span.Length < 2) @@ -77,11 +88,13 @@ internal static ushort ReadUInt16(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode UInt16 from memory."); } - return BinaryPrimitives.ReadUInt16BigEndian(span); + return (ushort)((span[0] << 8) | span[1]); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static uint ReadUInt32(ReadOnlyMemory memory) => ReadUInt32(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static uint ReadUInt32(ReadOnlySpan span) { if (span.Length < 4) @@ -89,11 +102,13 @@ internal static uint ReadUInt32(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode UInt32 from memory."); } - return BinaryPrimitives.ReadUInt32BigEndian(span); + return (uint)((span[0] << 24) | (span[1] << 16) | (span[2] << 8) | span[3]); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong ReadUInt64(ReadOnlyMemory memory) => ReadUInt64(memory.Span); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong ReadUInt64(ReadOnlySpan span) { if (span.Length < 8) @@ -101,7 +116,9 @@ internal static ulong ReadUInt64(ReadOnlySpan span) throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to decode UInt64 from memory."); } - return BinaryPrimitives.ReadUInt64BigEndian(span); + uint num1 = (uint)((span[0] << 24) | (span[1] << 16) | (span[2] << 8) | span[3]); + uint num2 = (uint)((span[4] << 24) | (span[5] << 16) | (span[6] << 8) | span[7]); + return ((ulong)num1 << 32) | num2; } } } diff --git a/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs b/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs index 992a3a082d..1435723e95 100644 --- a/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs +++ b/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs @@ -1,10 +1,13 @@ using System; using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace RabbitMQ.Util { internal static class NetworkOrderSerializer { + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteDouble(Memory memory, double val) { if (memory.Length < 8) @@ -12,9 +15,11 @@ internal static void WriteDouble(Memory memory, double val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write Double to memory."); } - BinaryPrimitives.WriteInt64BigEndian(memory.Span, BitConverter.DoubleToInt64Bits(val)); + long tempVal = BitConverter.DoubleToInt64Bits(val); + SerializeInt64(memory.Span, tempVal); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteInt16(Memory memory, short val) { if (memory.Length < 2) @@ -22,9 +27,10 @@ internal static void WriteInt16(Memory memory, short val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write Int16 to memory."); } - BinaryPrimitives.WriteInt16BigEndian(memory.Span, val); + SerializeInt16(memory.Span, val); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteInt32(Memory memory, int val) { if (memory.Length < 4) @@ -32,9 +38,10 @@ internal static void WriteInt32(Memory memory, int val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write Int32 to memory."); } - BinaryPrimitives.WriteInt32BigEndian(memory.Span, val); + SerializeInt32(memory.Span, val); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteInt64(Memory memory, long val) { if (memory.Length < 8) @@ -42,9 +49,10 @@ internal static void WriteInt64(Memory memory, long val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write Int64 to memory."); } - BinaryPrimitives.WriteInt64BigEndian(memory.Span, val); - } + SerializeInt64(memory.Span, val); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteSingle(Memory memory, float val) { if (memory.Length < 4) @@ -52,15 +60,11 @@ internal static void WriteSingle(Memory memory, float val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write Single to memory."); } - byte[] bytes = BitConverter.GetBytes(val); - if (BitConverter.IsLittleEndian) - { - Array.Reverse(bytes); - } - - bytes.AsMemory().CopyTo(memory); + int tempVal = Unsafe.As(ref val); + SerializeInt32(memory.Span, tempVal); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteUInt16(Memory memory, ushort val) { if (memory.Length < 2) @@ -68,9 +72,10 @@ internal static void WriteUInt16(Memory memory, ushort val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write UInt16 to memory."); } - BinaryPrimitives.WriteUInt16BigEndian(memory.Span, val); + SerializeUInt16(memory.Span, val); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteUInt32(Memory memory, uint val) { if (memory.Length < 4) @@ -78,9 +83,11 @@ internal static void WriteUInt32(Memory memory, uint val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write UInt32 to memory."); } - BinaryPrimitives.WriteUInt32BigEndian(memory.Span, val); + SerializeUInt32(memory.Span, val); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteUInt64(Memory memory, ulong val) { if (memory.Length < 8) @@ -88,7 +95,54 @@ internal static void WriteUInt64(Memory memory, ulong val) throw new ArgumentOutOfRangeException(nameof(memory), "Insufficient length to write UInt64 from memory."); } - BinaryPrimitives.WriteUInt64BigEndian(memory.Span, val); + SerializeUInt64(memory.Span, val); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeInt16(Span memory, short val) + { + SerializeUInt16(memory, (ushort)val); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeUInt16(Span memory, ushort val) + { + memory[0] = (byte)((val >> 8) & 0xFF); + memory[1] = (byte)(val & 0xFF); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeInt32(Span memory, int val) + { + SerializeUInt32(memory, (uint)val); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeUInt32(Span memory, uint val) + { + memory[0] = (byte)((val >> 24) & 0xFF); + memory[1] = (byte)((val >> 16) & 0xFF); + memory[2] = (byte)((val >> 8) & 0xFF); + memory[3] = (byte)(val & 0xFF); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeInt64(Span memory, long val) + { + SerializeUInt64(memory, (ulong)val); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SerializeUInt64(Span memory, ulong val) + { + memory[0] = (byte)((val >> 56) & 0xFF); + memory[1] = (byte)((val >> 48) & 0xFF); + memory[2] = (byte)((val >> 40) & 0xFF); + memory[3] = (byte)((val >> 32) & 0xFF); + memory[4] = (byte)((val >> 24) & 0xFF); + memory[5] = (byte)((val >> 16) & 0xFF); + memory[6] = (byte)((val >> 8) & 0xFF); + memory[7] = (byte)(val & 0xFF); } } }