Created
March 31, 2022 16:54
-
-
Save StephenCleary/70a1996fd390d8db5685ca0011d65cfb to your computer and use it in GitHub Desktop.
Buffer sequence helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/dotnet/runtime/issues/27869#issuecomment-475356398 | |
public static class MemoryOwnerSliceExtensions | |
{ | |
public static IMemoryOwner<T> Slice<T>(this IMemoryOwner<T> owner, int start, int length) | |
{ | |
if (start == 0 && length == owner.Memory.Length) | |
return owner; | |
return new SliceOwner<T>(owner, start, length); | |
} | |
public static IMemoryOwner<T> Slice<T>(this IMemoryOwner<T> owner, int start) | |
{ | |
if (start == 0) | |
return owner; | |
return new SliceOwner<T>(owner, start); | |
} | |
private sealed class SliceOwner<T> : IMemoryOwner<T> | |
{ | |
private readonly IMemoryOwner<T> _owner; | |
public Memory<T> Memory { get; } | |
public SliceOwner(IMemoryOwner<T> owner, int start, int length) | |
{ | |
_owner = owner; | |
Memory = _owner.Memory.Slice(start, length); | |
} | |
public SliceOwner(IMemoryOwner<T> owner, int start) | |
{ | |
_owner = owner; | |
Memory = _owner.Memory[start..]; | |
} | |
public void Dispose() => _owner.Dispose(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class MemorySequence<T> | |
{ | |
private MemorySegment? _head; | |
private MemorySegment? _tail; | |
public MemorySequence<T> Append(ReadOnlyMemory<T> buffer) | |
{ | |
if (_tail == null) | |
_head = _tail = new MemorySegment(buffer, runningIndex: 0); | |
else | |
_tail = _tail.Append(buffer); | |
return this; | |
} | |
public ReadOnlySequence<T> ReadOnlySequence => CreateReadOnlySequence(0, _tail?.Memory.Length ?? 0); | |
public ReadOnlySequence<T> CreateReadOnlySequence(int firstBufferStartIndex, int lastBufferEndIndex) => | |
_tail == null ? new ReadOnlySequence<T>(Array.Empty<T>()) : | |
new ReadOnlySequence<T>(_head!, firstBufferStartIndex, _tail, lastBufferEndIndex); | |
private sealed class MemorySegment : ReadOnlySequenceSegment<T> | |
{ | |
public MemorySegment(ReadOnlyMemory<T> memory, long runningIndex) | |
{ | |
Memory = memory; | |
RunningIndex = runningIndex; | |
} | |
public MemorySegment Append(ReadOnlyMemory<T> nextMemory) | |
{ | |
var next = new MemorySegment(nextMemory, RunningIndex + Memory.Length); | |
Next = next; | |
return next; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class OwnedMemorySequence<T> : IDisposable | |
{ | |
private readonly CollectionDisposable _disposable = new(); | |
private readonly MemorySequence<T> _sequence = new(); | |
public OwnedMemorySequence<T> Append(IMemoryOwner<T> memoryOwner) | |
{ | |
_disposable.Add(memoryOwner); | |
_sequence.Append(memoryOwner.Memory); | |
return this; | |
} | |
public ReadOnlySequence<T> ReadOnlySequence => _sequence.ReadOnlySequence; | |
public ReadOnlySequence<T> CreateReadOnlySequence(int firstBufferStartIndex, int lastBufferEndIndex) => | |
_sequence.CreateReadOnlySequence(firstBufferStartIndex, lastBufferEndIndex); | |
public void Dispose() => _disposable.Dispose(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment