Skip to content

Commit b15949c

Browse files
committed
guid and list serialization methods
1 parent d766fc0 commit b15949c

6 files changed

Lines changed: 461 additions & 63 deletions

File tree

samples/SpaceWar.Shared/Logic/GameState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void LoadState(ref readonly BinaryBufferReader reader)
4949
{
5050
Bounds = reader.ReadRectangle();
5151
FrameNumber = reader.ReadInt32();
52-
reader.Read(Ships);
52+
reader.Read(in Ships);
5353
}
5454

5555
static GameInput GetShipAI(in Ship ship) => new(

src/Backdash/Serialization/BinaryBufferReader.cs

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,18 @@ public void ReadByte(in Span<byte> values)
7171
slice.CopyTo(values[..length]);
7272
}
7373

74+
/// <summary>Reads a list of <see cref="byte"/> from buffer into <paramref name="values"/>.</summary>
75+
public void ReadByte(in List<byte> values) => ReadByte(GetListSpan(values));
76+
7477
/// <summary>Reads single <see cref="sbyte"/> from buffer.</summary>
7578
public sbyte ReadSByte() => unchecked((sbyte)buffer[offset++]);
7679

7780
/// <summary>Reads a span of <see cref="sbyte"/> from buffer into <paramref name="values"/>.</summary>
7881
public void ReadSByte(in Span<sbyte> values) => ReadSpan(values);
7982

83+
/// <summary>Reads a list of <see cref="sbyte"/> from buffer into <paramref name="values"/>.</summary>
84+
public void ReadSByte(in List<sbyte> values) => ReadSByte(GetListSpan(values));
85+
8086
/// <summary>Reads single <see cref="bool"/> from buffer.</summary>
8187
public bool ReadBoolean()
8288
{
@@ -88,6 +94,9 @@ public bool ReadBoolean()
8894
/// <summary>Reads a span of <see cref="bool"/> from buffer into <paramref name="values"/>.</summary>
8995
public void ReadBoolean(in Span<bool> values) => ReadSpan(values);
9096

97+
/// <summary>Reads a list of <see cref="bool"/> from buffer into <paramref name="values"/>.</summary>
98+
public void ReadBoolean(in List<bool> values) => ReadBoolean(GetListSpan(values));
99+
91100
/// <summary>Reads single <see cref="short"/> from buffer.</summary>
92101
public short ReadInt16() => ReadNumber<short>(false);
93102

@@ -99,6 +108,9 @@ public void ReadInt16(in Span<short> values)
99108
BinaryPrimitives.ReverseEndianness(values, values);
100109
}
101110

111+
/// <summary>Reads a list of <see cref="short"/> from buffer into <paramref name="values"/>.</summary>
112+
public void ReadInt16(in List<short> values) => ReadInt16(GetListSpan(values));
113+
102114
/// <summary>Reads single <see cref="ushort"/> from buffer.</summary>
103115
public ushort ReadUInt16() => ReadNumber<ushort>(true);
104116

@@ -110,6 +122,9 @@ public void ReadUInt16(in Span<ushort> values)
110122
BinaryPrimitives.ReverseEndianness(values, values);
111123
}
112124

125+
/// <summary>Reads a list of <see cref="ushort"/> from buffer into <paramref name="values"/>.</summary>
126+
public void ReadUInt16(in List<ushort> values) => ReadUInt16(GetListSpan(values));
127+
113128
/// <summary>Reads single <see cref="char"/> from buffer.</summary>
114129
public char ReadChar() => (char)ReadUInt16();
115130

@@ -124,6 +139,9 @@ public void ReadChar(in Span<char> values)
124139
}
125140
}
126141

142+
/// <summary>Reads a list of <see cref="char"/> from buffer into <paramref name="values"/>.</summary>
143+
public void ReadChar(in List<char> values) => ReadChar(GetListSpan(values));
144+
127145
/// <summary>Reads single <see cref="char"/> from buffer.</summary>
128146
public char ReadUtf8Char()
129147
{
@@ -132,14 +150,17 @@ public char ReadUtf8Char()
132150
return result[0];
133151
}
134152

