diff --git a/csharp/sbe-dll/DirectBuffer.cs b/csharp/sbe-dll/DirectBuffer.cs index 52b78ea4af..09eb64ec7e 100644 --- a/csharp/sbe-dll/DirectBuffer.cs +++ b/csharp/sbe-dll/DirectBuffer.cs @@ -64,6 +64,25 @@ public DirectBuffer(byte* pBuffer, int bufferLength, BufferOverflowDelegate buff Wrap(pBuffer, bufferLength); } + /// + /// Attach a view to a buffer owned by external code + /// + /// byte buffer + public DirectBuffer(ArraySegment buffer) : this(buffer, null) + { + } + + /// + /// Attach a view to a buffer owned by external code + /// + /// byte buffer + /// delegate to allow reallocation of buffer + public DirectBuffer(ArraySegment buffer, BufferOverflowDelegate bufferOverflow) + { + this.bufferOverflow = bufferOverflow; + Wrap(buffer); + } + /// /// Creates a DirectBuffer that can later be wrapped /// @@ -114,6 +133,24 @@ public void Wrap(byte* pBuffer, int bufferLength) _needToFreeGCHandle = false; } + /// + /// Recycles an existing from a byte buffer owned by external code + /// + /// buffer of bytes + public void Wrap(ArraySegment buffer) + { + if (buffer == null) throw new ArgumentNullException(nameof(buffer)); + + FreeGCHandle(); + + // pin the buffer so it does not get moved around by GC, this is required since we use pointers + _pinnedGCHandle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned); + _needToFreeGCHandle = true; + + _pBuffer = ((byte*)_pinnedGCHandle.AddrOfPinnedObject().ToPointer()) + buffer.Offset; + _capacity = buffer.Count; + } + /// /// Capacity of the underlying buffer /// diff --git a/csharp/sbe-tests/DirectBufferTests.cs b/csharp/sbe-tests/DirectBufferTests.cs index 2ac82e4e07..4c37ebe1f0 100644 --- a/csharp/sbe-tests/DirectBufferTests.cs +++ b/csharp/sbe-tests/DirectBufferTests.cs @@ -66,6 +66,40 @@ public void ConstructFromNativeBuffer() } } + [TestMethod] + public void ConstructFromByteArray() + { + var buffer = new byte[16]; + + const int value = 5; + const int index = 0; + + using (var directBuffer = new DirectBuffer(buffer)) + { + directBuffer.Int64PutLittleEndian(index, value); + Assert.AreEqual(value, buffer[index]); + } + } + + [TestMethod] + public void ConstructFromArraySegment() + { + const int value = 5; + const int index = 0; + const int offset = 512; + const int size = 1024; + + var bigBuffer = new byte[size]; + var buffer = new ArraySegment(bigBuffer, offset, size - offset); + + using (var directBuffer = new DirectBuffer(buffer)) + { + directBuffer.Int64PutLittleEndian(index, value); + Assert.AreEqual(value, bigBuffer[offset + index]); + Assert.AreEqual(value, buffer.AsSpan()[index]); + } + } + [TestMethod] public void Recycle() {