namespace Tinesware.Enumerables { using System; using System.Collections.Generic; using System.IO; using System.Linq; using Should.Fluent; /// <summary> /// More extension methods for enumerables /// </summary> public static class Chunk { /// <summary> /// Split an IEnumerable<T> into an IEnumerable<T[]> /// </summary> /// <typeparam name="T">Element type of the array</typeparam> /// <param name="source">The IEnumerable to operate on</param> /// <param name="chunk">The window size</param> /// <returns>The enumeration</returns> public static IEnumerable<T[]> Window<T>(this IEnumerable<T> source, int chunk) { while (true) { var result = source.Take(chunk).ToArray(); if (result.Any()) { yield return result; } else { break; } } } /// <summary> /// Turns a stream into an IEnumerable<byte> /// </summary> /// <param name="stream">The stream to wrap</param> /// <returns>The stream as an enumeration</returns> public static IEnumerable<byte> ToEnumerable(this Stream stream) { while (true) { var result = stream.ReadByte(); if (result >= 0) { yield return (byte)result; } else { break; } } } /// <summary> /// A Self-test program /// </summary> private static void Main() { var input = Enumerable.Range(0, 42).Select(x => (byte)x).ToArray(); var inStream = new MemoryStream(input); var channel = inStream.ToEnumerable(); var chunk = channel.Take(16).ToArray(); chunk.Length.Should().Equal(16); chunk[0].Should().Equal((byte)0); chunk = channel.Take(16).ToArray(); chunk.Length.Should().Equal(16); chunk[0].Should().Equal((byte)16); chunk = channel.Take(16).ToArray(); chunk.Length.Should().Equal(10); chunk[0].Should().Equal((byte)32); inStream.Position = 0; var chunks = inStream.ToEnumerable().Window(16).ToArray(); chunks.Length.Should().Equal(3); chunks[0].Length.Should().Equal(16); chunks[1].Length.Should().Equal(16); chunks[2].Length.Should().Equal(10); } } }