@@ -12,6 +12,7 @@ import iopipe.traits;
1212import std.traits : isDynamicArray, hasMember;
1313import std.range.primitives ;
1414
15+
1516/**
1617 * An example processor. This demonstrates the required items for implementing
1718 * an iopipe.
@@ -815,3 +816,54 @@ template iosrc(alias fun, Chain)
815816 return IOSource (c);
816817 }
817818}
819+
820+ // TODO: need to deal with general ranges.
821+ /**
822+ * Write data from a random access range or character array into the given
823+ * iopipe, and release all the data that was written. Note that this really
824+ * only does anything of interest on iopipes that are writing on release (i.e.
825+ * ones that have a push component).
826+ *
827+ * Params: c = The iopipe chain to write to.
828+ * data = The range to write to the chain.
829+ *
830+ * Returns: The number of elements written. This should match the elements of
831+ * the range, but could potentially be less if there wasn't a way to extend
832+ * more space and more space was needed.
833+ */
834+ size_t writeBuf (Chain, Range )(ref Chain c, Range data) if (isIopipe! Chain &&
835+ __traits (compiles , (c.window[0 .. 0 ] = data[0 .. 0 ])))
836+ {
837+ // trivial case
838+ if (data.length == 0 )
839+ return 0 ;
840+
841+ size_t result = data.length;
842+
843+ if (c.window.length == 0 )
844+ c.extend(0 );
845+
846+ while (true )
847+ {
848+ const dlen = data.length;
849+ const wlen = c.window.length;
850+ if (wlen == 0 )
851+ return result - dlen;
852+ if (wlen >= dlen)
853+ {
854+ c.window[0 .. dlen] = data[];
855+ c.release(dlen);
856+ return result;
857+ }
858+ else
859+ {
860+ c.window[] = data[0 .. wlen];
861+ data = data[wlen .. $];
862+ c.release(wlen);
863+ // window is now empty, extend to get more space for writing
864+ c.extend(0 );
865+ }
866+ }
867+ }
868+
869+ // TODO: need unittests for writeBuf
0 commit comments