diff --git a/RabbitMQDotNetClient.sln b/RabbitMQDotNetClient.sln index e7b966dc5e..f39ee45490 100644 --- a/RabbitMQDotNetClient.sln +++ b/RabbitMQDotNetClient.sln @@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RabbitMQ.Client", "projects EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unit", "projects\Unit\Unit.csproj", "{B8FAC024-CC03-4067-9FFC-02846FB8AE48}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "projects\Benchmarks\Benchmarks.csproj", "{38D72C9A-68E9-4653-B0CE-C7BA9FFD91D0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,6 +28,10 @@ Global {B8FAC024-CC03-4067-9FFC-02846FB8AE48}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8FAC024-CC03-4067-9FFC-02846FB8AE48}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8FAC024-CC03-4067-9FFC-02846FB8AE48}.Release|Any CPU.Build.0 = Release|Any CPU + {38D72C9A-68E9-4653-B0CE-C7BA9FFD91D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38D72C9A-68E9-4653-B0CE-C7BA9FFD91D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38D72C9A-68E9-4653-B0CE-C7BA9FFD91D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38D72C9A-68E9-4653-B0CE-C7BA9FFD91D0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/projects/Benchmarks/Benchmarks.csproj b/projects/Benchmarks/Benchmarks.csproj new file mode 100644 index 0000000000..e69b9683d0 --- /dev/null +++ b/projects/Benchmarks/Benchmarks.csproj @@ -0,0 +1,18 @@ + + + + Exe + ../rabbit.snk + true + netcoreapp3.1 + + + + + + + + + + + diff --git a/projects/Benchmarks/Program.cs b/projects/Benchmarks/Program.cs new file mode 100644 index 0000000000..9843e9293b --- /dev/null +++ b/projects/Benchmarks/Program.cs @@ -0,0 +1,12 @@ +using BenchmarkDotNet.Running; + +namespace Benchmarks +{ + public static class Program + { + public static void Main(string[] args) + { + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicAck.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicAck.cs new file mode 100644 index 0000000000..118a0f813f --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicAck.cs @@ -0,0 +1,24 @@ +using System; +using BenchmarkDotNet.Attributes; +using RabbitMQ.Client.Framing.Impl; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Read_BasicAck + { + private readonly byte[] _buffer = new byte[1024]; + + public WireFormatting_Read_BasicAck() + { + new BasicAck(ulong.MaxValue, true).WriteArgumentsTo(_buffer); + } + + [Benchmark(Baseline = true)] + public object ReadFromSpan() + { + return new BasicAck(new ReadOnlySpan(_buffer)); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicDeliver.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicDeliver.cs new file mode 100644 index 0000000000..7e01e98c4f --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicDeliver.cs @@ -0,0 +1,24 @@ +using System; +using BenchmarkDotNet.Attributes; +using BasicDeliver = RabbitMQ.Client.Framing.Impl.BasicDeliver; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Read_BasicDeliver + { + private readonly byte[] _buffer = new byte[1024]; + + public WireFormatting_Read_BasicDeliver() + { + new BasicDeliver(string.Empty, 0, false, string.Empty, string.Empty).WriteArgumentsTo(_buffer); + } + + [Benchmark(Baseline = true)] + public object ReadFromSpan() + { + return new BasicDeliver(new ReadOnlySpan(_buffer)); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicProperties.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicProperties.cs new file mode 100644 index 0000000000..3d32a0268e --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Read_BasicProperties.cs @@ -0,0 +1,29 @@ +using System; +using BenchmarkDotNet.Attributes; +using BasicProperties = RabbitMQ.Client.Framing.BasicProperties; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Read_BasicProperties + { + private readonly byte[] _buffer = new byte[1024]; + + public WireFormatting_Read_BasicProperties() + { + new BasicProperties + { + Persistent = true, + AppId = "AppId", + ContentEncoding = "content" + }.WritePropertiesTo(_buffer); + } + + [Benchmark(Baseline = true)] + public object ReadFromSpan() + { + return new BasicProperties(new ReadOnlySpan(_buffer)); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Read_ChannelClose.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Read_ChannelClose.cs new file mode 100644 index 0000000000..69d3b24b64 --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Read_ChannelClose.cs @@ -0,0 +1,24 @@ +using System; +using BenchmarkDotNet.Attributes; +using RabbitMQ.Client.Framing.Impl; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Read_ChannelClose + { + private readonly byte[] _buffer = new byte[1024]; + + public WireFormatting_Read_ChannelClose() + { + new ChannelClose(333, string.Empty, 0099, 2999).WriteArgumentsTo(_buffer); + } + + [Benchmark(Baseline = true)] + public object ReadFromSpan() + { + return new ChannelClose(new ReadOnlySpan(_buffer)); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicAck.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicAck.cs new file mode 100644 index 0000000000..4a7c5f3db4 --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicAck.cs @@ -0,0 +1,19 @@ +using BenchmarkDotNet.Attributes; +using RabbitMQ.Client.Framing.Impl; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Write_BasicAck + { + private readonly byte[] _buffer = new byte[1024]; + private readonly BasicAck _method = new BasicAck(ulong.MaxValue, true); + + [Benchmark(Baseline = true)] + public int WriteArgumentsTo() + { + return _method.WriteArgumentsTo(_buffer); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicDeliver.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicDeliver.cs new file mode 100644 index 0000000000..dadf3185f0 --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicDeliver.cs @@ -0,0 +1,19 @@ +using BenchmarkDotNet.Attributes; +using BasicDeliver = RabbitMQ.Client.Framing.Impl.BasicDeliver; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Write_BasicDeliver + { + private readonly byte[] _buffer = new byte[1024]; + private readonly BasicDeliver _method = new BasicDeliver(string.Empty, 0, false, string.Empty, string.Empty); + + [Benchmark(Baseline = true)] + public int WriteArgumentsTo() + { + return _method.WriteArgumentsTo(_buffer); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicProperties.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicProperties.cs new file mode 100644 index 0000000000..1fc9210525 --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Write_BasicProperties.cs @@ -0,0 +1,25 @@ +using System; +using BenchmarkDotNet.Attributes; +using BasicProperties = RabbitMQ.Client.Framing.BasicProperties; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Write_BasicProperties + { + private readonly byte[] _buffer = new byte[1024]; + private readonly BasicProperties _properties = new BasicProperties + { + Persistent = true, + AppId = "AppId", + ContentEncoding = "content", + }; + + [Benchmark(Baseline = true)] + public void WritePropertiesToSpan() + { + _properties.WritePropertiesTo(new Span(_buffer)); + } + } +} diff --git a/projects/Benchmarks/WireFormatting/WireFormatting_Write_ChannelClose.cs b/projects/Benchmarks/WireFormatting/WireFormatting_Write_ChannelClose.cs new file mode 100644 index 0000000000..a4eada41b8 --- /dev/null +++ b/projects/Benchmarks/WireFormatting/WireFormatting_Write_ChannelClose.cs @@ -0,0 +1,19 @@ +using BenchmarkDotNet.Attributes; +using RabbitMQ.Client.Framing.Impl; + +namespace Benchmarks.WireFormatting +{ + [ShortRunJob] + [MemoryDiagnoser] + public class WireFormatting_Write_ChannelClose + { + private readonly byte[] _buffer = new byte[1024]; + private readonly ChannelClose _method = new ChannelClose(333, string.Empty, 0099, 2999); + + [Benchmark(Baseline = true)] + public int WriteArgumentsTo() + { + return _method.WriteArgumentsTo(_buffer); + } + } +} diff --git a/projects/RabbitMQ.Client/RabbitMQ.Client.csproj b/projects/RabbitMQ.Client/RabbitMQ.Client.csproj index 525b76c192..baf2f47196 100755 --- a/projects/RabbitMQ.Client/RabbitMQ.Client.csproj +++ b/projects/RabbitMQ.Client/RabbitMQ.Client.csproj @@ -51,6 +51,9 @@ <_Parameter1>Unit, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d20ec856aeeb8c3153a77faa2d80e6e43b5db93224a20cc7ae384f65f142e89730e2ff0fcc5d578bbe96fa98a7196c77329efdee4579b3814c0789e5a39b51df6edd75b602a33ceabdfcf19a3feb832f31d8254168cd7ba5700dfbca301fbf8db614ba41ba18474de0a5f4c2d51c995bc3636c641c8cbe76f45717bfcb943b5 + + <_Parameter1>Benchmarks, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d20ec856aeeb8c3153a77faa2d80e6e43b5db93224a20cc7ae384f65f142e89730e2ff0fcc5d578bbe96fa98a7196c77329efdee4579b3814c0789e5a39b51df6edd75b602a33ceabdfcf19a3feb832f31d8254168cd7ba5700dfbca301fbf8db614ba41ba18474de0a5f4c2d51c995bc3636c641c8cbe76f45717bfcb943b5 + diff --git a/projects/RabbitMQ.Client/client/framing/BasicAck.cs b/projects/RabbitMQ.Client/client/framing/BasicAck.cs index 321fafea2f..30a921c5fa 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicAck.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicAck.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -48,21 +50,20 @@ public BasicAck(ulong DeliveryTag, bool Multiple) _multiple = Multiple; } + public BasicAck(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLonglong(span, out _deliveryTag); + WireFormatting.ReadBits(span.Slice(offset), out _multiple); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicAck; public override string ProtocolMethodName => "basic.ack"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _deliveryTag = reader.ReadLonglong(); - _multiple = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLonglong(_deliveryTag); - writer.WriteBit(_multiple); - writer.EndBits(); + int offset = WireFormatting.WriteLonglong(span, _deliveryTag); + return offset + WireFormatting.WriteBits(span.Slice(offset), _multiple); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicCancel.cs b/projects/RabbitMQ.Client/client/framing/BasicCancel.cs index 48f2ef9bd3..1364ec91de 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicCancel.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicCancel.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -49,21 +51,20 @@ public BasicCancel(string ConsumerTag, bool Nowait) _nowait = Nowait; } + public BasicCancel(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShortstr(span, out _consumerTag); + WireFormatting.ReadBits(span.Slice(offset), out _nowait); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicCancel; public override string ProtocolMethodName => "basic.cancel"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _consumerTag = reader.ReadShortstr(); - _nowait = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_consumerTag); - writer.WriteBit(_nowait); - writer.EndBits(); + int offset = WireFormatting.WriteShortstr(span, _consumerTag); + return offset + WireFormatting.WriteBits(span.Slice(offset), _nowait); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicCancelOk.cs b/projects/RabbitMQ.Client/client/framing/BasicCancelOk.cs index 645cd604fc..9b5b73d091 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicCancelOk.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicCancelOk.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public BasicCancelOk(string ConsumerTag) _consumerTag = ConsumerTag; } + public BasicCancelOk(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _consumerTag); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicCancelOk; public override string ProtocolMethodName => "basic.cancel-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _consumerTag = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_consumerTag); + return WireFormatting.WriteShortstr(span, _consumerTag); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicConsume.cs b/projects/RabbitMQ.Client/client/framing/BasicConsume.cs index 7373133c1e..252492e127 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicConsume.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicConsume.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -63,33 +64,27 @@ public BasicConsume(ushort Reserved1, string Queue, string ConsumerTag, bool NoL _arguments = Arguments; } + public BasicConsume(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span, out _queue); + offset += WireFormatting.ReadShortstr(span, out _consumerTag); + offset += WireFormatting.ReadBits(span.Slice(offset), out _noLocal, out _noAck, out _exclusive, out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicConsume; public override string ProtocolMethodName => "basic.consume"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _consumerTag = reader.ReadShortstr(); - _noLocal = reader.ReadBit(); - _noAck = reader.ReadBit(); - _exclusive = reader.ReadBit(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteShortstr(_consumerTag); - writer.WriteBit(_noLocal); - writer.WriteBit(_noAck); - writer.WriteBit(_exclusive); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _consumerTag); + offset += WireFormatting.WriteBits(span.Slice(offset), _noLocal, _noAck, _exclusive, _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicConsumeOk.cs b/projects/RabbitMQ.Client/client/framing/BasicConsumeOk.cs index 87ae07838c..44a6854e70 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicConsumeOk.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicConsumeOk.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public BasicConsumeOk(string ConsumerTag) _consumerTag = ConsumerTag; } + public BasicConsumeOk(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _consumerTag); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicConsumeOk; public override string ProtocolMethodName => "basic.consume-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _consumerTag = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_consumerTag); + return WireFormatting.WriteShortstr(span, _consumerTag); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicDeliver.cs b/projects/RabbitMQ.Client/client/framing/BasicDeliver.cs index 7316addb42..1ac81c5011 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicDeliver.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicDeliver.cs @@ -29,8 +29,11 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; +using System.Buffers.Binary; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -55,27 +58,26 @@ public BasicDeliver(string ConsumerTag, ulong DeliveryTag, bool Redelivered, str _routingKey = RoutingKey; } + public BasicDeliver(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShortstr(span, out _consumerTag); + offset += WireFormatting.ReadLonglong(span.Slice(offset), out _deliveryTag); + offset += WireFormatting.ReadBits(span.Slice(offset), out _redelivered); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicDeliver; public override string ProtocolMethodName => "basic.deliver"; public override bool HasContent => true; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _consumerTag = reader.ReadShortstr(); - _deliveryTag = reader.ReadLonglong(); - _redelivered = reader.ReadBit(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_consumerTag); - writer.WriteLonglong(_deliveryTag); - writer.WriteBit(_redelivered); - writer.EndBits(); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); + int offset = WireFormatting.WriteShortstr(span, _consumerTag); + offset += WireFormatting.WriteLonglong(span.Slice(offset), _deliveryTag); + offset += WireFormatting.WriteBits(span.Slice(offset), _redelivered); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + return offset + WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicGet.cs b/projects/RabbitMQ.Client/client/framing/BasicGet.cs index cb9055e594..6c84d79622 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicGet.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicGet.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -51,23 +53,22 @@ public BasicGet(ushort Reserved1, string Queue, bool NoAck) _noAck = NoAck; } + public BasicGet(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + WireFormatting.ReadBits(span.Slice(offset), out _noAck); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicGet; public override string ProtocolMethodName => "basic.get"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _noAck = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteBit(_noAck); - writer.EndBits(); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + return offset + WireFormatting.WriteBits(span.Slice(offset), _noAck); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicGetEmpty.cs b/projects/RabbitMQ.Client/client/framing/BasicGetEmpty.cs index 6a9dd00f85..1c163f53b6 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicGetEmpty.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicGetEmpty.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public BasicGetEmpty(string Reserved1) _reserved1 = Reserved1; } + public BasicGetEmpty(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _reserved1); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicGetEmpty; public override string ProtocolMethodName => "basic.get-empty"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_reserved1); + return WireFormatting.WriteShortstr(span, _reserved1); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicGetOk.cs b/projects/RabbitMQ.Client/client/framing/BasicGetOk.cs index 594f4583d9..e490bf2243 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicGetOk.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicGetOk.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -55,27 +57,26 @@ public BasicGetOk(ulong DeliveryTag, bool Redelivered, string Exchange, string R _messageCount = MessageCount; } + public BasicGetOk(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLonglong(span, out _deliveryTag); + offset += WireFormatting.ReadBits(span.Slice(offset), out _redelivered); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + WireFormatting.ReadLong(span.Slice(offset), out _messageCount); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicGetOk; public override string ProtocolMethodName => "basic.get-ok"; public override bool HasContent => true; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _deliveryTag = reader.ReadLonglong(); - _redelivered = reader.ReadBit(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _messageCount = reader.ReadLong(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLonglong(_deliveryTag); - writer.WriteBit(_redelivered); - writer.EndBits(); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); - writer.WriteLong(_messageCount); + int offset = WireFormatting.WriteLonglong(span, _deliveryTag); + offset += WireFormatting.WriteBits(span.Slice(offset), _redelivered); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + return offset + WireFormatting.WriteLong(span.Slice(offset), _messageCount); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicNack.cs b/projects/RabbitMQ.Client/client/framing/BasicNack.cs index 0bd67b7555..1f2186647b 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicNack.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicNack.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -50,23 +52,20 @@ public BasicNack(ulong DeliveryTag, bool Multiple, bool Requeue) _requeue = Requeue; } + public BasicNack(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLonglong(span, out _deliveryTag); + WireFormatting.ReadBits(span.Slice(offset), out _multiple, out _requeue); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicNack; public override string ProtocolMethodName => "basic.nack"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _deliveryTag = reader.ReadLonglong(); - _multiple = reader.ReadBit(); - _requeue = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLonglong(_deliveryTag); - writer.WriteBit(_multiple); - writer.WriteBit(_requeue); - writer.EndBits(); + int offset = WireFormatting.WriteLonglong(span, _deliveryTag); + return offset + WireFormatting.WriteBits(span.Slice(offset), _multiple, _requeue); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicProperties.cs b/projects/RabbitMQ.Client/client/framing/BasicProperties.cs index fd89e8139e..362ced0f13 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicProperties.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicProperties.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.Impl; @@ -197,73 +198,63 @@ public BasicProperties() { } - public override ushort ProtocolClassId => 60; - public override string ProtocolClassName => "basic"; - - internal override void ReadPropertiesFrom(ref ContentHeaderPropertyReader reader) + public BasicProperties(ReadOnlySpan span) { - bool contentType_present = reader.ReadPresence(); - bool contentEncoding_present = reader.ReadPresence(); - bool headers_present = reader.ReadPresence(); - bool deliveryMode_present = reader.ReadPresence(); - bool priority_present = reader.ReadPresence(); - bool correlationId_present = reader.ReadPresence(); - bool replyTo_present = reader.ReadPresence(); - bool expiration_present = reader.ReadPresence(); - bool messageId_present = reader.ReadPresence(); - bool timestamp_present = reader.ReadPresence(); - bool type_present = reader.ReadPresence(); - bool userId_present = reader.ReadPresence(); - bool appId_present = reader.ReadPresence(); - bool clusterId_present = reader.ReadPresence(); - reader.FinishPresence(); - if (contentType_present) { _contentType = reader.ReadShortstr(); } - if (contentEncoding_present) { _contentEncoding = reader.ReadShortstr(); } - if (headers_present) { _headers = reader.ReadTable(); } - if (deliveryMode_present) { _deliveryMode = reader.ReadOctet(); } - if (priority_present) { _priority = reader.ReadOctet(); } - if (correlationId_present) { _correlationId = reader.ReadShortstr(); } - if (replyTo_present) { _replyTo = reader.ReadShortstr(); } - if (expiration_present) { _expiration = reader.ReadShortstr(); } - if (messageId_present) { _messageId = reader.ReadShortstr(); } - if (timestamp_present) { _timestamp = reader.ReadTimestamp(); } - if (type_present) { _type = reader.ReadShortstr(); } - if (userId_present) { _userId = reader.ReadShortstr(); } - if (appId_present) { _appId = reader.ReadShortstr(); } - if (clusterId_present) { _clusterId = reader.ReadShortstr(); } + int offset = WireFormatting.ReadBits(span, + out bool contentType_present, + out bool contentEncoding_present, + out bool headers_present, + out bool deliveryMode_present, + out bool priority_present, + out bool correlationId_present, + out bool replyTo_present, + out bool expiration_present, + out bool messageId_present, + out bool timestamp_present, + out bool type_present, + out bool userId_present, + out bool appId_present, + out bool clusterId_present); + if (contentType_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _contentType); } + if (contentEncoding_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _contentEncoding); } + if (headers_present) { offset += WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDirectory); _headers = tmpDirectory; } + if (deliveryMode_present) { _deliveryMode = span[offset++]; } + if (priority_present) { _priority = span[offset++]; } + if (correlationId_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _correlationId); } + if (replyTo_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _replyTo); } + if (expiration_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _expiration); } + if (messageId_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _messageId); } + if (timestamp_present) { offset += WireFormatting.ReadTimestamp(span.Slice(offset), out _timestamp); } + if (type_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _type); } + if (userId_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _userId); } + if (appId_present) { offset += WireFormatting.ReadShortstr(span.Slice(offset), out _appId); } + if (clusterId_present) { WireFormatting.ReadShortstr(span.Slice(offset), out _clusterId); } } - internal override void WritePropertiesTo(ref ContentHeaderPropertyWriter writer) + public override ushort ProtocolClassId => 60; + public override string ProtocolClassName => "basic"; + + internal override int WritePropertiesTo(Span span) { - writer.WritePresence(IsContentTypePresent()); - writer.WritePresence(IsContentEncodingPresent()); - writer.WritePresence(IsHeadersPresent()); - writer.WritePresence(IsDeliveryModePresent()); - writer.WritePresence(IsPriorityPresent()); - writer.WritePresence(IsCorrelationIdPresent()); - writer.WritePresence(IsReplyToPresent()); - writer.WritePresence(IsExpirationPresent()); - writer.WritePresence(IsMessageIdPresent()); - writer.WritePresence(IsTimestampPresent()); - writer.WritePresence(IsTypePresent()); - writer.WritePresence(IsUserIdPresent()); - writer.WritePresence(IsAppIdPresent()); - writer.WritePresence(IsClusterIdPresent()); - writer.FinishPresence(); - if (IsContentTypePresent()) { writer.WriteShortstr(_contentType); } - if (IsContentEncodingPresent()) { writer.WriteShortstr(_contentEncoding); } - if (IsHeadersPresent()) { writer.WriteTable(_headers); } - if (IsDeliveryModePresent()) { writer.WriteOctet(_deliveryMode); } - if (IsPriorityPresent()) { writer.WriteOctet(_priority); } - if (IsCorrelationIdPresent()) { writer.WriteShortstr(_correlationId); } - if (IsReplyToPresent()) { writer.WriteShortstr(_replyTo); } - if (IsExpirationPresent()) { writer.WriteShortstr(_expiration); } - if (IsMessageIdPresent()) { writer.WriteShortstr(_messageId); } - if (IsTimestampPresent()) { writer.WriteTimestamp(_timestamp); } - if (IsTypePresent()) { writer.WriteShortstr(_type); } - if (IsUserIdPresent()) { writer.WriteShortstr(_userId); } - if (IsAppIdPresent()) { writer.WriteShortstr(_appId); } - if (IsClusterIdPresent()) { writer.WriteShortstr(_clusterId); } + int offset = WireFormatting.WriteBits(span, + IsContentTypePresent(), IsContentEncodingPresent(), IsHeadersPresent(), IsDeliveryModePresent(), IsPriorityPresent(), + IsCorrelationIdPresent(), IsReplyToPresent(), IsExpirationPresent(), IsMessageIdPresent(), IsTimestampPresent(), + IsTypePresent(), IsUserIdPresent(), IsAppIdPresent(), IsClusterIdPresent()); + if (IsContentTypePresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _contentType); } + if (IsContentEncodingPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _contentEncoding); } + if (IsHeadersPresent()) { offset += WireFormatting.WriteTable(span.Slice(offset), _headers); } + if (IsDeliveryModePresent()) { span[offset++] = _deliveryMode; } + if (IsPriorityPresent()) { span[offset++] = _priority; } + if (IsCorrelationIdPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _correlationId); } + if (IsReplyToPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _replyTo); } + if (IsExpirationPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _expiration); } + if (IsMessageIdPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _messageId); } + if (IsTimestampPresent()) { offset += WireFormatting.WriteTimestamp(span.Slice(offset), _timestamp); } + if (IsTypePresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _type); } + if (IsUserIdPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _userId); } + if (IsAppIdPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _appId); } + if (IsClusterIdPresent()) { offset += WireFormatting.WriteShortstr(span.Slice(offset), _clusterId); } + return offset; } public override int GetRequiredPayloadBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicPublish.cs b/projects/RabbitMQ.Client/client/framing/BasicPublish.cs index 78e6d9e055..e0af575684 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicPublish.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicPublish.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -55,27 +57,24 @@ public BasicPublish(ushort Reserved1, string Exchange, string RoutingKey, bool M _immediate = Immediate; } + public BasicPublish(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + WireFormatting.ReadBits(span.Slice(offset), out _mandatory, out _immediate); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicPublish; public override string ProtocolMethodName => "basic.publish"; public override bool HasContent => true; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _mandatory = reader.ReadBit(); - _immediate = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); - writer.WriteBit(_mandatory); - writer.WriteBit(_immediate); - writer.EndBits(); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + return offset + WireFormatting.WriteBits(span.Slice(offset), _mandatory, _immediate); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicQos.cs b/projects/RabbitMQ.Client/client/framing/BasicQos.cs index cc5ce5bb1d..8827097bd2 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicQos.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicQos.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -50,23 +52,22 @@ public BasicQos(uint PrefetchSize, ushort PrefetchCount, bool Global) _global = Global; } + public BasicQos(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLong(span, out _prefetchSize); + offset += WireFormatting.ReadShort(span.Slice(offset), out _prefetchCount); + WireFormatting.ReadBits(span.Slice(offset), out _global); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicQos; public override string ProtocolMethodName => "basic.qos"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _prefetchSize = reader.ReadLong(); - _prefetchCount = reader.ReadShort(); - _global = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLong(_prefetchSize); - writer.WriteShort(_prefetchCount); - writer.WriteBit(_global); - writer.EndBits(); + int offset = WireFormatting.WriteLong(span, _prefetchSize); + offset += WireFormatting.WriteShort(span.Slice(offset), _prefetchCount); + return offset + WireFormatting.WriteBits(span.Slice(offset), _global); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicQosOk.cs b/projects/RabbitMQ.Client/client/framing/BasicQosOk.cs index 323ff99d49..eec5245931 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicQosOk.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicQosOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public BasicQosOk() public override string ProtocolMethodName => "basic.qos-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicRecover.cs b/projects/RabbitMQ.Client/client/framing/BasicRecover.cs index 2d53f93368..8c3fd6571a 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicRecover.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicRecover.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,19 +48,18 @@ public BasicRecover(bool Requeue) _requeue = Requeue; } + public BasicRecover(ReadOnlySpan span) + { + WireFormatting.ReadBits(span, out _requeue); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicRecover; public override string ProtocolMethodName => "basic.recover"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _requeue = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteBit(_requeue); - writer.EndBits(); + return WireFormatting.WriteBits(span, _requeue); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicRecoverAsync.cs b/projects/RabbitMQ.Client/client/framing/BasicRecoverAsync.cs index ba063b03a4..0f46194a2a 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicRecoverAsync.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicRecoverAsync.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,19 +48,18 @@ public BasicRecoverAsync(bool Requeue) _requeue = Requeue; } + public BasicRecoverAsync(ReadOnlySpan span) + { + WireFormatting.ReadBits(span, out _requeue); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicRecoverAsync; public override string ProtocolMethodName => "basic.recover-async"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _requeue = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteBit(_requeue); - writer.EndBits(); + return WireFormatting.WriteBits(span, _requeue); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicRecoverOk.cs b/projects/RabbitMQ.Client/client/framing/BasicRecoverOk.cs index b4e0dd8d3b..90fce6114c 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicRecoverOk.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicRecoverOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public BasicRecoverOk() public override string ProtocolMethodName => "basic.recover-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicReject.cs b/projects/RabbitMQ.Client/client/framing/BasicReject.cs index beb404504a..392af4967a 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicReject.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicReject.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -48,21 +50,20 @@ public BasicReject(ulong DeliveryTag, bool Requeue) _requeue = Requeue; } + public BasicReject(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLonglong(span, out _deliveryTag); + WireFormatting.ReadBits(span.Slice(offset), out _requeue); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicReject; public override string ProtocolMethodName => "basic.reject"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _deliveryTag = reader.ReadLonglong(); - _requeue = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLonglong(_deliveryTag); - writer.WriteBit(_requeue); - writer.EndBits(); + int offset = WireFormatting.WriteLonglong(span, _deliveryTag); + return offset + WireFormatting.WriteBits(span.Slice(offset), _requeue); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/BasicReturn.cs b/projects/RabbitMQ.Client/client/framing/BasicReturn.cs index 3fc125171f..ca1261ccad 100644 --- a/projects/RabbitMQ.Client/client/framing/BasicReturn.cs +++ b/projects/RabbitMQ.Client/client/framing/BasicReturn.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -53,24 +55,24 @@ public BasicReturn(ushort ReplyCode, string ReplyText, string Exchange, string R _routingKey = RoutingKey; } + public BasicReturn(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _replyCode); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _replyText); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.BasicReturn; public override string ProtocolMethodName => "basic.return"; public override bool HasContent => true; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _replyCode = reader.ReadShort(); - _replyText = reader.ReadShortstr(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_replyCode); - writer.WriteShortstr(_replyText); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); + int offset = WireFormatting.WriteShort(span, _replyCode); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _replyText); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + return offset + WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ChannelClose.cs b/projects/RabbitMQ.Client/client/framing/ChannelClose.cs index 74dab73704..d14c45833e 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelClose.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelClose.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -53,24 +55,24 @@ public ChannelClose(ushort ReplyCode, string ReplyText, ushort ClassId, ushort M _methodId = MethodId; } + public ChannelClose(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _replyCode); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _replyText); + offset += WireFormatting.ReadShort(span.Slice(offset), out _classId); + WireFormatting.ReadShort(span.Slice(offset), out _methodId); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ChannelClose; public override string ProtocolMethodName => "channel.close"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _replyCode = reader.ReadShort(); - _replyText = reader.ReadShortstr(); - _classId = reader.ReadShort(); - _methodId = reader.ReadShort(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_replyCode); - writer.WriteShortstr(_replyText); - writer.WriteShort(_classId); - writer.WriteShort(_methodId); + int offset = WireFormatting.WriteShort(span, _replyCode); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _replyText); + offset += WireFormatting.WriteShort(span.Slice(offset), _classId); + return offset + WireFormatting.WriteShort(span.Slice(offset), _methodId); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ChannelCloseOk.cs b/projects/RabbitMQ.Client/client/framing/ChannelCloseOk.cs index 243b0b4ebb..23a91391a0 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelCloseOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelCloseOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ChannelCloseOk() public override string ProtocolMethodName => "channel.close-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ChannelFlow.cs b/projects/RabbitMQ.Client/client/framing/ChannelFlow.cs index 4fc6da12c8..20ef906cac 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelFlow.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelFlow.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,19 +48,18 @@ public ChannelFlow(bool Active) _active = Active; } + public ChannelFlow(ReadOnlySpan span) + { + WireFormatting.ReadBits(span, out _active); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ChannelFlow; public override string ProtocolMethodName => "channel.flow"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _active = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteBit(_active); - writer.EndBits(); + return WireFormatting.WriteBits(span, _active); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ChannelFlowOk.cs b/projects/RabbitMQ.Client/client/framing/ChannelFlowOk.cs index 82325a9cd1..6e06a26ca5 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelFlowOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelFlowOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,25 +48,23 @@ public ChannelFlowOk(bool Active) _active = Active; } + public ChannelFlowOk(ReadOnlySpan span) + { + WireFormatting.ReadBits(span, out _active); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ChannelFlowOk; public override string ProtocolMethodName => "channel.flow-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _active = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteBit(_active); - writer.EndBits(); + return WireFormatting.WriteBits(span, _active); } public override int GetRequiredBufferSize() { - int bufferSize = 1; // bytes for bit fields - return bufferSize; + return 1; // bytes for bit fields } } } diff --git a/projects/RabbitMQ.Client/client/framing/ChannelOpen.cs b/projects/RabbitMQ.Client/client/framing/ChannelOpen.cs index c1b32ec897..b62673e4b4 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelOpen.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelOpen.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public ChannelOpen(string Reserved1) _reserved1 = Reserved1; } + public ChannelOpen(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _reserved1); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ChannelOpen; public override string ProtocolMethodName => "channel.open"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_reserved1); + return WireFormatting.WriteShortstr(span, _reserved1); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ChannelOpenOk.cs b/projects/RabbitMQ.Client/client/framing/ChannelOpenOk.cs index 2d3633f6da..2355e20ada 100644 --- a/projects/RabbitMQ.Client/client/framing/ChannelOpenOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ChannelOpenOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,18 +48,18 @@ public ChannelOpenOk(byte[] Reserved1) _reserved1 = Reserved1; } + public ChannelOpenOk(ReadOnlySpan span) + { + WireFormatting.ReadLongstr(span, out _reserved1); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ChannelOpenOk; public override string ProtocolMethodName => "channel.open-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadLongstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLongstr(_reserved1); + return WireFormatting.WriteLongstr(span, _reserved1); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConfirmSelect.cs b/projects/RabbitMQ.Client/client/framing/ConfirmSelect.cs index 2d0c5ae488..62d7d32c36 100644 --- a/projects/RabbitMQ.Client/client/framing/ConfirmSelect.cs +++ b/projects/RabbitMQ.Client/client/framing/ConfirmSelect.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,19 +48,18 @@ public ConfirmSelect(bool Nowait) _nowait = Nowait; } + public ConfirmSelect(ReadOnlySpan span) + { + WireFormatting.ReadBits(span, out _nowait); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConfirmSelect; public override string ProtocolMethodName => "confirm.select"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _nowait = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteBit(_nowait); - writer.EndBits(); + return WireFormatting.WriteBits(span, _nowait); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConfirmSelectOk.cs b/projects/RabbitMQ.Client/client/framing/ConfirmSelectOk.cs index ac87a1abad..78f68e6012 100644 --- a/projects/RabbitMQ.Client/client/framing/ConfirmSelectOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConfirmSelectOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ConfirmSelectOk() public override string ProtocolMethodName => "confirm.select-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionBlocked.cs b/projects/RabbitMQ.Client/client/framing/ConnectionBlocked.cs index 962146be40..8288bf7fd9 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionBlocked.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionBlocked.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public ConnectionBlocked(string Reason) _reason = Reason; } + public ConnectionBlocked(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _reason); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionBlocked; public override string ProtocolMethodName => "connection.blocked"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reason = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_reason); + return WireFormatting.WriteShortstr(span, _reason); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionClose.cs b/projects/RabbitMQ.Client/client/framing/ConnectionClose.cs index 32c390c9a3..dfe5f0c026 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionClose.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionClose.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -53,24 +55,24 @@ public ConnectionClose(ushort ReplyCode, string ReplyText, ushort ClassId, ushor _methodId = MethodId; } + public ConnectionClose(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _replyCode); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _replyText); + offset += WireFormatting.ReadShort(span.Slice(offset), out _classId); + WireFormatting.ReadShort(span.Slice(offset), out _methodId); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionClose; public override string ProtocolMethodName => "connection.close"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _replyCode = reader.ReadShort(); - _replyText = reader.ReadShortstr(); - _classId = reader.ReadShort(); - _methodId = reader.ReadShort(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_replyCode); - writer.WriteShortstr(_replyText); - writer.WriteShort(_classId); - writer.WriteShort(_methodId); + int offset = WireFormatting.WriteShort(span, _replyCode); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _replyText); + offset += WireFormatting.WriteShort(span.Slice(offset), _classId); + return offset + WireFormatting.WriteShort(span.Slice(offset), _methodId); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionCloseOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionCloseOk.cs index 338454a24b..333edc325c 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionCloseOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionCloseOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ConnectionCloseOk() public override string ProtocolMethodName => "connection.close-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionOpen.cs b/projects/RabbitMQ.Client/client/framing/ConnectionOpen.cs index 7b2e296696..46901aeb5a 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionOpen.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionOpen.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -51,23 +53,22 @@ public ConnectionOpen(string VirtualHost, string Reserved1, bool Reserved2) _reserved2 = Reserved2; } + public ConnectionOpen(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShortstr(span, out _virtualHost); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _reserved1); + WireFormatting.ReadBits(span.Slice(offset), out _reserved2); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionOpen; public override string ProtocolMethodName => "connection.open"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _virtualHost = reader.ReadShortstr(); - _reserved1 = reader.ReadShortstr(); - _reserved2 = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_virtualHost); - writer.WriteShortstr(_reserved1); - writer.WriteBit(_reserved2); - writer.EndBits(); + int offset = WireFormatting.WriteShortstr(span, _virtualHost); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _reserved1); + return offset + WireFormatting.WriteBits(span.Slice(offset), _reserved2); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionOpenOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionOpenOk.cs index 85e756894e..1b39bd2a15 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionOpenOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionOpenOk.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -47,18 +49,18 @@ public ConnectionOpenOk(string Reserved1) _reserved1 = Reserved1; } + public ConnectionOpenOk(ReadOnlySpan span) + { + WireFormatting.ReadShortstr(span, out _reserved1); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionOpenOk; public override string ProtocolMethodName => "connection.open-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_reserved1); + return WireFormatting.WriteShortstr(span, _reserved1); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionSecure.cs b/projects/RabbitMQ.Client/client/framing/ConnectionSecure.cs index d3e17489a7..8c20f4be27 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionSecure.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionSecure.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,18 +48,18 @@ public ConnectionSecure(byte[] Challenge) _challenge = Challenge; } + public ConnectionSecure(ReadOnlySpan span) + { + WireFormatting.ReadLongstr(span, out _challenge); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionSecure; public override string ProtocolMethodName => "connection.secure"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _challenge = reader.ReadLongstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLongstr(_challenge); + return WireFormatting.WriteLongstr(span, _challenge); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionSecureOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionSecureOk.cs index 4965d2e377..79cacd4eb9 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionSecureOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionSecureOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,18 +48,18 @@ public ConnectionSecureOk(byte[] Response) _response = Response; } + public ConnectionSecureOk(ReadOnlySpan span) + { + WireFormatting.ReadLongstr(span, out _response); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionSecureOk; public override string ProtocolMethodName => "connection.secure-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _response = reader.ReadLongstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLongstr(_response); + return WireFormatting.WriteLongstr(span, _response); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionStart.cs b/projects/RabbitMQ.Client/client/framing/ConnectionStart.cs index cc19799a21..cae6323b00 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionStart.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionStart.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using RabbitMQ.Client.client.framing; using RabbitMQ.Client.Impl; @@ -39,7 +40,7 @@ internal sealed class ConnectionStart : MethodBase { public byte _versionMajor; public byte _versionMinor; - public IDictionary _serverProperties; + public Dictionary _serverProperties; public byte[] _mechanisms; public byte[] _locales; @@ -47,7 +48,7 @@ public ConnectionStart() { } - public ConnectionStart(byte VersionMajor, byte VersionMinor, IDictionary ServerProperties, byte[] Mechanisms, byte[] Locales) + public ConnectionStart(byte VersionMajor, byte VersionMinor, Dictionary ServerProperties, byte[] Mechanisms, byte[] Locales) { _versionMajor = VersionMajor; _versionMinor = VersionMinor; @@ -56,32 +57,32 @@ public ConnectionStart(byte VersionMajor, byte VersionMinor, IDictionary span) + { + _versionMajor = span[0]; + _versionMinor = span[1]; + int offset = 2 + WireFormatting.ReadDictionary(span.Slice(2), out _serverProperties); + offset += WireFormatting.ReadLongstr(span.Slice(offset), out _mechanisms); + WireFormatting.ReadLongstr(span.Slice(offset), out _locales); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionStart; public override string ProtocolMethodName => "connection.start"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _versionMajor = reader.ReadOctet(); - _versionMinor = reader.ReadOctet(); - _serverProperties = reader.ReadTable(); - _mechanisms = reader.ReadLongstr(); - _locales = reader.ReadLongstr(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteOctet(_versionMajor); - writer.WriteOctet(_versionMinor); - writer.WriteTable(_serverProperties); - writer.WriteLongstr(_mechanisms); - writer.WriteLongstr(_locales); + span[0] = _versionMajor; + span[1] = _versionMinor; + int offset = 2 + WireFormatting.WriteTable(span.Slice(2), (IDictionary)_serverProperties); + offset += WireFormatting.WriteLongstr(span.Slice(offset), _mechanisms); + return offset + WireFormatting.WriteLongstr(span.Slice(offset), _locales); } public override int GetRequiredBufferSize() { int bufferSize = 1 + 1 + 4 + 4; // bytes for _versionMajor, _versionMinor, length of _mechanisms, length of _locales - bufferSize += WireFormatting.GetTableByteCount(_serverProperties); // _serverProperties in bytes + bufferSize += WireFormatting.GetTableByteCount((IDictionary)_serverProperties); // _serverProperties in bytes bufferSize += _mechanisms.Length; // _mechanisms in bytes bufferSize += _locales.Length; // _locales in bytes return bufferSize; diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionStartOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionStartOk.cs index 2fdd051ecd..fddda9e3f0 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionStartOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionStartOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -55,24 +56,25 @@ public ConnectionStartOk(IDictionary ClientProperties, string Me _locale = Locale; } + public ConnectionStartOk(ReadOnlySpan span) + { + int offset = WireFormatting.ReadDictionary(span, out var tmpDictionary); + _clientProperties = tmpDictionary; + offset += WireFormatting.ReadShortstr(span, out _mechanism); + offset += WireFormatting.ReadLongstr(span, out _response); + WireFormatting.ReadShortstr(span.Slice(offset), out _locale); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionStartOk; public override string ProtocolMethodName => "connection.start-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _clientProperties = reader.ReadTable(); - _mechanism = reader.ReadShortstr(); - _response = reader.ReadLongstr(); - _locale = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteTable(_clientProperties); - writer.WriteShortstr(_mechanism); - writer.WriteLongstr(_response); - writer.WriteShortstr(_locale); + int offset = WireFormatting.WriteTable(span, _clientProperties); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _mechanism); + offset += WireFormatting.WriteLongstr(span.Slice(offset), _response); + return offset + WireFormatting.WriteShortstr(span.Slice(offset), _locale); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionTune.cs b/projects/RabbitMQ.Client/client/framing/ConnectionTune.cs index 2bf9e19579..f0f840a01c 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionTune.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionTune.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -50,22 +52,22 @@ public ConnectionTune(ushort ChannelMax, uint FrameMax, ushort Heartbeat) _heartbeat = Heartbeat; } + public ConnectionTune(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _channelMax); + offset += WireFormatting.ReadLong(span.Slice(offset), out _frameMax); + WireFormatting.ReadShort(span.Slice(offset), out _heartbeat); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionTune; public override string ProtocolMethodName => "connection.tune"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _channelMax = reader.ReadShort(); - _frameMax = reader.ReadLong(); - _heartbeat = reader.ReadShort(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_channelMax); - writer.WriteLong(_frameMax); - writer.WriteShort(_heartbeat); + int offset = WireFormatting.WriteShort(span, _channelMax); + offset += WireFormatting.WriteLong(span.Slice(offset), _frameMax); + return offset + WireFormatting.WriteShort(span.Slice(offset), _heartbeat); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionTuneOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionTuneOk.cs index 4afc59ba2a..42736b205d 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionTuneOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionTuneOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -50,22 +52,22 @@ public ConnectionTuneOk(ushort ChannelMax, uint FrameMax, ushort Heartbeat) _heartbeat = Heartbeat; } + public ConnectionTuneOk(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _channelMax); + offset += WireFormatting.ReadLong(span.Slice(offset), out _frameMax); + WireFormatting.ReadShort(span.Slice(offset), out _heartbeat); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionTuneOk; public override string ProtocolMethodName => "connection.tune-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _channelMax = reader.ReadShort(); - _frameMax = reader.ReadLong(); - _heartbeat = reader.ReadShort(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_channelMax); - writer.WriteLong(_frameMax); - writer.WriteShort(_heartbeat); + int offset = WireFormatting.WriteShort(span, _channelMax); + offset += WireFormatting.WriteLong(span.Slice(offset), _frameMax); + return offset + WireFormatting.WriteShort(span.Slice(offset), _heartbeat); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionUnblocked.cs b/projects/RabbitMQ.Client/client/framing/ConnectionUnblocked.cs index 0c4555b624..dde99fc9a5 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionUnblocked.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionUnblocked.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ConnectionUnblocked() public override string ProtocolMethodName => "connection.unblocked"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecret.cs b/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecret.cs index d008c848ed..ae778980d5 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecret.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecret.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -49,20 +51,20 @@ public ConnectionUpdateSecret(byte[] NewSecret, string Reason) _reason = Reason; } + public ConnectionUpdateSecret(ReadOnlySpan span) + { + int offset = WireFormatting.ReadLongstr(span, out _newSecret); + WireFormatting.ReadShortstr(span.Slice(offset), out _reason); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ConnectionUpdateSecret; public override string ProtocolMethodName => "connection.update-secret"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _newSecret = reader.ReadLongstr(); - _reason = reader.ReadShortstr(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLongstr(_newSecret); - writer.WriteShortstr(_reason); + int offset = WireFormatting.WriteLongstr(span, _newSecret); + return offset + WireFormatting.WriteShortstr(span.Slice(offset), _reason); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecretOk.cs b/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecretOk.cs index 9bac494a01..3e377c206f 100644 --- a/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecretOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ConnectionUpdateSecretOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ConnectionUpdateSecretOk() public override string ProtocolMethodName => "connection.update-secret-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeBind.cs b/projects/RabbitMQ.Client/client/framing/ExchangeBind.cs index 4e79f91844..6f75cd2ff0 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeBind.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeBind.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -59,29 +60,29 @@ public ExchangeBind(ushort Reserved1, string Destination, string Source, string _arguments = Arguments; } + public ExchangeBind(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _destination); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _source); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + offset += WireFormatting.ReadBits(span.Slice(offset), out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ExchangeBind; public override string ProtocolMethodName => "exchange.bind"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _destination = reader.ReadShortstr(); - _source = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_destination); - writer.WriteShortstr(_source); - writer.WriteShortstr(_routingKey); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _destination); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _source); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + offset += WireFormatting.WriteBits(span.Slice(offset), _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeBindOk.cs b/projects/RabbitMQ.Client/client/framing/ExchangeBindOk.cs index 565a5c4744..04b7eacbc5 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeBindOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeBindOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ExchangeBindOk() public override string ProtocolMethodName => "exchange.bind-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeDeclare.cs b/projects/RabbitMQ.Client/client/framing/ExchangeDeclare.cs index fe7707f53d..75344c2621 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeDeclare.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeDeclare.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -65,35 +66,27 @@ public ExchangeDeclare(ushort Reserved1, string Exchange, string Type, bool Pass _arguments = Arguments; } + public ExchangeDeclare(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _type); + offset += WireFormatting.ReadBits(span.Slice(offset), out _passive, out _durable, out _autoDelete, out _internal, out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ExchangeDeclare; public override string ProtocolMethodName => "exchange.declare"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _exchange = reader.ReadShortstr(); - _type = reader.ReadShortstr(); - _passive = reader.ReadBit(); - _durable = reader.ReadBit(); - _autoDelete = reader.ReadBit(); - _internal = reader.ReadBit(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_type); - writer.WriteBit(_passive); - writer.WriteBit(_durable); - writer.WriteBit(_autoDelete); - writer.WriteBit(_internal); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _type); + offset += WireFormatting.WriteBits(span.Slice(offset), _passive, _durable, _autoDelete, _internal, _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeDeclareOk.cs b/projects/RabbitMQ.Client/client/framing/ExchangeDeclareOk.cs index 880e87a92b..03921f2220 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeDeclareOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeDeclareOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ExchangeDeclareOk() public override string ProtocolMethodName => "exchange.declare-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeDelete.cs b/projects/RabbitMQ.Client/client/framing/ExchangeDelete.cs index c3a469f385..a0ae94bf4a 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeDelete.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeDelete.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -53,25 +55,22 @@ public ExchangeDelete(ushort Reserved1, string Exchange, bool IfUnused, bool Now _nowait = Nowait; } + public ExchangeDelete(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + WireFormatting.ReadBits(span.Slice(offset), out _ifUnused, out _nowait); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ExchangeDelete; public override string ProtocolMethodName => "exchange.delete"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _exchange = reader.ReadShortstr(); - _ifUnused = reader.ReadBit(); - _nowait = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_exchange); - writer.WriteBit(_ifUnused); - writer.WriteBit(_nowait); - writer.EndBits(); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + return offset + WireFormatting.WriteBits(span.Slice(offset), _ifUnused, _nowait); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeDeleteOk.cs b/projects/RabbitMQ.Client/client/framing/ExchangeDeleteOk.cs index 0a8d3d8845..106d4f2d82 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeDeleteOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeDeleteOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ExchangeDeleteOk() public override string ProtocolMethodName => "exchange.delete-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeUnbind.cs b/projects/RabbitMQ.Client/client/framing/ExchangeUnbind.cs index d19b573035..e86f72b582 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeUnbind.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeUnbind.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -59,29 +60,29 @@ public ExchangeUnbind(ushort Reserved1, string Destination, string Source, strin _arguments = Arguments; } + public ExchangeUnbind(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _destination); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _source); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + offset += WireFormatting.ReadBits(span.Slice(offset), out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.ExchangeUnbind; public override string ProtocolMethodName => "exchange.unbind"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _destination = reader.ReadShortstr(); - _source = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_destination); - writer.WriteShortstr(_source); - writer.WriteShortstr(_routingKey); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _destination); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _source); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + offset += WireFormatting.WriteBits(span.Slice(offset), _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/ExchangeUnbindOk.cs b/projects/RabbitMQ.Client/client/framing/ExchangeUnbindOk.cs index 513c28604b..b195002955 100644 --- a/projects/RabbitMQ.Client/client/framing/ExchangeUnbindOk.cs +++ b/projects/RabbitMQ.Client/client/framing/ExchangeUnbindOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public ExchangeUnbindOk() public override string ProtocolMethodName => "exchange.unbind-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/Protocol.cs b/projects/RabbitMQ.Client/client/framing/Protocol.cs index f9304b6158..f61c72d100 100644 --- a/projects/RabbitMQ.Client/client/framing/Protocol.cs +++ b/projects/RabbitMQ.Client/client/framing/Protocol.cs @@ -55,72 +55,69 @@ internal sealed class Protocol : ProtocolBase internal override Client.Impl.MethodBase DecodeMethodFrom(ReadOnlySpan span) { var commandId = (ProtocolCommandId)Util.NetworkOrderDeserializer.ReadUInt32(span); - Client.Impl.MethodBase result = DecodeMethodFrom(commandId); - Client.Impl.MethodArgumentReader reader = new Client.Impl.MethodArgumentReader(span.Slice(4)); - result.ReadArgumentsFrom(ref reader); - return result; + return DecodeMethodFrom(commandId, span.Slice(4)); } - internal Client.Impl.MethodBase DecodeMethodFrom(ProtocolCommandId commandId) + private static Client.Impl.MethodBase DecodeMethodFrom(ProtocolCommandId commandId, ReadOnlySpan span) { switch (commandId) { - case ProtocolCommandId.ConnectionStart: return new ConnectionStart(); - case ProtocolCommandId.ConnectionStartOk: return new ConnectionStartOk(); - case ProtocolCommandId.ConnectionSecure: return new ConnectionSecure(); - case ProtocolCommandId.ConnectionSecureOk: return new ConnectionSecureOk(); - case ProtocolCommandId.ConnectionTune: return new ConnectionTune(); - case ProtocolCommandId.ConnectionTuneOk: return new ConnectionTuneOk(); - case ProtocolCommandId.ConnectionOpen: return new ConnectionOpen(); - case ProtocolCommandId.ConnectionOpenOk: return new ConnectionOpenOk(); - case ProtocolCommandId.ConnectionClose: return new ConnectionClose(); + case ProtocolCommandId.ConnectionStart: return new ConnectionStart(span); + case ProtocolCommandId.ConnectionStartOk: return new ConnectionStartOk(span); + case ProtocolCommandId.ConnectionSecure: return new ConnectionSecure(span); + case ProtocolCommandId.ConnectionSecureOk: return new ConnectionSecureOk(span); + case ProtocolCommandId.ConnectionTune: return new ConnectionTune(span); + case ProtocolCommandId.ConnectionTuneOk: return new ConnectionTuneOk(span); + case ProtocolCommandId.ConnectionOpen: return new ConnectionOpen(span); + case ProtocolCommandId.ConnectionOpenOk: return new ConnectionOpenOk(span); + case ProtocolCommandId.ConnectionClose: return new ConnectionClose(span); case ProtocolCommandId.ConnectionCloseOk: return new ConnectionCloseOk(); - case ProtocolCommandId.ConnectionBlocked: return new ConnectionBlocked(); + case ProtocolCommandId.ConnectionBlocked: return new ConnectionBlocked(span); case ProtocolCommandId.ConnectionUnblocked: return new ConnectionUnblocked(); - case ProtocolCommandId.ConnectionUpdateSecret: return new ConnectionUpdateSecret(); + case ProtocolCommandId.ConnectionUpdateSecret: return new ConnectionUpdateSecret(span); case ProtocolCommandId.ConnectionUpdateSecretOk: return new ConnectionUpdateSecretOk(); - case ProtocolCommandId.ChannelOpen: return new ChannelOpen(); - case ProtocolCommandId.ChannelOpenOk: return new ChannelOpenOk(); - case ProtocolCommandId.ChannelFlow: return new ChannelFlow(); - case ProtocolCommandId.ChannelFlowOk: return new ChannelFlowOk(); - case ProtocolCommandId.ChannelClose: return new ChannelClose(); + case ProtocolCommandId.ChannelOpen: return new ChannelOpen(span); + case ProtocolCommandId.ChannelOpenOk: return new ChannelOpenOk(span); + case ProtocolCommandId.ChannelFlow: return new ChannelFlow(span); + case ProtocolCommandId.ChannelFlowOk: return new ChannelFlowOk(span); + case ProtocolCommandId.ChannelClose: return new ChannelClose(span); case ProtocolCommandId.ChannelCloseOk: return new ChannelCloseOk(); - case ProtocolCommandId.ExchangeDeclare: return new ExchangeDeclare(); + case ProtocolCommandId.ExchangeDeclare: return new ExchangeDeclare(span); case ProtocolCommandId.ExchangeDeclareOk: return new ExchangeDeclareOk(); - case ProtocolCommandId.ExchangeDelete: return new ExchangeDelete(); + case ProtocolCommandId.ExchangeDelete: return new ExchangeDelete(span); case ProtocolCommandId.ExchangeDeleteOk: return new ExchangeDeleteOk(); - case ProtocolCommandId.ExchangeBind: return new ExchangeBind(); + case ProtocolCommandId.ExchangeBind: return new ExchangeBind(span); case ProtocolCommandId.ExchangeBindOk: return new ExchangeBindOk(); - case ProtocolCommandId.ExchangeUnbind: return new ExchangeUnbind(); + case ProtocolCommandId.ExchangeUnbind: return new ExchangeUnbind(span); case ProtocolCommandId.ExchangeUnbindOk: return new ExchangeUnbindOk(); - case ProtocolCommandId.QueueDeclare: return new QueueDeclare(); - case ProtocolCommandId.QueueDeclareOk: return new Impl.QueueDeclareOk(); - case ProtocolCommandId.QueueBind: return new QueueBind(); + case ProtocolCommandId.QueueDeclare: return new QueueDeclare(span); + case ProtocolCommandId.QueueDeclareOk: return new Impl.QueueDeclareOk(span); + case ProtocolCommandId.QueueBind: return new QueueBind(span); case ProtocolCommandId.QueueBindOk: return new QueueBindOk(); - case ProtocolCommandId.QueueUnbind: return new QueueUnbind(); + case ProtocolCommandId.QueueUnbind: return new QueueUnbind(span); case ProtocolCommandId.QueueUnbindOk: return new QueueUnbindOk(); - case ProtocolCommandId.QueuePurge: return new QueuePurge(); - case ProtocolCommandId.QueuePurgeOk: return new QueuePurgeOk(); - case ProtocolCommandId.QueueDelete: return new QueueDelete(); - case ProtocolCommandId.QueueDeleteOk: return new QueueDeleteOk(); - case ProtocolCommandId.BasicQos: return new BasicQos(); + case ProtocolCommandId.QueuePurge: return new QueuePurge(span); + case ProtocolCommandId.QueuePurgeOk: return new QueuePurgeOk(span); + case ProtocolCommandId.QueueDelete: return new QueueDelete(span); + case ProtocolCommandId.QueueDeleteOk: return new QueueDeleteOk(span); + case ProtocolCommandId.BasicQos: return new BasicQos(span); case ProtocolCommandId.BasicQosOk: return new BasicQosOk(); - case ProtocolCommandId.BasicConsume: return new BasicConsume(); - case ProtocolCommandId.BasicConsumeOk: return new BasicConsumeOk(); - case ProtocolCommandId.BasicCancel: return new BasicCancel(); - case ProtocolCommandId.BasicCancelOk: return new BasicCancelOk(); - case ProtocolCommandId.BasicPublish: return new BasicPublish(); - case ProtocolCommandId.BasicReturn: return new BasicReturn(); - case ProtocolCommandId.BasicDeliver: return new BasicDeliver(); - case ProtocolCommandId.BasicGet: return new BasicGet(); - case ProtocolCommandId.BasicGetOk: return new BasicGetOk(); - case ProtocolCommandId.BasicGetEmpty: return new BasicGetEmpty(); - case ProtocolCommandId.BasicAck: return new BasicAck(); - case ProtocolCommandId.BasicReject: return new BasicReject(); - case ProtocolCommandId.BasicRecoverAsync: return new BasicRecoverAsync(); - case ProtocolCommandId.BasicRecover: return new BasicRecover(); + case ProtocolCommandId.BasicConsume: return new BasicConsume(span); + case ProtocolCommandId.BasicConsumeOk: return new BasicConsumeOk(span); + case ProtocolCommandId.BasicCancel: return new BasicCancel(span); + case ProtocolCommandId.BasicCancelOk: return new BasicCancelOk(span); + case ProtocolCommandId.BasicPublish: return new BasicPublish(span); + case ProtocolCommandId.BasicReturn: return new BasicReturn(span); + case ProtocolCommandId.BasicDeliver: return new BasicDeliver(span); + case ProtocolCommandId.BasicGet: return new BasicGet(span); + case ProtocolCommandId.BasicGetOk: return new BasicGetOk(span); + case ProtocolCommandId.BasicGetEmpty: return new BasicGetEmpty(span); + case ProtocolCommandId.BasicAck: return new BasicAck(span); + case ProtocolCommandId.BasicReject: return new BasicReject(span); + case ProtocolCommandId.BasicRecoverAsync: return new BasicRecoverAsync(span); + case ProtocolCommandId.BasicRecover: return new BasicRecover(span); case ProtocolCommandId.BasicRecoverOk: return new BasicRecoverOk(); - case ProtocolCommandId.BasicNack: return new BasicNack(); + case ProtocolCommandId.BasicNack: return new BasicNack(span); case ProtocolCommandId.TxSelect: return new TxSelect(); case ProtocolCommandId.TxSelectOk: return new TxSelectOk(); case ProtocolCommandId.TxCommit: return new TxCommit(); @@ -130,17 +127,15 @@ internal Client.Impl.MethodBase DecodeMethodFrom(ProtocolCommandId commandId) case ProtocolCommandId.ConfirmSelect: return new ConfirmSelect(); case ProtocolCommandId.ConfirmSelectOk: return new ConfirmSelectOk(); default: - //TODO Check if valid throw new Exceptions.UnknownClassOrMethodException((ushort)((uint)commandId >> 16), (ushort)((uint)commandId & 0xFFFF)); } } - - internal override Client.Impl.ContentHeaderBase DecodeContentHeaderFrom(ushort classId) + internal override Client.Impl.ContentHeaderBase DecodeContentHeaderFrom(ushort classId, ReadOnlySpan span) { switch (classId) { - case 60: return new BasicProperties(); + case 60: return new BasicProperties(span); default: throw new Exceptions.UnknownClassOrMethodException(classId, 0); } } diff --git a/projects/RabbitMQ.Client/client/framing/QueueBind.cs b/projects/RabbitMQ.Client/client/framing/QueueBind.cs index c7ae275a38..05c7021b7c 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueBind.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueBind.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -59,29 +60,29 @@ public QueueBind(ushort Reserved1, string Queue, string Exchange, string Routing _arguments = Arguments; } + public QueueBind(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + offset += WireFormatting.ReadBits(span.Slice(offset), out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueBind; public override string ProtocolMethodName => "queue.bind"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + offset += WireFormatting.WriteBits(span.Slice(offset), _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueBindOk.cs b/projects/RabbitMQ.Client/client/framing/QueueBindOk.cs index 74a2fbbb53..660462c2b8 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueBindOk.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueBindOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public QueueBindOk() public override string ProtocolMethodName => "queue.bind-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueDeclare.cs b/projects/RabbitMQ.Client/client/framing/QueueDeclare.cs index e0b9d44001..d3540aa6e5 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueDeclare.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueDeclare.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -63,33 +64,25 @@ public QueueDeclare(ushort Reserved1, string Queue, bool Passive, bool Durable, _arguments = Arguments; } + public QueueDeclare(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + offset += WireFormatting.ReadBits(span.Slice(offset), out _passive, out _durable, out _exclusive, out _autoDelete, out _nowait); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueDeclare; public override string ProtocolMethodName => "queue.declare"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _passive = reader.ReadBit(); - _durable = reader.ReadBit(); - _exclusive = reader.ReadBit(); - _autoDelete = reader.ReadBit(); - _nowait = reader.ReadBit(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteBit(_passive); - writer.WriteBit(_durable); - writer.WriteBit(_exclusive); - writer.WriteBit(_autoDelete); - writer.WriteBit(_nowait); - writer.EndBits(); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + offset += WireFormatting.WriteBits(span.Slice(offset), _passive, _durable, _exclusive, _autoDelete, _nowait); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueDeclareOk.cs b/projects/RabbitMQ.Client/client/framing/QueueDeclareOk.cs index b8df61c616..3f8ecf97c8 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueDeclareOk.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueDeclareOk.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -51,22 +53,22 @@ public QueueDeclareOk(string Queue, uint MessageCount, uint ConsumerCount) _consumerCount = ConsumerCount; } + public QueueDeclareOk(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShortstr(span, out _queue); + offset += WireFormatting.ReadLong(span.Slice(offset), out _messageCount); + WireFormatting.ReadLong(span.Slice(offset), out _consumerCount); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueDeclareOk; public override string ProtocolMethodName => "queue.declare-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _queue = reader.ReadShortstr(); - _messageCount = reader.ReadLong(); - _consumerCount = reader.ReadLong(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShortstr(_queue); - writer.WriteLong(_messageCount); - writer.WriteLong(_consumerCount); + int offset = WireFormatting.WriteShortstr(span, _queue); + offset += WireFormatting.WriteLong(span.Slice(offset), _messageCount); + return offset + WireFormatting.WriteLong(span.Slice(offset), _consumerCount); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueDelete.cs b/projects/RabbitMQ.Client/client/framing/QueueDelete.cs index 5454c492d2..b0e4b83f26 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueDelete.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueDelete.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -55,27 +57,22 @@ public QueueDelete(ushort Reserved1, string Queue, bool IfUnused, bool IfEmpty, _nowait = Nowait; } + public QueueDelete(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + WireFormatting.ReadBits(span.Slice(offset), out _ifUnused, out _ifEmpty, out _nowait); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueDelete; public override string ProtocolMethodName => "queue.delete"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _ifUnused = reader.ReadBit(); - _ifEmpty = reader.ReadBit(); - _nowait = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteBit(_ifUnused); - writer.WriteBit(_ifEmpty); - writer.WriteBit(_nowait); - writer.EndBits(); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + return offset + WireFormatting.WriteBits(span.Slice(offset), _ifUnused, _ifEmpty, _nowait); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueDeleteOk.cs b/projects/RabbitMQ.Client/client/framing/QueueDeleteOk.cs index facffe6c55..00ee2d4b3f 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueDeleteOk.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueDeleteOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,18 +48,18 @@ public QueueDeleteOk(uint MessageCount) _messageCount = MessageCount; } + public QueueDeleteOk(ReadOnlySpan span) + { + WireFormatting.ReadLong(span, out _messageCount); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueDeleteOk; public override string ProtocolMethodName => "queue.delete-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _messageCount = reader.ReadLong(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLong(_messageCount); + return WireFormatting.WriteLong(span, _messageCount); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueuePurge.cs b/projects/RabbitMQ.Client/client/framing/QueuePurge.cs index 4c16f36660..29944e63fc 100644 --- a/projects/RabbitMQ.Client/client/framing/QueuePurge.cs +++ b/projects/RabbitMQ.Client/client/framing/QueuePurge.cs @@ -29,8 +29,10 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Text; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -51,23 +53,22 @@ public QueuePurge(ushort Reserved1, string Queue, bool Nowait) _nowait = Nowait; } + public QueuePurge(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + WireFormatting.ReadBits(span.Slice(offset), out _nowait); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueuePurge; public override string ProtocolMethodName => "queue.purge"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _nowait = reader.ReadBit(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteBit(_nowait); - writer.EndBits(); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + return offset + WireFormatting.WriteBits(span.Slice(offset), _nowait); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueuePurgeOk.cs b/projects/RabbitMQ.Client/client/framing/QueuePurgeOk.cs index 1c7ae606aa..3c7aeec20a 100644 --- a/projects/RabbitMQ.Client/client/framing/QueuePurgeOk.cs +++ b/projects/RabbitMQ.Client/client/framing/QueuePurgeOk.cs @@ -29,7 +29,9 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; +using RabbitMQ.Client.Impl; namespace RabbitMQ.Client.Framing.Impl { @@ -46,18 +48,18 @@ public QueuePurgeOk(uint MessageCount) _messageCount = MessageCount; } + public QueuePurgeOk(ReadOnlySpan span) + { + WireFormatting.ReadLong(span, out _messageCount); + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueuePurgeOk; public override string ProtocolMethodName => "queue.purge-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - _messageCount = reader.ReadLong(); - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteLong(_messageCount); + return WireFormatting.WriteLong(span, _messageCount); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueUnbind.cs b/projects/RabbitMQ.Client/client/framing/QueueUnbind.cs index 22e5bb25ca..1717389c91 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueUnbind.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueUnbind.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Text; using RabbitMQ.Client.client.framing; @@ -57,26 +58,27 @@ public QueueUnbind(ushort Reserved1, string Queue, string Exchange, string Routi _arguments = Arguments; } + public QueueUnbind(ReadOnlySpan span) + { + int offset = WireFormatting.ReadShort(span, out _reserved1); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _queue); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _exchange); + offset += WireFormatting.ReadShortstr(span.Slice(offset), out _routingKey); + WireFormatting.ReadDictionary(span.Slice(offset), out var tmpDictionary); + _arguments = tmpDictionary; + } + public override ProtocolCommandId ProtocolCommandId => ProtocolCommandId.QueueUnbind; public override string ProtocolMethodName => "queue.unbind"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref MethodArgumentReader reader) - { - _reserved1 = reader.ReadShort(); - _queue = reader.ReadShortstr(); - _exchange = reader.ReadShortstr(); - _routingKey = reader.ReadShortstr(); - _arguments = reader.ReadTable(); - } - - public override void WriteArgumentsTo(ref MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { - writer.WriteShort(_reserved1); - writer.WriteShortstr(_queue); - writer.WriteShortstr(_exchange); - writer.WriteShortstr(_routingKey); - writer.WriteTable(_arguments); + int offset = WireFormatting.WriteShort(span, _reserved1); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _queue); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _exchange); + offset += WireFormatting.WriteShortstr(span.Slice(offset), _routingKey); + return offset + WireFormatting.WriteTable(span.Slice(offset), _arguments); } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/QueueUnbindOk.cs b/projects/RabbitMQ.Client/client/framing/QueueUnbindOk.cs index e1cfa06556..026a5b90ce 100644 --- a/projects/RabbitMQ.Client/client/framing/QueueUnbindOk.cs +++ b/projects/RabbitMQ.Client/client/framing/QueueUnbindOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public QueueUnbindOk() public override string ProtocolMethodName => "queue.unbind-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxCommit.cs b/projects/RabbitMQ.Client/client/framing/TxCommit.cs index 645ebcf2c2..fdd8d67f4f 100644 --- a/projects/RabbitMQ.Client/client/framing/TxCommit.cs +++ b/projects/RabbitMQ.Client/client/framing/TxCommit.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxCommit() public override string ProtocolMethodName => "tx.commit"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxCommitOk.cs b/projects/RabbitMQ.Client/client/framing/TxCommitOk.cs index e70006639b..68c548734c 100644 --- a/projects/RabbitMQ.Client/client/framing/TxCommitOk.cs +++ b/projects/RabbitMQ.Client/client/framing/TxCommitOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxCommitOk() public override string ProtocolMethodName => "tx.commit-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxRollback.cs b/projects/RabbitMQ.Client/client/framing/TxRollback.cs index e136568ece..a713c67dac 100644 --- a/projects/RabbitMQ.Client/client/framing/TxRollback.cs +++ b/projects/RabbitMQ.Client/client/framing/TxRollback.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxRollback() public override string ProtocolMethodName => "tx.rollback"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxRollbackOk.cs b/projects/RabbitMQ.Client/client/framing/TxRollbackOk.cs index 21f8212ead..c447a6c0f2 100644 --- a/projects/RabbitMQ.Client/client/framing/TxRollbackOk.cs +++ b/projects/RabbitMQ.Client/client/framing/TxRollbackOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxRollbackOk() public override string ProtocolMethodName => "tx.rollback-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxSelect.cs b/projects/RabbitMQ.Client/client/framing/TxSelect.cs index 5e76884630..8d518d400a 100644 --- a/projects/RabbitMQ.Client/client/framing/TxSelect.cs +++ b/projects/RabbitMQ.Client/client/framing/TxSelect.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxSelect() public override string ProtocolMethodName => "tx.select"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/framing/TxSelectOk.cs b/projects/RabbitMQ.Client/client/framing/TxSelectOk.cs index 0b3d9fb704..01fd55dc96 100644 --- a/projects/RabbitMQ.Client/client/framing/TxSelectOk.cs +++ b/projects/RabbitMQ.Client/client/framing/TxSelectOk.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Framing.Impl @@ -43,12 +44,9 @@ public TxSelectOk() public override string ProtocolMethodName => "tx.select-ok"; public override bool HasContent => false; - public override void ReadArgumentsFrom(ref Client.Impl.MethodArgumentReader reader) - { - } - - public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer) + public override int WriteArgumentsTo(Span span) { + return 0; } public override int GetRequiredBufferSize() diff --git a/projects/RabbitMQ.Client/client/impl/CommandAssembler.cs b/projects/RabbitMQ.Client/client/impl/CommandAssembler.cs index 9c1943906b..2a728fe9fd 100644 --- a/projects/RabbitMQ.Client/client/impl/CommandAssembler.cs +++ b/projects/RabbitMQ.Client/client/impl/CommandAssembler.cs @@ -114,8 +114,7 @@ private void ParseHeaderFrame(in InboundFrame frame) } ReadOnlySpan span = frame.Payload.Span; - _header = _protocol.DecodeContentHeaderFrom(NetworkOrderDeserializer.ReadUInt16(span)); - _header.ReadFrom(span.Slice(12)); + _header = _protocol.DecodeContentHeaderFrom(NetworkOrderDeserializer.ReadUInt16(span), span.Slice(12)); ulong totalBodyBytes = NetworkOrderDeserializer.ReadUInt64(span.Slice(4)); if (totalBodyBytes > MaxArrayOfBytesSize) { diff --git a/projects/RabbitMQ.Client/client/impl/ContentHeaderBase.cs b/projects/RabbitMQ.Client/client/impl/ContentHeaderBase.cs index b9c2592693..ca9213825d 100644 --- a/projects/RabbitMQ.Client/client/impl/ContentHeaderBase.cs +++ b/projects/RabbitMQ.Client/client/impl/ContentHeaderBase.cs @@ -50,17 +50,7 @@ public virtual object Clone() throw new NotImplementedException(); } - /// - /// Fill this instance from the given byte buffer stream. - /// - internal void ReadFrom(ReadOnlySpan span) - { - ContentHeaderPropertyReader reader = new ContentHeaderPropertyReader(span); - ReadPropertiesFrom(ref reader); - } - - internal abstract void ReadPropertiesFrom(ref ContentHeaderPropertyReader reader); - internal abstract void WritePropertiesTo(ref ContentHeaderPropertyWriter writer); + internal abstract int WritePropertiesTo(Span span); public abstract int GetRequiredPayloadBufferSize(); } diff --git a/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyReader.cs b/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyReader.cs deleted file mode 100644 index 8a0ddcc403..0000000000 --- a/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyReader.cs +++ /dev/null @@ -1,152 +0,0 @@ -// This source code is dual-licensed under the Apache License, version -// 2.0, and the Mozilla Public License, version 2.0. -// -// The APL v2.0: -// -//--------------------------------------------------------------------------- -// Copyright (c) 2007-2020 VMware, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//--------------------------------------------------------------------------- -// -// The MPL v2.0: -// -//--------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// -// Copyright (c) 2007-2020 VMware, Inc. All rights reserved. -//--------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using RabbitMQ.Client.Exceptions; -using RabbitMQ.Util; - -namespace RabbitMQ.Client.Impl -{ - internal ref struct ContentHeaderPropertyReader - { - private const int StartBitMask = 0b1000_0000_0000_0000; - private const int EndBitMask = 0b0000_0000_0000_0001; - - private readonly ReadOnlySpan _span; - private int _offset; - private int _bitMask; - private int _bits; - - private ReadOnlySpan Span => _span.Slice(_offset); - - public ContentHeaderPropertyReader(ReadOnlySpan span) - { - _span = span; - _offset = 0; - _bitMask = EndBitMask; // force a flag read - _bits = 1; // just the continuation bit - } - - private bool ContinuationBitSet => (_bits & EndBitMask) != 0; - - public void FinishPresence() - { - if (ContinuationBitSet) - { - throw new MalformedFrameException("Unexpected continuation flag word"); - } - } - - public bool ReadBit() - { - return ReadPresence(); - } - - private void ReadBits() - { - if (!ContinuationBitSet) - { - throw new MalformedFrameException("Attempted to read flag word when none advertised"); - } - _bits = NetworkOrderDeserializer.ReadUInt16(Span); - _offset += 2; - _bitMask = StartBitMask; - } - - public uint ReadLong() - { - uint result = NetworkOrderDeserializer.ReadUInt32(Span); - _offset += 4; - return result; - } - - public ulong ReadLonglong() - { - ulong result = NetworkOrderDeserializer.ReadUInt64(Span); - _offset += 8; - return result; - } - - public byte[] ReadLongstr() - { - byte[] result = WireFormatting.ReadLongstr(Span); - _offset += 4 + result.Length; - return result; - } - - public byte ReadOctet() - { - return _span[_offset++]; - } - - public bool ReadPresence() - { - if (_bitMask == EndBitMask) - { - ReadBits(); - } - - bool result = (_bits & _bitMask) != 0; - _bitMask >>= 1; - return result; - } - - public ushort ReadShort() - { - ushort result = NetworkOrderDeserializer.ReadUInt16(Span); - _offset += 2; - return result; - } - - public string ReadShortstr() - { - string result = WireFormatting.ReadShortstr(Span, out int bytesRead); - _offset += bytesRead; - return result; - } - - /// A type of . - public Dictionary ReadTable() - { - Dictionary result = WireFormatting.ReadTable(Span, out int bytesRead); - _offset += bytesRead; - return result; - } - - public AmqpTimestamp ReadTimestamp() - { - AmqpTimestamp result = WireFormatting.ReadTimestamp(Span); - _offset += 8; - return result; - } - } -} diff --git a/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyWriter.cs b/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyWriter.cs deleted file mode 100644 index d8fa833007..0000000000 --- a/projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyWriter.cs +++ /dev/null @@ -1,135 +0,0 @@ -// This source code is dual-licensed under the Apache License, version -// 2.0, and the Mozilla Public License, version 2.0. -// -// The APL v2.0: -// -//--------------------------------------------------------------------------- -// Copyright (c) 2007-2020 VMware, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//--------------------------------------------------------------------------- -// -// The MPL v2.0: -// -//--------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// -// Copyright (c) 2007-2020 VMware, Inc. All rights reserved. -//--------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; - -using RabbitMQ.Util; - -namespace RabbitMQ.Client.Impl -{ - internal ref struct ContentHeaderPropertyWriter - { - private const ushort StartBitMask = 0b1000_0000_0000_0000; - private const ushort EndBitMask = 0b0000_0000_0000_0001; - - private readonly Span _span; - private ushort _bitAccumulator; - private ushort _bitMask; - - public int Offset { get; private set; } - - private Span Span => _span.Slice(Offset); - - public ContentHeaderPropertyWriter(Span span) - { - _span = span; - Offset = 0; - _bitAccumulator = 0; - _bitMask = StartBitMask; - } - - public void FinishPresence() - { - WriteBits(); - } - - public void WriteBit(bool bit) - { - WritePresence(bit); - } - - public void WriteLong(uint val) - { - Offset += WireFormatting.WriteLong(Span, val); - } - - public void WriteLonglong(ulong val) - { - Offset += WireFormatting.WriteLonglong(Span, val); - } - - public void WriteLongstr(byte[] val) - { - Offset += WireFormatting.WriteLongstr(Span, val); - } - - public void WriteOctet(byte val) - { - _span[Offset++] = val; - } - - public void WritePresence(bool present) - { - if (_bitMask == EndBitMask) - { - // Mark continuation - _bitAccumulator |= _bitMask; - WriteBits(); - } - - if (present) - { - _bitAccumulator |= _bitMask; - } - - _bitMask >>= 1; - } - - public void WriteShort(ushort val) - { - Offset += WireFormatting.WriteShort(Span, val); - } - - public void WriteShortstr(string val) - { - Offset += WireFormatting.WriteShortstr(Span, val); - } - - public void WriteTable(IDictionary val) - { - Offset += WireFormatting.WriteTable(Span, val); - } - - public void WriteTimestamp(AmqpTimestamp val) - { - Offset += WireFormatting.WriteTimestamp(Span, val); - } - - private void WriteBits() - { - NetworkOrderSerializer.WriteUInt16(Span, _bitAccumulator); - Offset += 2; - _bitMask = StartBitMask; - _bitAccumulator = 0; - } - } -} diff --git a/projects/RabbitMQ.Client/client/impl/Frame.cs b/projects/RabbitMQ.Client/client/impl/Frame.cs index bb48bc7c5b..1db6c3d4b5 100644 --- a/projects/RabbitMQ.Client/client/impl/Frame.cs +++ b/projects/RabbitMQ.Client/client/impl/Frame.cs @@ -81,9 +81,8 @@ public static int WriteTo(Span span, ushort channel, MethodBase method) const int StartMethodArguments = StartPayload + 4; NetworkOrderSerializer.WriteUInt32(span.Slice(StartClassId), (uint)method.ProtocolCommandId); - var argWriter = new MethodArgumentWriter(span.Slice(StartMethodArguments)); - method.WriteArgumentsTo(ref argWriter); - return WriteBaseFrame(span, FrameType.FrameMethod, channel, StartMethodArguments - StartPayload + argWriter.Offset); + int offset = method.WriteArgumentsTo(span.Slice(StartMethodArguments)); + return WriteBaseFrame(span, FrameType.FrameMethod, channel, StartMethodArguments - StartPayload + offset); } } @@ -106,9 +105,8 @@ public static int WriteTo(Span span, ushort channel, ContentHeaderBase hea NetworkOrderSerializer.WriteUInt16(span.Slice(StartClassId), header.ProtocolClassId); NetworkOrderSerializer.WriteUInt16(span.Slice(StartWeight), 0); // Weight - not used NetworkOrderSerializer.WriteUInt64(span.Slice(StartBodyLength), (ulong)bodyLength); - var headerWriter = new ContentHeaderPropertyWriter(span.Slice(StartHeaderArguments)); - header.WritePropertiesTo(ref headerWriter); - return WriteBaseFrame(span, FrameType.FrameHeader, channel, StartHeaderArguments - StartPayload + headerWriter.Offset); + int offset = header.WritePropertiesTo(span.Slice(StartHeaderArguments)); + return WriteBaseFrame(span, FrameType.FrameHeader, channel, StartHeaderArguments - StartPayload + offset); } } diff --git a/projects/RabbitMQ.Client/client/impl/MethodArgumentReader.cs b/projects/RabbitMQ.Client/client/impl/MethodArgumentReader.cs deleted file mode 100644 index ae8190faa0..0000000000 --- a/projects/RabbitMQ.Client/client/impl/MethodArgumentReader.cs +++ /dev/null @@ -1,129 +0,0 @@ -// This source code is dual-licensed under the Apache License, version -// 2.0, and the Mozilla Public License, version 2.0. -// -// The APL v2.0: -// -//--------------------------------------------------------------------------- -// Copyright (c) 2007-2020 VMware, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//--------------------------------------------------------------------------- -// -// The MPL v2.0: -// -//--------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// -// Copyright (c) 2007-2020 VMware, Inc. All rights reserved. -//--------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; - -using RabbitMQ.Util; - -namespace RabbitMQ.Client.Impl -{ - internal ref struct MethodArgumentReader - { - private readonly ReadOnlySpan _span; - private int _offset; - private int _bitMask; - private int _bits; - - private ReadOnlySpan Span => _span.Slice(_offset); - - public MethodArgumentReader(ReadOnlySpan span) - { - _span = span; - _offset = 0; - _bitMask = 0; - _bits = 0; - } - - public bool ReadBit() - { - int bit = _bitMask; - if (bit == 0) - { - _bits = _span[_offset++]; - bit = 1; - } - - bool result = (_bits & bit) != 0; - _bitMask = bit << 1; - return result; - } - - public byte[] ReadContent() - { - throw new NotSupportedException("ReadContent should not be called"); - } - - public uint ReadLong() - { - uint result = NetworkOrderDeserializer.ReadUInt32(Span); - _offset += 4; - return result; - } - - public ulong ReadLonglong() - { - ulong result = NetworkOrderDeserializer.ReadUInt64(Span); - _offset += 8; - return result; - } - - public byte[] ReadLongstr() - { - byte[] result = WireFormatting.ReadLongstr(Span); - _offset += 4 + result.Length; - return result; - } - - public byte ReadOctet() - { - return _span[_offset++]; - } - - public ushort ReadShort() - { - ushort result = NetworkOrderDeserializer.ReadUInt16(Span); - _offset += 2; - return result; - } - - public string ReadShortstr() - { - string result = WireFormatting.ReadShortstr(Span, out int bytesRead); - _offset += bytesRead; - return result; - } - - public Dictionary ReadTable() - { - Dictionary result = WireFormatting.ReadTable(Span, out int bytesRead); - _offset += bytesRead; - return result; - } - - public AmqpTimestamp ReadTimestamp() - { - AmqpTimestamp result = WireFormatting.ReadTimestamp(Span); - _offset += 8; - return result; - } - } -} diff --git a/projects/RabbitMQ.Client/client/impl/MethodArgumentWriter.cs b/projects/RabbitMQ.Client/client/impl/MethodArgumentWriter.cs deleted file mode 100644 index 5e4d1d9db6..0000000000 --- a/projects/RabbitMQ.Client/client/impl/MethodArgumentWriter.cs +++ /dev/null @@ -1,125 +0,0 @@ -// This source code is dual-licensed under the Apache License, version -// 2.0, and the Mozilla Public License, version 2.0. -// -// The APL v2.0: -// -//--------------------------------------------------------------------------- -// Copyright (c) 2007-2020 VMware, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//--------------------------------------------------------------------------- -// -// The MPL v2.0: -// -//--------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// -// Copyright (c) 2007-2020 VMware, Inc. All rights reserved. -//--------------------------------------------------------------------------- - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace RabbitMQ.Client.Impl -{ - internal ref struct MethodArgumentWriter - { - private readonly Span _span; - private int _bitAccumulator; - private int _bitMask; - - public int Offset { get; private set; } - - private Span Span => _span.Slice(Offset); - - public MethodArgumentWriter(Span span) - { - _span = span; - Offset = 0; - _bitAccumulator = 0; - _bitMask = 1; - } - - public void WriteBit(bool val) - { - if (val) - { - _bitAccumulator |= _bitMask; - } - _bitMask <<= 1; - } - - public void EndBits() - { - if (_bitMask > 1) - { - _span[Offset++] = (byte)_bitAccumulator; - _bitAccumulator = 0; - _bitMask = 1; - } - } - - public void WriteContent(byte[] val) - { - throw new NotSupportedException("WriteContent should not be called"); - } - - public void WriteLong(uint val) - { - Offset += WireFormatting.WriteLong(Span, val); - } - - public void WriteLonglong(ulong val) - { - Offset += WireFormatting.WriteLonglong(Span, val); - } - - public void WriteLongstr(byte[] val) - { - Offset += WireFormatting.WriteLongstr(Span, val); - } - - public void WriteOctet(byte val) - { - _span[Offset++] = val; - } - - public void WriteShort(ushort val) - { - Offset += WireFormatting.WriteShort(Span, val); - } - - public void WriteShortstr(string val) - { - Offset += WireFormatting.WriteShortstr(Span, val); - } - - public void WriteTable(IDictionary val) - { - Offset += WireFormatting.WriteTable(Span, val); - } - - public void WriteTable(IDictionary val) - { - Offset += WireFormatting.WriteTable(Span, val); - } - - public void WriteTimestamp(AmqpTimestamp val) - { - Offset += WireFormatting.WriteTimestamp(Span, val); - } - } -} diff --git a/projects/RabbitMQ.Client/client/impl/MethodBase.cs b/projects/RabbitMQ.Client/client/impl/MethodBase.cs index 93a301a280..7384df3963 100644 --- a/projects/RabbitMQ.Client/client/impl/MethodBase.cs +++ b/projects/RabbitMQ.Client/client/impl/MethodBase.cs @@ -29,6 +29,7 @@ // Copyright (c) 2007-2020 VMware, Inc. All rights reserved. //--------------------------------------------------------------------------- +using System; using RabbitMQ.Client.client.framing; namespace RabbitMQ.Client.Impl @@ -53,8 +54,8 @@ internal abstract class MethodBase /// Retrieves the name of this method - for debugging use. /// public abstract string ProtocolMethodName { get; } - public abstract void ReadArgumentsFrom(ref MethodArgumentReader reader); - public abstract void WriteArgumentsTo(ref MethodArgumentWriter writer); + + public abstract int WriteArgumentsTo(Span span); public abstract int GetRequiredBufferSize(); } } diff --git a/projects/RabbitMQ.Client/client/impl/ProtocolBase.cs b/projects/RabbitMQ.Client/client/impl/ProtocolBase.cs index 255e527d4c..ddf4fccac3 100644 --- a/projects/RabbitMQ.Client/client/impl/ProtocolBase.cs +++ b/projects/RabbitMQ.Client/client/impl/ProtocolBase.cs @@ -83,7 +83,7 @@ public void CreateConnectionClose(ushort reasonCode, string reasonText, out Outg replyProtocolCommandId = ProtocolCommandId.ConnectionCloseOk; } - internal abstract ContentHeaderBase DecodeContentHeaderFrom(ushort classId); + internal abstract ContentHeaderBase DecodeContentHeaderFrom(ushort classId, ReadOnlySpan span); internal abstract MethodBase DecodeMethodFrom(ReadOnlySpan reader); public override bool Equals(object obj) diff --git a/projects/RabbitMQ.Client/client/impl/WireFormatting.cs b/projects/RabbitMQ.Client/client/impl/WireFormatting.cs index 317886baeb..74f75aaec9 100644 --- a/projects/RabbitMQ.Client/client/impl/WireFormatting.cs +++ b/projects/RabbitMQ.Client/client/impl/WireFormatting.cs @@ -32,22 +32,24 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text; - using RabbitMQ.Client.Exceptions; using RabbitMQ.Util; namespace RabbitMQ.Client.Impl { - internal class WireFormatting + internal static class WireFormatting { - public static decimal AmqpToDecimal(byte scale, uint unsignedMantissa) + public static decimal ReadDecimal(ReadOnlySpan span) { + byte scale = span[0]; if (scale > 28) { throw new SyntaxErrorException($"Unrepresentable AMQP decimal table field: scale={scale}"); } + uint unsignedMantissa = NetworkOrderDeserializer.ReadUInt32(span.Slice(1)); return new decimal( // The low 32 bits of a 96-bit integer lo: (int)(unsignedMantissa & 0x7FFFFFFF), @@ -60,29 +62,6 @@ public static decimal AmqpToDecimal(byte scale, uint unsignedMantissa) scale: scale); } - public static void DecimalToAmqp(decimal value, out byte scale, out int mantissa) - { - // According to the documentation :- - // - word 0: low-order "mantissa" - // - word 1, word 2: medium- and high-order "mantissa" - // - word 3: mostly reserved; "exponent" and sign bit - // In one way, this is broader than AMQP: the mantissa is larger. - // In another way, smaller: the exponent ranges 0-28 inclusive. - // We need to be careful about the range of word 0, too: we can - // only take 31 bits worth of it, since the sign bit needs to - // fit in there too. - int[] bitRepresentation = decimal.GetBits(value); - if (bitRepresentation[1] != 0 || // mantissa extends into middle word - bitRepresentation[2] != 0 || // mantissa extends into top word - bitRepresentation[0] < 0) // mantissa extends beyond 31 bits - { - throw new WireFormattingException("Decimal overflow in AMQP encoding", value); - } - scale = (byte)((((uint)bitRepresentation[3]) >> 16) & 0xFF); - mantissa = (int)((((uint)bitRepresentation[3]) & 0x80000000) | - (((uint)bitRepresentation[0]) & 0x7FFFFFFF)); - } - public static IList ReadArray(ReadOnlySpan span, out int bytesRead) { List array = new List(); @@ -98,22 +77,14 @@ public static IList ReadArray(ReadOnlySpan span, out int bytesRead) return array; } - public static decimal ReadDecimal(ReadOnlySpan span) - { - byte scale = span[0]; - uint unsignedMantissa = NetworkOrderDeserializer.ReadUInt32(span.Slice(1)); - return AmqpToDecimal(scale, unsignedMantissa); - } - public static object ReadFieldValue(ReadOnlySpan span, out int bytesRead) { bytesRead = 1; switch ((char)span[0]) { case 'S': - byte[] result = ReadLongstr(span.Slice(1)); - bytesRead += result.Length + 4; - return result; + bytesRead += ReadLongstr(span.Slice(1), out var bytes); + return bytes; case 'I': bytesRead += 4; return NetworkOrderDeserializer.ReadInt32(span.Slice(1)); @@ -124,12 +95,11 @@ public static object ReadFieldValue(ReadOnlySpan span, out int bytesRead) bytesRead += 5; return ReadDecimal(span.Slice(1)); case 'T': - bytesRead += 8; - return ReadTimestamp(span.Slice(1)); + bytesRead += ReadTimestamp(span.Slice(1), out var timestamp); + return timestamp; case 'F': - Dictionary tableResult = ReadTable(span.Slice(1), out int tableBytesRead); - bytesRead += tableBytesRead; - return tableResult; + bytesRead += ReadDictionary(span.Slice(1), out var dictionary); + return dictionary; case 'A': IList arrayResult = ReadArray(span.Slice(1), out int arrayBytesRead); bytesRead += arrayBytesRead; @@ -156,8 +126,7 @@ public static object ReadFieldValue(ReadOnlySpan span, out int bytesRead) bytesRead += 1; return span[1] != 0; case 'x': - byte[] binaryTableResult = ReadLongstr(span.Slice(1)); - bytesRead += binaryTableResult.Length + 4; + bytesRead += ReadLongstr(span.Slice(1), out var binaryTableResult); return new BinaryTableValue(binaryTableResult); case 'V': return null; @@ -166,35 +135,137 @@ public static object ReadFieldValue(ReadOnlySpan span, out int bytesRead) } } - public static byte[] ReadLongstr(ReadOnlySpan span) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadLongstr(ReadOnlySpan span, out byte[] value) { uint byteCount = NetworkOrderDeserializer.ReadUInt32(span); if (byteCount > int.MaxValue) { - throw new SyntaxErrorException($"Long string too long; byte length={byteCount}, max={int.MaxValue}"); + value = null; + return ThrowSyntaxErrorException(byteCount); } - return span.Slice(4, (int)byteCount).ToArray(); + value = span.Slice(4, (int)byteCount).ToArray(); + return 4 + value.Length; } - public static unsafe string ReadShortstr(ReadOnlySpan span, out int bytesRead) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe int ReadShortstr(ReadOnlySpan span, out string value) { int byteCount = span[0]; if (byteCount == 0) { - bytesRead = 1; - return string.Empty; + value = string.Empty; + return 1; } - if (span.Length >= byteCount + 1) + + // equals span.Length >= byteCount + 1 + if (span.Length > byteCount) { - bytesRead = 1 + byteCount; fixed (byte* bytes = &span.Slice(1).GetPinnableReference()) { - return Encoding.UTF8.GetString(bytes, byteCount); + value = Encoding.UTF8.GetString(bytes, byteCount); + return 1 + byteCount; } } - throw new ArgumentOutOfRangeException(nameof(span), $"Span has not enough space ({span.Length} instead of {byteCount + 1})"); + value = string.Empty; + return ThrowArgumentOutOfRangeException(span.Length, byteCount + 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, out bool val) + { + val = (span[0] & 0b0000_0001) != 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, out bool val1, out bool val2) + { + byte bits = span[0]; + val1 = (bits & 0b0000_0001) != 0; + val2 = (bits & 0b0000_0010) != 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, out bool val1, out bool val2, out bool val3) + { + byte bits = span[0]; + val1 = (bits & 0b0000_0001) != 0; + val2 = (bits & 0b0000_0010) != 0; + val3 = (bits & 0b0000_0100) != 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, out bool val1, out bool val2, out bool val3, out bool val4) + { + byte bits = span[0]; + val1 = (bits & 0b0000_0001) != 0; + val2 = (bits & 0b0000_0010) != 0; + val3 = (bits & 0b0000_0100) != 0; + val4 = (bits & 0b0000_1000) != 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, out bool val1, out bool val2, out bool val3, out bool val4, out bool val5) + { + byte bits = span[0]; + val1 = (bits & 0b0000_0001) != 0; + val2 = (bits & 0b0000_0010) != 0; + val3 = (bits & 0b0000_0100) != 0; + val4 = (bits & 0b0000_1000) != 0; + val5 = (bits & 0b0001_0000) != 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadBits(ReadOnlySpan span, + out bool val1, out bool val2, out bool val3, out bool val4, out bool val5, + out bool val6, out bool val7, out bool val8, out bool val9, out bool val10, + out bool val11, out bool val12, out bool val13, out bool val14) + { + byte bits = span[0]; + val1 = (bits & 0b1000_0000) != 0; + val2 = (bits & 0b0100_0000) != 0; + val3 = (bits & 0b0010_0000) != 0; + val4 = (bits & 0b0001_0000) != 0; + val5 = (bits & 0b0000_1000) != 0; + val6 = (bits & 0b0000_0100) != 0; + val7 = (bits & 0b0000_0010) != 0; + val8 = (bits & 0b0000_0001) != 0; + bits = span[1]; + val9 = (bits & 0b1000_0000) != 0; + val10 = (bits & 0b0100_0000) != 0; + val11 = (bits & 0b0010_0000) != 0; + val12 = (bits & 0b0001_0000) != 0; + val13 = (bits & 0b0000_1000) != 0; + val14 = (bits & 0b0000_0100) != 0; + return 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadShort(ReadOnlySpan span, out ushort value) + { + value = NetworkOrderDeserializer.ReadUInt16(span); + return 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadLong(ReadOnlySpan span, out uint value) + { + value = NetworkOrderDeserializer.ReadUInt32(span); + return 4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadLonglong(ReadOnlySpan span, out ulong value) + { + value = NetworkOrderDeserializer.ReadUInt64(span); + return 8; } ///Reads an AMQP "table" definition from the reader. @@ -204,38 +275,37 @@ public static unsafe string ReadShortstr(ReadOnlySpan span, out int bytesR /// x and V types and the AMQP 0-9-1 A type. /// /// A . - public static Dictionary ReadTable(ReadOnlySpan span, out int bytesRead) + public static int ReadDictionary(ReadOnlySpan span, out Dictionary valueDictionary) { - bytesRead = 4; long tableLength = NetworkOrderDeserializer.ReadUInt32(span); if (tableLength == 0) { - return null; + valueDictionary = null; + return 4; } - Dictionary table = new Dictionary(); - while ((bytesRead - 4) < tableLength) + span = span.Slice(4); + valueDictionary = new Dictionary(); + int bytesRead = 0; + while (bytesRead < tableLength) { - string key = ReadShortstr(span.Slice(bytesRead), out int keyBytesRead); - bytesRead += keyBytesRead; + bytesRead += ReadShortstr(span.Slice(bytesRead), out string key); object value = ReadFieldValue(span.Slice(bytesRead), out int valueBytesRead); bytesRead += valueBytesRead; - if (!table.ContainsKey(key)) - { - table[key] = value; - } + valueDictionary[key] = value; } - return table; + return 4 + bytesRead; } - public static AmqpTimestamp ReadTimestamp(ReadOnlySpan span) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadTimestamp(ReadOnlySpan span, out AmqpTimestamp value) { - ulong stamp = NetworkOrderDeserializer.ReadUInt64(span); // 0-9 is afaict silent on the signedness of the timestamp. // See also MethodArgumentWriter.WriteTimestamp and AmqpTimestamp itself - return new AmqpTimestamp((long)stamp); + value = new AmqpTimestamp((long)NetworkOrderDeserializer.ReadUInt64(span)); + return 8; } public static int WriteArray(Span span, IList val) @@ -245,17 +315,15 @@ public static int WriteArray(Span span, IList val) NetworkOrderSerializer.WriteUInt32(span, 0); return 4; } - else - { - int bytesWritten = 0; - for (int index = 0; index < val.Count; index++) - { - bytesWritten += WriteFieldValue(span.Slice(4 + bytesWritten), val[index]); - } - NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten); - return 4 + bytesWritten; + int bytesWritten = 4; + for (int index = 0; index < val.Count; index++) + { + bytesWritten += WriteFieldValue(span.Slice(bytesWritten), val[index]); } + + NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten - 4u); + return bytesWritten; } public static int GetArrayByteCount(IList val) @@ -281,6 +349,29 @@ public static int WriteDecimal(Span span, decimal value) return 1 + WriteLong(span.Slice(1), (uint)mantissa); } + private static void DecimalToAmqp(decimal value, out byte scale, out int mantissa) + { + // According to the documentation :- + // - word 0: low-order "mantissa" + // - word 1, word 2: medium- and high-order "mantissa" + // - word 3: mostly reserved; "exponent" and sign bit + // In one way, this is broader than AMQP: the mantissa is larger. + // In another way, smaller: the exponent ranges 0-28 inclusive. + // We need to be careful about the range of word 0, too: we can + // only take 31 bits worth of it, since the sign bit needs to + // fit in there too. + int[] bitRepresentation = decimal.GetBits(value); + if (bitRepresentation[1] != 0 || // mantissa extends into middle word + bitRepresentation[2] != 0 || // mantissa extends into top word + bitRepresentation[0] < 0) // mantissa extends beyond 31 bits + { + throw new WireFormattingException("Decimal overflow in AMQP encoding", value); + } + scale = (byte)((((uint)bitRepresentation[3]) >> 16) & 0xFF); + mantissa = (int)((((uint)bitRepresentation[3]) & 0x80000000) | + (((uint)bitRepresentation[0]) & 0x7FFFFFFF)); + } + public static int WriteFieldValue(Span span, object value) { if (value is null) @@ -391,18 +482,209 @@ public static int GetFieldValueByteCount(object value) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int WriteLong(Span span, uint val) { NetworkOrderSerializer.WriteUInt32(span, val); return 4; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int WriteLonglong(Span span, ulong val) { NetworkOrderSerializer.WriteUInt64(span, val); return 8; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, bool val) + { + span[0] = val ? (byte) 1 : (byte) 0; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, bool val1, bool val2) + { + byte bits = 0; + if (val1) + { + bits |= 1 << 0; + } + + if (val2) + { + bits |= 1 << 1; + } + span[0] = bits; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, bool val1, bool val2, bool val3) + { + byte bits = 0; + if (val1) + { + bits |= 1 << 0; + } + + if (val2) + { + bits |= 1 << 1; + } + + if (val3) + { + bits |= 1 << 2; + } + + span[0] = bits; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, bool val1, bool val2, bool val3, bool val4) + { + byte bits = 0; + if (val1) + { + bits |= 1 << 0; + } + + if (val2) + { + bits |= 1 << 1; + } + + if (val3) + { + bits |= 1 << 2; + } + + if (val4) + { + bits |= 1 << 3; + } + + span[0] = bits; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, bool val1, bool val2, bool val3, bool val4, bool val5) + { + byte bits = 0; + if (val1) + { + bits |= 1 << 0; + } + + if (val2) + { + bits |= 1 << 1; + } + + if (val3) + { + bits |= 1 << 2; + } + + if (val4) + { + bits |= 1 << 3; + } + + if (val5) + { + bits |= 1 << 4; + } + span[0] = bits; + return 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int WriteBits(Span span, + bool val1, bool val2, bool val3, bool val4, bool val5, + bool val6, bool val7, bool val8, bool val9, bool val10, + bool val11, bool val12, bool val13, bool val14) + { + byte bits = 0; + if (val1) + { + bits |= 1 << 7; + } + + if (val2) + { + bits |= 1 << 6; + } + + if (val3) + { + bits |= 1 << 5; + } + + if (val4) + { + bits |= 1 << 4; + } + + if (val5) + { + bits |= 1 << 3; + } + + if (val6) + { + bits |= 1 << 2; + } + + if (val7) + { + bits |= 1 << 1; + } + + if (val8) + { + bits |= 1 << 0; + } + span[0] = bits; + bits = 0; + if (val9) + { + bits |= 1 << 7; + } + + if (val10) + { + bits |= 1 << 6; + } + + if (val11) + { + bits |= 1 << 5; + } + + if (val12) + { + bits |= 1 << 4; + } + + if (val13) + { + bits |= 1 << 3; + } + + if (val14) + { + bits |= 1 << 2; + } + span[1] = bits; + return 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int WriteLongstr(Span span, ReadOnlySpan val) { WriteLong(span, (uint)val.Length); @@ -410,12 +692,14 @@ public static int WriteLongstr(Span span, ReadOnlySpan val) return 4 + val.Length; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int WriteShort(Span span, ushort val) { NetworkOrderSerializer.WriteUInt16(span, val); return 2; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe int WriteShortstr(Span span, string val) { int maxLength = span.Length - 1; @@ -434,11 +718,12 @@ public static unsafe int WriteShortstr(Span span, string val) } catch (ArgumentException) { - throw new ArgumentOutOfRangeException(nameof(val), val, $"Value exceeds the maximum allowed length of {maxLength} bytes."); + return ThrowArgumentOutOfRangeException(val, maxLength); } } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe int WriteLongstr(Span span, string val) { fixed (char* chars = val) @@ -454,23 +739,21 @@ public static int WriteTable(Span span, IDictionary val) { if (val is null || val.Count == 0) { - NetworkOrderSerializer.WriteUInt32(span, 0); + NetworkOrderSerializer.WriteUInt32(span, 0u); return 4; } - else - { - // Let's only write after the length header. - Span slice = span.Slice(4); - int bytesWritten = 0; - foreach (DictionaryEntry entry in val) - { - bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key.ToString()); - bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); - } - NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten); - return 4 + bytesWritten; + // Let's only write after the length header. + Span slice = span.Slice(4); + int bytesWritten = 0; + foreach (DictionaryEntry entry in val) + { + bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key.ToString()); + bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); } + + NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten); + return 4 + bytesWritten; } public static int WriteTable(Span span, IDictionary val) @@ -480,31 +763,29 @@ public static int WriteTable(Span span, IDictionary val) NetworkOrderSerializer.WriteUInt32(span, 0); return 4; } - else + + // Let's only write after the length header. + Span slice = span.Slice(4); + int bytesWritten = 0; + if (val is Dictionary dict) { - // Let's only write after the length header. - Span slice = span.Slice(4); - int bytesWritten = 0; - if (val is Dictionary dict) + foreach (KeyValuePair entry in dict) { - foreach (KeyValuePair entry in dict) - { - bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key); - bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); - } + bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key); + bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); } - else + } + else + { + foreach (KeyValuePair entry in val) { - foreach (KeyValuePair entry in val) - { - bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key); - bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); - } + bytesWritten += WriteShortstr(slice.Slice(bytesWritten), entry.Key); + bytesWritten += WriteFieldValue(slice.Slice(bytesWritten), entry.Value); } - - NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten); - return 4 + bytesWritten; } + + NetworkOrderSerializer.WriteUInt32(span, (uint)bytesWritten); + return 4 + bytesWritten; } public static int GetTableByteCount(IDictionary val) @@ -552,11 +833,27 @@ public static int GetTableByteCount(IDictionary val) return byteCount; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int WriteTimestamp(Span span, AmqpTimestamp val) { // 0-9 is afaict silent on the signedness of the timestamp. // See also MethodArgumentReader.ReadTimestamp and AmqpTimestamp itself return WriteLonglong(span, (ulong)val.UnixTime); } + + public static int ThrowArgumentOutOfRangeException(int orig, int expected) + { + throw new ArgumentOutOfRangeException("span", $"Span has not enough space ({orig} instead of {expected})"); + } + + public static int ThrowArgumentOutOfRangeException(string val, int maxLength) + { + throw new ArgumentOutOfRangeException(nameof(val), val, $"Value exceeds the maximum allowed length of {maxLength} bytes."); + } + + public static int ThrowSyntaxErrorException(uint byteCount) + { + throw new SyntaxErrorException($"Long string too long; byte length={byteCount}, max={int.MaxValue}"); + } } } diff --git a/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs b/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs index 74eb3615d7..99ae415624 100644 --- a/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs +++ b/projects/RabbitMQ.Client/util/NetworkOrderSerializer.cs @@ -145,12 +145,12 @@ internal static void WriteUInt32(Span span, uint val) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WriteUInt64(Span span, ulong val) { +#if NETFRAMEWORK if (span.Length < 8) { throw new ArgumentOutOfRangeException(nameof(span), "Insufficient length to write UInt64 from memory."); } -#if NETFRAMEWORK span[0] = (byte)((val >> 56) & 0xFF); span[1] = (byte)((val >> 48) & 0xFF); span[2] = (byte)((val >> 40) & 0xFF); diff --git a/projects/Unit/APIApproval.Approve.verified.txt b/projects/Unit/APIApproval.Approve.verified.txt index 48d75c7599..75ceac3259 100644 --- a/projects/Unit/APIApproval.Approve.verified.txt +++ b/projects/Unit/APIApproval.Approve.verified.txt @@ -1,3 +1,4 @@ +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"Benchmarks, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d20ec856aeeb8c3153a77faa2d80e6e43b5db93224a20cc7ae384f65f142e89730e2ff0fcc5d578bbe96fa98a7196c77329efdee4579b3814c0789e5a39b51df6edd75b602a33ceabdfcf19a3feb832f31d8254168cd7ba5700dfbca301fbf8db614ba41ba18474de0a5f4c2d51c995bc3636c641c8cbe76f45717bfcb943b5")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"Unit, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d20ec856aeeb8c3153a77faa2d80e6e43b5db93224a20cc7ae384f65f142e89730e2ff0fcc5d578bbe96fa98a7196c77329efdee4579b3814c0789e5a39b51df6edd75b602a33ceabdfcf19a3feb832f31d8254168cd7ba5700dfbca301fbf8db614ba41ba18474de0a5f4c2d51c995bc3636c641c8cbe76f45717bfcb943b5")] namespace RabbitMQ.Client { diff --git a/projects/Unit/TestBasicProperties.cs b/projects/Unit/TestBasicProperties.cs index d15817553a..36b6e1b410 100644 --- a/projects/Unit/TestBasicProperties.cs +++ b/projects/Unit/TestBasicProperties.cs @@ -79,7 +79,6 @@ public void TestNullableProperties_CanWrite( // Arrange var subject = new Framing.BasicProperties { - // Act ClusterId = clusterId, CorrelationId = correlationId, @@ -97,13 +96,10 @@ public void TestNullableProperties_CanWrite( Assert.AreEqual(isMessageIdPresent, subject.IsMessageIdPresent()); Span span = new byte[1024]; - var writer = new Impl.ContentHeaderPropertyWriter(span); - subject.WritePropertiesTo(ref writer); + int offset = subject.WritePropertiesTo(span); // Read from Stream - var propertiesFromStream = new Framing.BasicProperties(); - var reader = new Impl.ContentHeaderPropertyReader(span.Slice(0, writer.Offset)); - propertiesFromStream.ReadPropertiesFrom(ref reader); + var propertiesFromStream = new Framing.BasicProperties(span.Slice(0, offset)); Assert.AreEqual(clusterId, propertiesFromStream.ClusterId); Assert.AreEqual(correlationId, propertiesFromStream.CorrelationId); @@ -130,13 +126,10 @@ public void TestProperties_ReplyTo([Values(null, "foo_1", "fanout://name/key")] Assert.AreEqual(isReplyToPresent, subject.IsReplyToPresent()); Span span = new byte[1024]; - var writer = new Impl.ContentHeaderPropertyWriter(span); - subject.WritePropertiesTo(ref writer); + int offset = subject.WritePropertiesTo(span); // Read from Stream - var propertiesFromStream = new Framing.BasicProperties(); - var reader = new Impl.ContentHeaderPropertyReader(span.Slice(0, writer.Offset)); - propertiesFromStream.ReadPropertiesFrom(ref reader); + var propertiesFromStream = new Framing.BasicProperties(span.Slice(0, offset)); Assert.AreEqual(replyTo, propertiesFromStream.ReplyTo); Assert.AreEqual(isReplyToPresent, propertiesFromStream.IsReplyToPresent()); diff --git a/projects/Unit/TestContentHeaderCodec.cs b/projects/Unit/TestContentHeaderCodec.cs index 7c89a0e0a9..152f94a151 100644 --- a/projects/Unit/TestContentHeaderCodec.cs +++ b/projects/Unit/TestContentHeaderCodec.cs @@ -30,10 +30,9 @@ //--------------------------------------------------------------------------- using System; - +using System.Collections.Generic; using NUnit.Framework; -using RabbitMQ.Client.Impl; using RabbitMQ.Util; namespace RabbitMQ.Client.Unit @@ -59,64 +58,63 @@ public void Check(ReadOnlyMemory actual, ReadOnlyMemory expected) } } - [Test] - public void TestPresence() - { - byte[] memory = new byte[1024]; - var m_w = new ContentHeaderPropertyWriter(memory); - m_w.WritePresence(false); - m_w.WritePresence(true); - m_w.WritePresence(false); - m_w.WritePresence(true); - m_w.FinishPresence(); - Check(memory.AsMemory().Slice(0, m_w.Offset), new byte[] { 0x50, 0x00 }); - } - - [Test] - public void TestLongPresence() - { - byte[] memory = new byte[1024]; - var m_w = new ContentHeaderPropertyWriter(memory); - - m_w.WritePresence(false); - m_w.WritePresence(true); - m_w.WritePresence(false); - m_w.WritePresence(true); - for (int i = 0; i < 20; i++) - { - m_w.WritePresence(false); - } - m_w.WritePresence(true); - m_w.FinishPresence(); - Check(memory.AsMemory().Slice(0, m_w.Offset), new byte[] { 0x50, 0x01, 0x00, 0x40 }); - } - - [Test] - public void TestNoPresence() - { - byte[] memory = new byte[1024]; - var m_w = new ContentHeaderPropertyWriter(memory); - m_w.FinishPresence(); - Check(memory.AsMemory().Slice(0, m_w.Offset), new byte[] { 0x00, 0x00 }); - } - [Test] public void TestSimpleProperties() { - RabbitMQ.Client.Framing.BasicProperties prop = - new RabbitMQ.Client.Framing.BasicProperties + Framing.BasicProperties prop = new Framing.BasicProperties { ContentType = "text/plain" }; int bytesNeeded = prop.GetRequiredPayloadBufferSize(); byte[] bytes = new byte[bytesNeeded]; - var m_w = new ContentHeaderPropertyWriter(bytes); - prop.WritePropertiesTo(ref m_w); - Check(bytes.AsMemory().Slice(0, m_w.Offset), new byte[] { + int offset = prop.WritePropertiesTo(bytes); + Check(bytes.AsMemory().Slice(0, offset), new byte[] { 0x80, 0x00, // props flags 0x0A, // shortstr len 0x74, 0x65, 0x78, 0x74, 0x2F, 0x70, 0x6C, 0x61, 0x69, 0x6E // text/plain }); } + + [Test] + public void TestFullProperties() + { + Framing.BasicProperties prop = new Framing.BasicProperties + { + AppId = "A", + ContentType = "B", + ContentEncoding = "C", + ClusterId = "D", + CorrelationId = "E", + DeliveryMode = 1, + Expiration = "F", + MessageId = "G", + Priority = 2, + Timestamp = new AmqpTimestamp(3), + Type = "H", + ReplyTo = "I", + UserId = "J", + Headers = new Dictionary(0) + }; + int bytesNeeded = prop.GetRequiredPayloadBufferSize(); + byte[] bytes = new byte[bytesNeeded]; + int offset = prop.WritePropertiesTo(bytes); + Check(bytes.AsMemory().Slice(0, offset), new byte[] { + 0b1111_1111, 0b1111_1100, // props flags (all set) + 0x01, 0x42, // ContentType + 0x01, 0x43, // ContentEncoding + 0x00, 0x00, 0x00, 0x00, // Headers (length 0) + 0x01, // DeliveryMode + 0x02, // Priority + 0x01, 0x45, // CorrelationId + 0x01, 0x49, // ReplyTo + 0x01, 0x46, // Expiration + 0x01, 0x47, // MessageId + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // Timestamp + 0x01, 0x48, // Type + 0x01, 0x4A, // UserId + 0x01, 0x41, // AppId + 0x01, 0x44, // ClusterId + }); + } } } diff --git a/projects/Unit/TestFieldTableFormatting.cs b/projects/Unit/TestFieldTableFormatting.cs index fd096570ba..8022c0eb34 100644 --- a/projects/Unit/TestFieldTableFormatting.cs +++ b/projects/Unit/TestFieldTableFormatting.cs @@ -65,7 +65,7 @@ public void TestStandardTypes() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - IDictionary nt = (IDictionary)WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out var nt); Assert.AreEqual(bytesNeeded, bytesRead); Assert.AreEqual(Encoding.UTF8.GetBytes("Hello"), nt["string"]); Assert.AreEqual(1234, nt["int"]); @@ -89,7 +89,7 @@ public void TestTableEncoding_S() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out _); Assert.AreEqual(bytesNeeded, bytesRead); Check(bytes, new byte[] { 0,0,0,9, // table length @@ -109,7 +109,7 @@ public void TestTableEncoding_x() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out _); Assert.AreEqual(bytesNeeded, bytesRead); Check(bytes, new byte[] { 0,0,0,9, // table length @@ -152,7 +152,7 @@ public void TestQpidJmsTypes() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - IDictionary nt = (IDictionary)WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out var nt); Assert.AreEqual(bytesNeeded, bytesRead); 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"]); diff --git a/projects/Unit/TestFieldTableFormattingGeneric.cs b/projects/Unit/TestFieldTableFormattingGeneric.cs index 8bd18030b7..b735db78df 100644 --- a/projects/Unit/TestFieldTableFormattingGeneric.cs +++ b/projects/Unit/TestFieldTableFormattingGeneric.cs @@ -66,7 +66,7 @@ public void TestStandardTypes() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - IDictionary nt = WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out var nt); Assert.AreEqual(bytesNeeded, bytesRead); Assert.AreEqual(Encoding.UTF8.GetBytes("Hello"), nt["string"]); Assert.AreEqual(1234, nt["int"]); @@ -90,7 +90,7 @@ public void TestTableEncoding_S() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out _); Assert.AreEqual(bytesNeeded, bytesRead); Check(bytes, new byte[] { 0,0,0,9, // table length @@ -110,7 +110,7 @@ public void TestTableEncoding_x() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out _); Assert.AreEqual(bytesNeeded, bytesRead); Check(bytes, new byte[] { 0,0,0,9, // table length @@ -139,7 +139,7 @@ public void TestQpidJmsTypes() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] bytes = new byte[bytesNeeded]; WireFormatting.WriteTable(bytes, t); - IDictionary nt = (IDictionary)WireFormatting.ReadTable(bytes, out int bytesRead); + int bytesRead = WireFormatting.ReadDictionary(bytes, out var nt); Assert.AreEqual(bytesNeeded, bytesRead); 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"]); diff --git a/projects/Unit/TestMethodArgumentCodec.cs b/projects/Unit/TestMethodArgumentCodec.cs index a424199b4b..6ed3c40227 100644 --- a/projects/Unit/TestMethodArgumentCodec.cs +++ b/projects/Unit/TestMethodArgumentCodec.cs @@ -41,18 +41,8 @@ namespace RabbitMQ.Client.Unit { [TestFixture] - class TestMethodArgumentCodec + public class TestMethodArgumentCodec { - public static MethodArgumentWriter Writer() - { - return new MethodArgumentWriter(new byte[1024]); - } - - public static MethodArgumentReader Reader(byte[] bytes) - { - return new MethodArgumentReader(bytes); - } - public void Check(byte[] actual, byte[] expected) { try @@ -81,9 +71,8 @@ public void TestTableLengthWrite() int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] memory = new byte[bytesNeeded]; - var writer = new MethodArgumentWriter(memory); - writer.WriteTable(t); - Assert.AreEqual(bytesNeeded, writer.Offset); + int offset = WireFormatting.WriteTable(memory.AsSpan(), t); + Assert.AreEqual(bytesNeeded, offset); Check(memory, new byte[] { 0x00, 0x00, 0x00, 0x0C, 0x03, 0x61, 0x62, 0x63, 0x53, 0x00, 0x00, 0x00, @@ -91,12 +80,13 @@ public void TestTableLengthWrite() } [Test] - public void TestTableLengthRead() + public void TestDictionaryLengthRead() { - IDictionary t = (IDictionary)Reader(new byte[] { 0x00, 0x00, 0x00, 0x0C, - 0x03, 0x61, 0x62, 0x63, - 0x53, 0x00, 0x00, 0x00, - 0x03, 0x64, 0x65, 0x66 }).ReadTable(); + WireFormatting.ReadDictionary(new byte[] { + 0x00, 0x00, 0x00, 0x0C, + 0x03, 0x61, 0x62, 0x63, + 0x53, 0x00, 0x00, 0x00, + 0x03, 0x64, 0x65, 0x66 }, out var t); Assert.AreEqual(Encoding.UTF8.GetBytes("def"), t["abc"]); Assert.AreEqual(1, t.Count); } @@ -112,9 +102,8 @@ public void TestNestedTableWrite() t["x"] = x; int bytesNeeded = WireFormatting.GetTableByteCount(t); byte[] memory = new byte[bytesNeeded]; - var writer = new MethodArgumentWriter(memory); - writer.WriteTable(t); - Assert.AreEqual(bytesNeeded, writer.Offset); + int offset = WireFormatting.WriteTable(memory.AsSpan(), t); + Assert.AreEqual(bytesNeeded, offset); Check(memory, new byte[] { 0x00, 0x00, 0x00, 0x0E, 0x01, 0x78, 0x46, 0x00, 0x00, 0x00, 0x07, 0x01,