1 /** 2 * A collection of array-backed streams for in-memory reading and writing. 3 */ 4 module streams.types.array; 5 6 /** 7 * An input stream that reads from an array of items. 8 */ 9 struct ArrayInputStream(DataType) { 10 private DataType[] array; 11 private uint currentIndex = 0; 12 13 int read(DataType[] buffer) { 14 if (this.currentIndex >= this.array.length) return 0; 15 uint bufferLength = cast(uint) buffer.length; 16 uint lengthRemaining = cast(uint) this.array.length - this.currentIndex; 17 uint lengthToRead = lengthRemaining < bufferLength ? lengthRemaining : bufferLength; 18 buffer[0 .. lengthToRead] = this.array[this.currentIndex .. this.currentIndex + lengthToRead]; 19 this.currentIndex += lengthToRead; 20 return lengthToRead; 21 } 22 23 void reset() { 24 this.currentIndex = 0; 25 } 26 } 27 28 unittest { 29 import streams.primitives; 30 31 assert(isSomeInputStream!(ArrayInputStream!int)); 32 assert(isInputStream!(ArrayInputStream!ubyte, ubyte)); 33 34 auto s1 = ArrayInputStream!int([1, 2, 3, 4, 5]); 35 int[] buffer = new int[2]; 36 assert(s1.read(buffer) == 2); 37 assert(buffer == [1, 2]); 38 assert(s1.read(buffer) == 2); 39 assert(buffer == [3, 4]); 40 assert(s1.read(buffer) == 1); 41 assert(buffer == [5, 4]); 42 } 43 44 /** 45 * Creates and returns an array input stream wrapped around the given array 46 * of elements. 47 * Params: 48 * array = The array to stream. 49 * Returns: The array input stream. 50 */ 51 ArrayInputStream!T inputStreamFor(T)(T[] array) { 52 return ArrayInputStream!T(array); 53 } 54 55 /** 56 * An output stream that writes to an internal array. The resulting array can 57 * be obtained with `toArray()`. 58 */ 59 struct ArrayOutputStream(DataType) { 60 import std.array : Appender, appender; 61 62 private Appender!(DataType[]) app; 63 64 int write(DataType[] buffer) { 65 this.app ~= buffer; 66 return cast(int) buffer.length; 67 } 68 69 /** 70 * Gets the internal array to which elements have been appended. 71 * Returns: The internal array. 72 */ 73 DataType[] toArray() { 74 return this.app[]; 75 } 76 77 void reset() { 78 this.app = appender!(DataType[])(); 79 } 80 } 81 82 unittest { 83 import streams.primitives; 84 85 assert(isSomeOutputStream!(ArrayOutputStream!bool)); 86 87 auto s1 = ArrayOutputStream!float(); 88 float[] buffer = [0.5, 1, 1.5]; 89 assert(s1.write(buffer) == 3); 90 buffer = [2, 2.5, 3]; 91 assert(s1.write(buffer) == 3); 92 assert(s1.toArray() == [0.5, 1, 1.5, 2, 2.5, 3]); 93 94 auto s2 = ArrayOutputStream!ubyte(); 95 ubyte[] buffer1 = [1, 2, 3]; 96 s2.write(buffer1); 97 ubyte[] data = s2.toArray(); 98 assert(data == [1, 2, 3]); 99 }