Skip to content

Commit e75921a

Browse files
Merge branch 'develop-3.x.x' into fix/fastbufferwriter-grow-from-zero-up-port
2 parents 017bc9a + 37e00de commit e75921a

3 files changed

Lines changed: 90 additions & 7 deletions

File tree

‎com.unity.netcode.gameobjects/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2525
### Fixed
2626

2727
- Issue where a growable `FastBufferWriter` created with a size of 0 never returned from its first write or `TryBeginWrite` call that needed the buffer to grow. (#4224)
28+
- Issue where a `FastBufferReader` created with an offset and the default length of -1 read past the end of its source. The `ArraySegment<byte>` overload that takes an offset now applies it from the start of the segment. (#4222)
2829
- Issue where a client promoted to session owner could throw an exception when synchronizing a newly joining client. (#4214)
2930
- Issue where `NetworkManager.OnNetCodeDisconnect` was not invoked when a connection closed during a hybrid mode session, only when the session shut down. (#4209)
3031
- Issue where a rejected parent change, for example one made by a client without parenting authority, restored the `NetworkObject`'s parent but left it at the moved position when the change was made with `worldPositionStays` disabled. The original position, rotation and scale are now restored. (#4202)

‎com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ internal unsafe void CommitBitwiseReads(int amount)
9090
return readerHandle;
9191
}
9292

93+
// A copy starts at offset, so -1 copies what follows it. Allocator.None keeps the whole source and starts reading at offset.
94+
private static int ResolveLength(int length, int sourceLength, int offset, Allocator copyAllocator)
95+
{
96+
if (length != -1)
97+
{
98+
return length;
99+
}
100+
return copyAllocator == Allocator.None ? sourceLength : sourceLength - offset;
101+
}
102+
93103
/// <summary>
94104
/// Create a FastBufferReader from a NativeArray.
95105
///
@@ -107,12 +117,12 @@ internal unsafe void CommitBitwiseReads(int amount)
107117
/// </summary>
108118
/// <param name="buffer">The NativeArray to create the reader from</param>
109119
/// <param name="copyAllocator">The allocator type used for internal data when copying an existing buffer if other than Allocator.None is specified, that memory will be owned by this FastBufferReader instance</param>
110-
/// <param name="length">The number of bytes to read from the buffer. If set to -1, the entire buffer length will be used</param>
120+
/// <param name="length">The number of bytes to read from the buffer. If set to -1, every byte from offset to the end of the buffer will be used</param>
111121
/// <param name="offset">The offset into the buffer to start reading from</param>
112122
/// <param name="internalAllocator">The allocator type used for internal data when this reader points directly at a buffer owned by someone else</param>
113123
public unsafe FastBufferReader(NativeArray<byte> buffer, Allocator copyAllocator, int length = -1, int offset = 0, Allocator internalAllocator = Allocator.Temp)
114124
{
115-
Handle = CreateHandle((byte*)buffer.GetUnsafePtr(), length == -1 ? buffer.Length : length, offset, copyAllocator, internalAllocator);
125+
Handle = CreateHandle((byte*)buffer.GetUnsafePtr(), ResolveLength(length, buffer.Length, offset, copyAllocator), offset, copyAllocator, internalAllocator);
116126
}
117127

118128
/// <summary>
@@ -127,7 +137,7 @@ public unsafe FastBufferReader(NativeArray<byte> buffer, Allocator copyAllocator
127137
/// <param name="buffer">The buffer to copy from</param>
128138
/// <param name="copyAllocator">The allocator type used for internal data when copying an existing buffer if other than Allocator.None is specified, that memory will be owned by this FastBufferReader instance</param>
129139
/// <param name="length">The number of bytes to copy (all if this is -1)</param>
130-
/// <param name="offset">The offset of the buffer to start copying from</param>
140+
/// <param name="offset">The offset into the segment to start copying from</param>
131141
public unsafe FastBufferReader(ArraySegment<byte> buffer, Allocator copyAllocator, int length = -1, int offset = 0)
132142
{
133143
if (copyAllocator == Allocator.None)
@@ -136,7 +146,7 @@ public unsafe FastBufferReader(ArraySegment<byte> buffer, Allocator copyAllocato
136146
}
137147
fixed (byte* data = buffer.Array)
138148
{
139-
Handle = CreateHandle(data, length == -1 ? buffer.Count : length, offset, copyAllocator, Allocator.Temp);
149+
Handle = CreateHandle(data + buffer.Offset, ResolveLength(length, buffer.Count, offset, copyAllocator), offset, copyAllocator, Allocator.Temp);
140150
}
141151
}
142152

@@ -209,7 +219,7 @@ public unsafe FastBufferReader(byte[] buffer, Allocator copyAllocator, int lengt
209219
}
210220
fixed (byte* data = buffer)
211221
{
212-
Handle = CreateHandle(data, length == -1 ? buffer.Length : length, offset, copyAllocator, Allocator.Temp);
222+
Handle = CreateHandle(data, ResolveLength(length, buffer.Length, offset, copyAllocator), offset, copyAllocator, Allocator.Temp);
213223
}
214224
}
215225

@@ -260,7 +270,7 @@ public unsafe FastBufferReader(byte* buffer, Allocator copyAllocator, int length
260270
/// <param name="internalAllocator">The allocator type used for internal data when this reader points directly at a buffer owned by someone else</param>
261271
public unsafe FastBufferReader(FastBufferWriter writer, Allocator copyAllocator, int length = -1, int offset = 0, Allocator internalAllocator = Allocator.Temp)
262272
{
263-
Handle = CreateHandle(writer.GetUnsafePtr(), length == -1 ? writer.Length : length, offset, copyAllocator, internalAllocator);
273+
Handle = CreateHandle(writer.GetUnsafePtr(), ResolveLength(length, writer.Length, offset, copyAllocator), offset, copyAllocator, internalAllocator);
264274
}
265275

266276
/// <summary>
@@ -285,7 +295,7 @@ public unsafe FastBufferReader(FastBufferWriter writer, Allocator copyAllocator,
285295
/// <param name="internalAllocator">The allocator type used for internal data when this reader points directly at a buffer owned by someone else</param>
286296
public unsafe FastBufferReader(FastBufferReader reader, Allocator copyAllocator, int length = -1, int offset = 0, Allocator internalAllocator = Allocator.Temp)
287297
{
288-
Handle = CreateHandle(reader.GetUnsafePtr(), length == -1 ? reader.Length : length, offset, copyAllocator, internalAllocator);
298+
Handle = CreateHandle(reader.GetUnsafePtr(), ResolveLength(length, reader.Length, offset, copyAllocator), offset, copyAllocator, internalAllocator);
289299
}
290300

291301
/// <summary>

‎com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,78 @@ public void WhenCreatingAReaderFromAnEmptyBuffer_LengthIsZero()
11181118
}
11191119
}
11201120

1121+
private const int k_SourceLength = 10;
1122+
private const int k_ReaderOffset = 2;
1123+
1124+
private static byte[] CreateSequentialBytes()
1125+
{
1126+
var bytes = new byte[k_SourceLength];
1127+
for (var i = 0; i < bytes.Length; ++i)
1128+
{
1129+
bytes[i] = (byte)i;
1130+
}
1131+
return bytes;
1132+
}
1133+
1134+
private static void AssertReadsToEndFrom(FastBufferReader reader, int firstValue)
1135+
{
1136+
var expectedCount = k_SourceLength - firstValue;
1137+
Assert.AreEqual(expectedCount, reader.Length - reader.Position);
1138+
for (var i = 0; i < expectedCount; ++i)
1139+
{
1140+
reader.ReadByteSafe(out byte value);
1141+
Assert.AreEqual((byte)(firstValue + i), value);
1142+
}
1143+
}
1144+
1145+
[Test]
1146+
public void WhenCreatingAReaderFromAnArrayWithAnOffsetAndNoLength_TheRestOfTheArrayIsCopied()
1147+
{
1148+
using var reader = new FastBufferReader(CreateSequentialBytes(), Allocator.Temp, -1, k_ReaderOffset);
1149+
AssertReadsToEndFrom(reader, k_ReaderOffset);
1150+
}
1151+
1152+
[Test]
1153+
public void WhenCreatingAReaderFromAnArraySegmentWithAnOffsetAndNoLength_TheRestOfTheSegmentIsCopied()
1154+
{
1155+
using var reader = new FastBufferReader(new ArraySegment<byte>(CreateSequentialBytes()), Allocator.Temp, -1, k_ReaderOffset);
1156+
AssertReadsToEndFrom(reader, k_ReaderOffset);
1157+
}
1158+
1159+
[Test]
1160+
public void WhenCreatingAReaderFromAnOffsetArraySegmentWithAnOffset_TheOffsetIsRelativeToTheSegment()
1161+
{
1162+
var segmentOffset = 3;
1163+
var segment = new ArraySegment<byte>(CreateSequentialBytes(), segmentOffset, k_SourceLength - segmentOffset);
1164+
using var reader = new FastBufferReader(segment, Allocator.Temp, -1, k_ReaderOffset);
1165+
AssertReadsToEndFrom(reader, segmentOffset + k_ReaderOffset);
1166+
}
1167+
1168+
[Test]
1169+
public void WhenCreatingAReaderFromANativeArrayWithAnOffsetAndNoLength_TheRestOfTheArrayIsRead([Values(Allocator.Temp, Allocator.None)] Allocator copyAllocator)
1170+
{
1171+
using var source = new NativeArray<byte>(CreateSequentialBytes(), Allocator.Temp);
1172+
using var reader = new FastBufferReader(source, copyAllocator, -1, k_ReaderOffset);
1173+
AssertReadsToEndFrom(reader, k_ReaderOffset);
1174+
}
1175+
1176+
[Test]
1177+
public void WhenCreatingAReaderFromAWriterWithAnOffsetAndNoLength_TheRestOfTheWriterIsRead([Values(Allocator.Temp, Allocator.None)] Allocator copyAllocator)
1178+
{
1179+
using var writer = new FastBufferWriter(k_SourceLength, Allocator.Temp);
1180+
writer.WriteBytesSafe(CreateSequentialBytes());
1181+
using var reader = new FastBufferReader(writer, copyAllocator, -1, k_ReaderOffset);
1182+
AssertReadsToEndFrom(reader, k_ReaderOffset);
1183+
}
1184+
1185+
[Test]
1186+
public void WhenCreatingAReaderFromAReaderWithAnOffsetAndNoLength_TheRestOfTheReaderIsRead([Values(Allocator.Temp, Allocator.None)] Allocator copyAllocator)
1187+
{
1188+
using var source = new FastBufferReader(CreateSequentialBytes(), Allocator.Temp);
1189+
using var reader = new FastBufferReader(source, copyAllocator, -1, k_ReaderOffset);
1190+
AssertReadsToEndFrom(reader, k_ReaderOffset);
1191+
}
1192+
11211193
[Test]
11221194
public void WhenCreatingNewFastBufferReader_IsInitializedIsTrue()
11231195
{

0 commit comments

Comments
 (0)