135-
/// <summary>Reads a span of <see cref="char"/> from buffer into <paramref name="values"/>.</summary>
153+
/// <summary>Reads a span of UTF8 <see cref="char"/> from buffer into <paramref name="values"/>.</summary>
136154
public void ReadUtf8String(in Span<char> values)
137155
{
138156
var byteCount = System.Text.Encoding.UTF8.GetByteCount(values);
139157
System.Text.Encoding.UTF8.GetChars(CurrentBuffer[..byteCount], values);
140158
Advance(byteCount);
141159
}
142160

161+
/// <summary>Reads a list of UTF8 <see cref="char"/> from buffer into <paramref name="values"/>.</summary>
162+
public void ReadUtf8String(in List<char> values) => ReadUtf8String(GetListSpan(values));
163+
143164
/// <summary>Reads single <see cref="int"/> from buffer.</summary>
144165
public int ReadInt32() => ReadNumber<int>(false);
145166

@@ -151,6 +172,9 @@ public void ReadInt32(in Span<int> values)
151172
BinaryPrimitives.ReverseEndianness(values, values);
152173
}
153174

175+
/// <summary>Reads a list of <see cref="int"/> from buffer into <paramref name="values"/>.</summary>
176+
public void ReadInt32(in List<int> values) => ReadInt32(GetListSpan(values));
177+
154178
/// <summary>Reads single <see cref="uint"/> from buffer.</summary>
155179
public uint ReadUInt32() => ReadNumber<uint>(true);
156180

@@ -162,6 +186,9 @@ public void ReadUInt32(in Span<uint> values)
162186
BinaryPrimitives.ReverseEndianness(values, values);
163187
}
164188

189+
/// <summary>Reads a list of <see cref="uint"/> from buffer into <paramref name="values"/>.</summary>
190+
public void ReadUInt32(in List<uint> values) => ReadUInt32(GetListSpan(values));
191+
165192
/// <summary>Reads single <see cref="long"/> from buffer.</summary>
166193
public long ReadInt64() => ReadNumber<long>(false);
167194

@@ -173,6 +200,9 @@ public void ReadInt64(in Span<long> values)
173200
BinaryPrimitives.ReverseEndianness(values, values);
174201
}
175202

203+
/// <summary>Reads a list of <see cref="long"/> from buffer into <paramref name="values"/>.</summary>
204+
public void ReadInt64(in List<long> values) => ReadInt64(GetListSpan(values));
205+
176206
/// <summary>Reads single <see cref="ulong"/> from buffer.</summary>
177207
public ulong ReadUInt64() => ReadNumber<ulong>(true);
178208

@@ -184,6 +214,9 @@ public void ReadUInt64(in Span<ulong> values)
184214
BinaryPrimitives.ReverseEndianness(values, values);
185215
}
186216

217+
/// <summary>Reads a list of <see cref="ulong"/> from buffer into <paramref name="values"/>.</summary>
218+
public void ReadUInt64(in List<ulong> values) => ReadUInt64(GetListSpan(values));
219+
187220
/// <summary>Reads single <see cref="Int128"/> from buffer.</summary>
188221
public Int128 ReadInt128() => ReadNumber<Int128>(false);
189222

@@ -195,6 +228,9 @@ public void ReadInt128(in Span<Int128> values)
195228
BinaryPrimitives.ReverseEndianness(values, values);
196229
}
197230

231+
/// <summary>Reads a list of <see cref="Int128"/> from buffer into <paramref name="values"/>.</summary>
232+
public void ReadInt128(in List<Int128> values) => ReadInt128(GetListSpan(values));
233+
198234
/// <summary>Reads single <see cref="UInt128"/> from buffer.</summary>
199235
public UInt128 ReadUInt128() => ReadNumber<UInt128>(true);
200236

@@ -206,6 +242,9 @@ public void ReadUInt128(in Span<UInt128> values)
206242
BinaryPrimitives.ReverseEndianness(values, values);
207243
}
208244

245+
/// <summary>Reads a list of <see cref="UInt128"/> from buffer into <paramref name="values"/>.</summary>
246+
public void ReadUInt128(in List<UInt128> values) => ReadUInt128(GetListSpan(values));
247+
209248
/// <summary>Reads single <see cref="Half"/> from buffer.</summary>
210249
public Half ReadHalf() => BitConverter.Int16BitsToHalf(ReadInt16());
211250

