Skip to content

Commit 4c34f6c

Browse files
committed
simplify reader / writer bit handling / span usage
1 parent 7717d31 commit 4c34f6c

10 files changed

+262
-245
lines changed

projects/Apigen/apigen/Apigen.cs

+20-1
Original file line numberDiff line numberDiff line change
@@ -855,9 +855,28 @@ public void EmitClassMethodImplementations(AmqpClass c)
855855
EmitLine("");
856856
EmitLine(" public override void WriteArgumentsTo(ref Client.Impl.MethodArgumentWriter writer)");
857857
EmitLine(" {");
858+
var lastWasBitClass = false;
858859
foreach (AmqpField f in m.m_Fields)
859860
{
860-
EmitLine($" writer.Write{MangleClass(ResolveDomain(f.Domain))}(_{MangleMethod(f.Name)});");
861+
string mangleClass = MangleClass(ResolveDomain(f.Domain));
862+
if (mangleClass != "Bit")
863+
{
864+
if (lastWasBitClass)
865+
{
866+
EmitLine($" writer.EndBits();");
867+
lastWasBitClass = false;
868+
}
869+
}
870+
else
871+
{
872+
lastWasBitClass = true;
873+
}
874+
875+
EmitLine($" writer.Write{mangleClass}(_{MangleMethod(f.Name)});");
876+
}
877+
if (lastWasBitClass)
878+
{
879+
EmitLine($" writer.EndBits();");
861880
}
862881
EmitLine(" }");
863882
EmitLine("");

projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyReader.cs

+39-35
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,30 @@
4545

4646
namespace RabbitMQ.Client.Impl
4747
{
48-
internal struct ContentHeaderPropertyReader
48+
internal ref struct ContentHeaderPropertyReader
4949
{
50-
private ushort m_bitCount;
51-
private ushort m_flagWord;
52-
private int _memoryOffset;
50+
private const int StartBitMask = 0b1000_0000_0000_0000;
51+
private const int EndBitMask = 0b0000_0000_0000_0001;
52+
5353
private readonly ReadOnlyMemory<byte> _memory;
54+
private readonly ReadOnlySpan<byte> _span;
55+
private int _offset;
56+
private int _bitMask;
57+
private int _bits;
58+
59+
private ReadOnlySpan<byte> Span => _span.Slice(_offset);
60+
private ReadOnlyMemory<byte> Memory => _memory.Slice(_offset);
5461

5562
public ContentHeaderPropertyReader(ReadOnlyMemory<byte> memory)
5663
{
5764
_memory = memory;
58-
_memoryOffset = 0;
59-
m_flagWord = 1; // just the continuation bit
60-
m_bitCount = 15; // the correct position to force a m_flagWord read
65+
_span = memory.Span;
66+
_offset = 0;
67+
_bitMask = EndBitMask; // force a flag read
68+
_bits = 1; // just the continuation bit
6169
}
6270

63-
public bool ContinuationBitSet
64-
{
65-
get { return (m_flagWord & 1) != 0; }
66-
}
71+
private bool ContinuationBitSet => (_bits & EndBitMask) != 0;
6772

6873
public void FinishPresence()
6974
{
@@ -78,82 +83,81 @@ public bool ReadBit()
7883
return ReadPresence();
7984
}
8085

81-
public void ReadFlagWord()
86+
private void ReadBits()
8287
{
8388
if (!ContinuationBitSet)
8489
{
8590
throw new MalformedFrameException("Attempted to read flag word when none advertised");
8691
}
87-
m_flagWord = NetworkOrderDeserializer.ReadUInt16(_memory.Slice(_memoryOffset).Span);
88-
_memoryOffset += 2;
89-
m_bitCount = 0;
92+
_bits = NetworkOrderDeserializer.ReadUInt16(Span);
93+
_offset += 2;
94+
_bitMask = StartBitMask;
9095
}
9196

9297
public uint ReadLong()
9398
{
94-
uint result = NetworkOrderDeserializer.ReadUInt32(_memory.Slice(_memoryOffset).Span);
95-
_memoryOffset += 4;
99+
uint result = NetworkOrderDeserializer.ReadUInt32(Span);
100+
_offset += 4;
96101
return result;
97102
}
98103

99104
public ulong ReadLonglong()
100105
{
101-
ulong result = NetworkOrderDeserializer.ReadUInt64(_memory.Slice(_memoryOffset).Span);
102-
_memoryOffset += 8;
106+
ulong result = NetworkOrderDeserializer.ReadUInt64(Span);
107+
_offset += 8;
103108
return result;
104109
}
105110

106111
public byte[] ReadLongstr()
107112
{
108-
byte[] result = WireFormatting.ReadLongstr(_memory.Slice(_memoryOffset));
109-
_memoryOffset += 4 + result.Length;
113+
byte[] result = WireFormatting.ReadLongstr(Span);
114+
_offset += 4 + result.Length;
110115
return result;
111116
}
112117

113118
public byte ReadOctet()
114119
{
115-
return _memory.Span[_memoryOffset++];
120+
return _span[_offset++];
116121
}
117122

118123
public bool ReadPresence()
119124
{
120-
if (m_bitCount == 15)
125+
if (_bitMask == EndBitMask)
121126
{
122-
ReadFlagWord();
127+
ReadBits();
123128
}
124129

125-
int bit = 15 - m_bitCount;
126-
bool result = (m_flagWord & (1 << bit)) != 0;
127-
m_bitCount++;
130+
bool result = (_bits & _bitMask) != 0;
131+
_bitMask >>= 1;
128132
return result;
129133
}
130134

131135
public ushort ReadShort()
132136
{
133-
ushort result = NetworkOrderDeserializer.ReadUInt16(_memory.Slice(_memoryOffset).Span);
134-
_memoryOffset += 2;
137+
ushort result = NetworkOrderDeserializer.ReadUInt16(Span);
138+
_offset += 2;
135139
return result;
136140
}
137141

138142
public string ReadShortstr()
139143
{
140-
string result = WireFormatting.ReadShortstr(_memory.Slice(_memoryOffset), out int bytesRead);
141-
_memoryOffset += bytesRead;
144+
string result = WireFormatting.ReadShortstr(Memory, out int bytesRead);
145+
_offset += bytesRead;
142146
return result;
143147
}
144148

145149
/// <returns>A type of <seealso cref="System.Collections.Generic.IDictionary{TKey,TValue}"/>.</returns>
146150
public Dictionary<string, object> ReadTable()
147151
{
148-
Dictionary<string, object> result = WireFormatting.ReadTable(_memory.Slice(_memoryOffset), out int bytesRead);
149-
_memoryOffset += bytesRead;
152+
Dictionary<string, object> result = WireFormatting.ReadTable(Memory, out int bytesRead);
153+
_offset += bytesRead;
150154
return result;
151155
}
152156

153157
public AmqpTimestamp ReadTimestamp()
154158
{
155-
AmqpTimestamp result = WireFormatting.ReadTimestamp(_memory.Slice(_memoryOffset));
156-
_memoryOffset += 8;
159+
AmqpTimestamp result = WireFormatting.ReadTimestamp(Span);
160+
_offset += 8;
157161
return result;
158162
}
159163
}

projects/RabbitMQ.Client/client/impl/ContentHeaderPropertyWriter.cs

+44-32
Original file line numberDiff line numberDiff line change
@@ -45,92 +45,104 @@
4545

4646
namespace RabbitMQ.Client.Impl
4747
{
48-
struct ContentHeaderPropertyWriter
48+
internal ref struct ContentHeaderPropertyWriter
4949
{
50-
private int _bitCount;
51-
private ushort _flagWord;
52-
public int Offset { get; private set; }
53-
public Memory<byte> Memory { get; private set; }
50+
private const ushort StartBitMask = 0b1000_0000_0000_0000;
51+
private const ushort EndBitMask = 0b0000_0000_0000_0001;
52+
53+
private readonly Memory<byte> _memory;
54+
private readonly Span<byte> _span;
55+
private int _offset;
56+
private ushort _bitAccumulator;
57+
private ushort _bitMask;
58+
59+
public int Offset => _offset;
60+
61+
private Span<byte> Span => _span.Slice(_offset);
62+
private Memory<byte> Memory => _memory.Slice(_offset);
5463

5564
public ContentHeaderPropertyWriter(Memory<byte> memory)
5665
{
57-
Memory = memory;
58-
_flagWord = 0;
59-
_bitCount = 0;
60-
Offset = 0;
66+
_memory = memory;
67+
_span = _memory.Span;
68+
_offset = 0;
69+
_bitAccumulator = 0;
70+
_bitMask = StartBitMask;
6171
}
6272

6373
public void FinishPresence()
6474
{
65-
EmitFlagWord(false);
75+
WriteBits();
6676
}
6777

6878
public void WriteBit(bool bit)
6979
{
7080
WritePresence(bit);
7181
}
72-
82+
7383
public void WriteLong(uint val)
7484
{
75-
Offset += WireFormatting.WriteLong(Memory.Slice(Offset), val);
85+
_offset += WireFormatting.WriteLong(Span, val);
7686
}
7787

7888
public void WriteLonglong(ulong val)
7989
{
80-
Offset += WireFormatting.WriteLonglong(Memory.Slice(Offset), val);
90+
_offset += WireFormatting.WriteLonglong(Span, val);
8191
}
8292

8393
public void WriteLongstr(byte[] val)
8494
{
85-
Offset += WireFormatting.WriteLongstr(Memory.Slice(Offset), val);
95+
_offset += WireFormatting.WriteLongstr(Span, val);
8696
}
8797

8898
public void WriteOctet(byte val)
8999
{
90-
Memory.Slice(Offset++).Span[0] = val;
100+
_span[_offset++] = val;
91101
}
92-
102+
93103
public void WritePresence(bool present)
94104
{
95-
if (_bitCount == 15)
105+
if (_bitMask == EndBitMask)
96106
{
97-
EmitFlagWord(true);
107+
// Mark continuation
108+
_bitAccumulator |= _bitMask;
109+
WriteBits();
98110
}
99111

100112
if (present)
101113
{
102-
int bit = 15 - _bitCount;
103-
_flagWord = (ushort)(_flagWord | (1 << bit));
114+
_bitAccumulator |= _bitMask;
104115
}
105-
_bitCount++;
106-
}
107116

117+
_bitMask >>= 1;
118+
}
119+
108120
public void WriteShort(ushort val)
109121
{
110-
Offset += WireFormatting.WriteShort(Memory.Slice(Offset), val);
122+
_offset += WireFormatting.WriteShort(Span, val);
111123
}
112124

113125
public void WriteShortstr(string val)
114126
{
115-
Offset += WireFormatting.WriteShortstr(Memory.Slice(Offset), val);
127+
_offset += WireFormatting.WriteShortstr(Memory, val);
116128
}
117129

118130
public void WriteTable(IDictionary<string, object> val)
119131
{
120-
Offset += WireFormatting.WriteTable(Memory.Slice(Offset), val);
132+
_offset += WireFormatting.WriteTable(Memory, val);
121133
}
122134

123135
public void WriteTimestamp(AmqpTimestamp val)
124136
{
125-
Offset += WireFormatting.WriteTimestamp(Memory.Slice(Offset), val);
137+
_offset += WireFormatting.WriteTimestamp(Span, val);
126138
}
127-
128-
private void EmitFlagWord(bool continuationBit)
139+
140+
private void WriteBits()
129141
{
130-
NetworkOrderSerializer.WriteUInt16(Memory.Slice(Offset).Span, (ushort)(continuationBit ? (_flagWord | 1) : _flagWord));
131-
Offset += 2;
132-
_flagWord = 0;
133-
_bitCount = 0;
142+
NetworkOrderSerializer.WriteUInt16(Span, _bitAccumulator);
143+
_offset += 2;
144+
_bitMask = StartBitMask;
145+
_bitAccumulator = 0;
134146
}
135147
}
136148
}

projects/RabbitMQ.Client/client/impl/Frame.cs

-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ internal override int WritePayload(Memory<byte> memory)
119119
NetworkOrderSerializer.WriteUInt16(span.Slice(2), _method.ProtocolMethodId);
120120
var argWriter = new MethodArgumentWriter(memory.Slice(4));
121121
_method.WriteArgumentsTo(ref argWriter);
122-
argWriter.Flush();
123122
return 4 + argWriter.Offset;
124123
}
125124
}

0 commit comments

Comments
 (0)