<NME> streams.clay
<BEF> 
public import io.errors.*;
import core.vectors.generic.*;
import buffervector.*;
import strings.*;


public import io.streams.bytevector.*;


/// @section  read, write wrappers to readBytes, writeBytes

[B, N when ByteLike?(B) and Integer?(N)]
overload read(stream, buf:Pointer[B], n:N) = readBytes(stream, Pointer[Byte](buf), SizeT(n));

[B, N when ByteLike?(B) and Integer?(N)]
overload write(stream, buf:Pointer[B], n:N) {
    var pos = SizeT(0);
    while (pos < n) {
        pos +: writeBytes(stream, Pointer[Byte](buf) + pos, SizeT(n) - pos);
    }
}


/// @section  readByte, readChar, writeByte, writeChar

readByte(stream) {
    var b = Byte();
    var result = read(stream, @b, SizeT(1));
    if (result == 1)
        return Maybe(b);
    else
        return nothing(Byte);
}

readChar(stream) {
    var b = Byte();
    var result = read(stream, @b, SizeT(1));
    if (result == 1)
        return Maybe(Char(b));
    else
        return nothing(Char);
}

[B when ByteLike?(B)]
writeByte(stream, b: B) {
    write(stream, @b, 1);
}

writeChar(stream, c: Char) {
    writeByte(stream, c);
}


/// @section  read - read into byte vector 

[V when ByteVector?(V)]
overload read(stream, n:SizeT, buf:V) {
    var current = size(buf);
    resize(buf, current + n);
    var ptr = Pointer[Byte](begin(buf) + current);
    var numRead = read(stream, ptr, n);
    resize(buf, current + numRead);
    return numRead;
}

overload read(stream, n:SizeT) {
    var buf = String();
    read(stream, n, buf);
    return move(buf);
}


/// @section  readN - read exactly n bytes 

record PrematureEOF(expected:SizeT, received:SizeT);
instance IOError (PrematureEOF);

define readN;

[V when ByteVector?(V)]
overload readN(stream, n:SizeT, buf:V) {
    var initial = size(buf);
    var current = initial;
    var expected = initial + n;
    while (current < expected) {
        var numRead = read(stream, expected - current, buf);
        if (numRead == 0)
            throw PrematureEOF(expected-initial, current-initial);
        current +: numRead;
    }
}

overload readN(stream, buffer:Pointer[Byte], n:SizeT) {
    var bv = BufferVector(buffer, buffer + n);
    readN(stream, n, bv);
}

overload readN(stream, n:SizeT) {
    var buf = String();
    readN(stream, n, buf);
    return move(buf);
}


/// @section  readAll 

define readAll;

[V when ByteVector?(V)]
overload readAll(stream, chunkSize:SizeT, buf:V) {
    while (true) {
        var numRead = read(stream, chunkSize, buf);
        if (numRead == 0)
            break;
    }
}

[V when ByteVector?(V)]
overload readAll(stream, buf:V) {
    readAll(stream, SizeT(4096), buf);
}

overload readAll(stream) : String {
    var buf = String();
    readAll(stream, buf);
    return move(buf);
}


/// @section  readUpto, readLine 

define readUpto;

[T, V when ByteLike?(T) and ByteVector?(V)]
overload readUpto(stream, upto:T, buf:V) {
    alias ElementType = SequenceElementType(V);
    var uptoByte = Byte(upto);
    while (true) {
        var mb = readByte(stream);
        if (not hasValue?(mb))
            break;
        var b = just(mb);
        push(buf, ElementType(b));
        if (b == uptoByte)
            break;
    }
}

[T when ByteLike?(T)]
overload readUpto(stream, upto:T) : String {
    var v = String();
    readUpto(stream, upto, v);
    return move(v);
}


define readLine;

[V when ByteVector?(V)]
overload readLine(stream, buf:V) {
    readUpto(stream, '\n', buf);
}

overload readLine(stream) = readUpto(stream, '\n');


/// @section  write - write one byte 

[I when Integer?(I)]
overload write(stream, x:I) {
    var b = Byte(x);
    write(stream, @b, SizeT(1));
}

overload write(stream, x:Char) {
    write(stream, Byte(x));
}


/// @section  write - write byte buffer 

[V when ByteBuffer?(V)]
overload write(stream, x:V) {
    write(stream, Pointer[Byte](begin(x)), size(x));
}


/// @section  write, flush - write to ByteVector 

[V when ByteVector?(V)]
overload writeBytes(stream:V, buf:Pointer[Byte], n:SizeT) {
    var currentSize = size(stream);
    resize(stream, currentSize + n);
    var dest = Pointer[Byte](begin(stream)) + currentSize;
    copyNonoverlappingMemory(dest, buf, buf+n);
    return n;
}

[V when ByteVector?(V)]
overload flush(stream:V) {
}



/// @section  collection protocols

[I when InputStream?(I)]
overload nextValue(is:I) = readByte(is);

[O, B when OutputStream?(O) and ByteLike?(B)]
overload push(os:O, b:B) {
    writeByte(os, b);
}

[O, B when OutputStream?(O) and ByteBuffer?(B)]
overload push(os:O, bs:B) {
    write(os, bs);
}



<MSG> Revert "Add printer/observe"

This reverts commit 7ec2d80cbe221649ecbb2d4bdc1f81e2c13b07ab.

<DFF> @@ -1,7 +1,7 @@
 
 public import io.errors.*;
 import core.vectors.generic.*;
-import buffervector.*;
+import buffer.*;
 import strings.*;
 
 

{'addition_count': 1, 'commit_subject': 'Revert "Add printer/observe"', 'deletion_count': 1, 'file_extension': '.clay', 'lang': 'clay', 'license': 'bsd-2-clause', 'repo_name': 'jckarter/clay'}