DotNext by Roman Sakno

<PackageReference Include="DotNext" Version="0.14.0" />

 ChunkSequence<T>

Represents sequence of memory chunks.
using System; using System.Buffers; using System.Collections; using System.Collections.Generic; namespace DotNext.Buffers { public readonly struct ChunkSequence<T> : IEnumerable<ReadOnlyMemory<T>>, IEnumerable { public struct Enumerator : IEnumerator<ReadOnlyMemory<T>>, IEnumerator, IDisposable { private readonly ReadOnlyMemory<T> source; private int startIndex; private int length; private readonly int chunkSize; public ReadOnlyMemory<T> Current => source.Slice(startIndex, length); object IEnumerator.Current { get { return Current; } } internal Enumerator(ReadOnlyMemory<T> source, int chunkSize) { this.source = source; this.chunkSize = chunkSize; startIndex = (length = -1); } void IDisposable.Dispose() { this = default(Enumerator); } public bool MoveNext() { if (startIndex == -1) { startIndex = 0; length = Math.Min(chunkSize, source.Length); } else { startIndex += chunkSize; length = Math.Min(source.Length - startIndex, chunkSize); } return startIndex < source.Length; } public void Reset() { startIndex = -1; } } private readonly ReadOnlyMemory<T> memory; private readonly int chunkSize; public ChunkSequence(ReadOnlyMemory<T> memory, int chunkSize) { if (chunkSize < 1) throw new ArgumentOutOfRangeException("chunkSize"); this.chunkSize = chunkSize; this.memory = memory; } public Enumerator GetEnumerator() { return new Enumerator(memory, chunkSize); } IEnumerator<ReadOnlyMemory<T>> IEnumerable<ReadOnlyMemory<T>>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public ReadOnlySequence<T> ToReadOnlySequence() { if (memory.IsEmpty) return default(ReadOnlySequence<T>); if (memory.Length < chunkSize) return new ReadOnlySequence<T>(memory); Chunk<T> first = null; Chunk<T> last = null; using (Enumerator enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { Chunk<T>.AddChunk(enumerator.Current, ref first, ref last); } } return new ReadOnlySequence<T>(first, 0, last, last.Memory.Length); } public static explicit operator ReadOnlySequence<T>(ChunkSequence<T> sequence) { return sequence.ToReadOnlySequence(); } } }