diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index ee8ba331c5..dc5ccfb5bc 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -9,6 +9,8 @@ Additional documentation and release notes are available at [Multiplayer Documen ## [Unreleased] ### Added +- Added `FastBufferReader(ArraySegment buffer, Allocator copyAllocator)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset and the `ArraySegment.Count` as the `FastBufferReader` length. (#3320) +- Added `FastBufferReader(ArraySegment buffer, Allocator copyAllocator, int length = -1)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset. (#3320) ### Fixed diff --git a/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs b/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs index 67d787fea5..7f87e02240 100644 --- a/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs +++ b/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs @@ -136,10 +136,59 @@ public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocato } fixed (byte* data = buffer.Array) { + Handle = CreateHandle(data, length == -1 ? buffer.Count : length, offset, copyAllocator, Allocator.Temp); } } + /// + /// Create a FastBufferReader from an ArraySegment that uses the ArraySegment.Offset for the reader's offset. + /// + /// A new buffer will be created using the given allocator and the value will be copied in. + /// FastBufferReader will then own the data. + /// + /// Allocator.None is not supported for byte[]. If you need this functionality, use a fixed() block + /// and ensure the FastBufferReader isn't used outside that block. + /// + /// The buffer to copy from + /// 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 + /// The number of bytes to copy (all if this is -1) + public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocator, int length = -1) + { + if (copyAllocator == Allocator.None) + { + throw new NotSupportedException("Allocator.None cannot be used with managed source buffers."); + } + fixed (byte* data = buffer.Array) + { + + Handle = CreateHandle(data, length == -1 ? buffer.Count : length, buffer.Offset, copyAllocator, Allocator.Temp); + } + } + + /// + /// Create a FastBufferReader from an ArraySegment that uses the ArraySegment.Offset for the reader's offset and the ArraySegment.Count for the reader's length. + /// + /// A new buffer will be created using the given allocator and the value will be copied in. + /// FastBufferReader will then own the data. + /// + /// Allocator.None is not supported for byte[]. If you need this functionality, use a fixed() block + /// and ensure the FastBufferReader isn't used outside that block. + /// + /// The buffer to copy from + /// 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 + public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocator) + { + if (copyAllocator == Allocator.None) + { + throw new NotSupportedException("Allocator.None cannot be used with managed source buffers."); + } + fixed (byte* data = buffer.Array) + { + Handle = CreateHandle(data, buffer.Count, buffer.Offset, copyAllocator, Allocator.Temp); + } + } + /// /// Create a FastBufferReader from an existing byte array. /// diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs index 2b4c70ebcb..17d0c979d9 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs @@ -1579,5 +1579,21 @@ public unsafe void WhenCallingTryBeginReadInternal_AllowedReadPositionDoesNotMov Assert.AreEqual(reader.Handle->AllowedReadMark, 25); } } + + [Test] + public unsafe void WhenUsingArraySegment_ConstructorHonorsArraySegmentConfiguration() + { + var bytes = new byte[] { 0, 1, 2, 3 }; + var segment = new ArraySegment(bytes, 1, 3); + var reader = new FastBufferReader(segment, Allocator.Temp); + + var readerArray = reader.ToArray(); + Assert.True(readerArray.Length == bytes.Length - 1, $"Array of reader should have a length of {bytes.Length - 1} but was {readerArray.Length}!"); + for (int i = 0; i < readerArray.Length; i++) + { + Assert.True(bytes[i + 1] == readerArray[i], $"Value of {nameof(readerArray)} at index {i} is {readerArray[i]} but should be {bytes[i + 1]}!"); + } + reader.Dispose(); + } } } diff --git a/pvpExceptions.json b/pvpExceptions.json index bab6a87515..4deefeeb86 100644 --- a/pvpExceptions.json +++ b/pvpExceptions.json @@ -731,6 +731,7 @@ "Unity.Netcode.EditorTests.FastBufferReaderTests: void WhenCallingTryBeginRead_TheAllowedReadPositionIsMarkedRelativeToCurrentPosition(): undocumented", "Unity.Netcode.EditorTests.FastBufferReaderTests: void WhenReadingAfterSeeking_TheNewReadComesFromTheCorrectPosition(): undocumented", "Unity.Netcode.EditorTests.FastBufferReaderTests: void WhenCallingTryBeginReadInternal_AllowedReadPositionDoesNotMoveBackward(): undocumented", + "Unity.Netcode.EditorTests.FastBufferReaderTests: void WhenUsingArraySegment_ConstructorHonorsArraySegmentConfiguration(): undocumented", "Unity.Netcode.EditorTests.FastBufferWriterTests: undocumented", "Unity.Netcode.EditorTests.FastBufferWriterTests: void RunTypeTest(T): undocumented", "Unity.Netcode.EditorTests.FastBufferWriterTests: void RunTypeTestSafe(T): undocumented",