@@ -219,6 +258,32 @@ public void ReadUInt128(in Span<UInt128> values)
219258
/// <summary>Reads single <see cref="double"/> from buffer.</summary>
220259
public double ReadDouble() => BitConverter.Int64BitsToDouble(ReadInt64());
221260

261+
/// <summary>Reads single <see cref="Guid"/> from buffer.</summary>
262+
public Guid ReadGuid()
263+
{
264+
var span = CurrentBuffer[..Unsafe.SizeOf<Guid>()];
265+
var result = new Guid(span, Endianness is Endianness.BigEndian);
266+
Advance(span.Length);
267+
return result;
268+
}
269+
270+
/// <summary>Reads a span of <see cref="Guid"/> from buffer into <paramref name="values"/>.</summary>
271+
public void ReadGuid(in Span<Guid> values)
272+
{
273+
if (values.IsEmpty) return;
274+
ref var current = ref MemoryMarshal.GetReference(values);
275+
ref var limit = ref Unsafe.Add(ref current, values.Length);
276+
277+
while (Unsafe.IsAddressLessThan(ref current, ref limit))
278+
{
279+
current = ReadGuid();
280+
current = ref Unsafe.Add(ref current, 1)!;
281+
}
282+
}
283+
284+
/// <summary>Reads a list of <see cref="Guid"/> from buffer into <paramref name="values"/>.</summary>
285+
public void ReadGuid(in List<Guid> values) => ReadGuid(GetListSpan(values));
286+
222287
/// <summary>Reads an unmanaged struct from buffer.</summary>
223288
public void ReadStruct<T>(ref T value) where T : unmanaged
224289
{
@@ -239,8 +304,11 @@ public T ReadStruct<T>() where T : unmanaged
239304
return result;
240305
}
241306

307+
/// <summary>Reads an unmanaged struct list from buffer.</summary>
308+
public void ReadStruct<T>(in List<T> values) where T : unmanaged =>
309+
ReadStruct(GetListSpan(in values));
242310

243-
/// <summary>Reads an unmanaged struct from buffer.</summary>
311+
/// <summary>Reads an unmanaged struct span from buffer.</summary>
244312
public void ReadStruct<T>(in Span<T> values) where T : unmanaged =>
245313
ReadByte(MemoryMarshal.AsBytes(values));
246314

@@ -296,15 +364,6 @@ public T ReadNumber<T>(bool isUnsigned) where T : unmanaged, IBinaryInteger<T>
296364
return result;
297365
}
298366

299-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
300-
Span<T> GetListSpan<T>(List<T> values)
301-
{
302-
var count = ReadInt32();
303-
CollectionsMarshal.SetCount(values, count);
304-
var span = CollectionsMarshal.AsSpan(values);
305-
return span;
306-
}
307-
308367
/// <summary>Reads a <see cref="IBinarySerializable"/> <paramref name="value"/> from buffer.</summary>
309368
/// <typeparam name="T">A type that implements <see cref="IBinarySerializable"/>.</typeparam>
310369
public void Read<T>(ref T value) where T : IBinarySerializable => value.Deserialize(in this);
@@ -330,5 +389,14 @@ public void Read<T>(in Span<T> values) where T : IBinarySerializable
330389

331390
/// <summary>Writes an array of <see cref="IBinarySerializable"/> <paramref name="values"/> into buffer.</summary>
332391
/// <typeparam name="T">A type that implements <see cref="IBinarySerializable"/>.</typeparam>
333-
public void Read<T>(in List<T> values) where T : IBinarySerializable => Read(GetListSpan(values));
392+
public void Read<T>(in List<T> values) where T : IBinarySerializable => Read(GetListSpan(in values));
393+
394+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
395+
Span<T> GetListSpan<T>(in List<T> values)
396+
{
397+
var count = ReadInt32();
398+
CollectionsMarshal.SetCount(values, count);
399+
var span = CollectionsMarshal.AsSpan(values);
400+
return span;
401+
}
334402
}

0 commit comments

Comments
 (0)