Commit 608ff52dc3

dbandstra <dbandstra@protonmail.com>
2018-07-29 20:52:10
add SliceOutStream, rename SliceStream to SliceInStream (#1301)
1 parent f884381
Changed files (2)
std/io.zig
@@ -419,7 +419,7 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ
     };
 }
 
-pub const SliceStream = struct {
+pub const SliceInStream = struct {
     const Self = this;
     pub const Error = error { };
     pub const Stream = InStream(Error);
@@ -447,7 +447,53 @@ pub const SliceStream = struct {
 
         return size;
     }
+};
+
+/// This is a simple OutStream that writes to a slice, and returns an error
+/// when it runs out of space.
+pub const SliceOutStream = struct {
+    pub const Error = error{OutOfSpace};
+    pub const Stream = OutStream(Error);
+
+    pub stream: Stream,
+
+    pos: usize,
+    slice: []u8,
 
+    pub fn init(slice: []u8) SliceOutStream {
+        return SliceOutStream{
+            .slice = slice,
+            .pos = 0,
+            .stream = Stream{ .writeFn = writeFn },
+        };
+    }
+
+    pub fn getWritten(self: *const SliceOutStream) []const u8 {
+        return self.slice[0..self.pos];
+    }
+
+    pub fn reset(self: *SliceOutStream) void {
+        self.pos = 0;
+    }
+
+    fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
+        const self = @fieldParentPtr(SliceOutStream, "stream", out_stream);
+
+        assert(self.pos <= self.slice.len);
+
+        const n =
+            if (self.pos + bytes.len <= self.slice.len)
+                bytes.len
+            else
+                self.slice.len - self.pos;
+
+        std.mem.copy(u8, self.slice[self.pos..self.pos + n], bytes[0..n]);
+        self.pos += n;
+
+        if (n < bytes.len) {
+            return Error.OutOfSpace;
+        }
+    }
 };
 
 pub fn BufferedOutStream(comptime Error: type) type {
std/io_test.zig
@@ -2,6 +2,7 @@ const std = @import("index.zig");
 const io = std.io;
 const DefaultPrng = std.rand.DefaultPrng;
 const assert = std.debug.assert;
+const assertError = std.debug.assertError;
 const mem = std.mem;
 const os = std.os;
 const builtin = @import("builtin");
@@ -61,9 +62,9 @@ test "BufferOutStream" {
     assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
 }
 
-test "SliceStream" {
+test "SliceInStream" {
     const bytes = []const u8 { 1, 2, 3, 4, 5, 6, 7 };
-    var ss = io.SliceStream.init(bytes);
+    var ss = io.SliceInStream.init(bytes);
 
     var dest: [4]u8 = undefined;
 
@@ -81,8 +82,8 @@ test "SliceStream" {
 
 test "PeekStream" {
     const bytes = []const u8 { 1, 2, 3, 4, 5, 6, 7, 8 };
-    var ss = io.SliceStream.init(bytes);
-    var ps = io.PeekStream(2, io.SliceStream.Error).init(&ss.stream);
+    var ss = io.SliceInStream.init(bytes);
+    var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
 
     var dest: [4]u8 = undefined;
 
@@ -111,3 +112,23 @@ test "PeekStream" {
     assert(dest[0] == 12);
     assert(dest[1] == 11);
 }
+
+test "SliceOutStream" {
+    var buffer: [10]u8 = undefined;
+    var ss = io.SliceOutStream.init(buffer[0..]);
+
+    try ss.stream.write("Hello");
+    assert(mem.eql(u8, ss.getWritten(), "Hello"));
+
+    try ss.stream.write("world");
+    assert(mem.eql(u8, ss.getWritten(), "Helloworld"));
+
+    assertError(ss.stream.write("!"), error.OutOfSpace);
+    assert(mem.eql(u8, ss.getWritten(), "Helloworld"));
+
+    ss.reset();
+    assert(ss.getWritten().len == 0);
+
+    assertError(ss.stream.write("Hello world!"), error.OutOfSpace);
+    assert(mem.eql(u8, ss.getWritten(), "Hello worl"));
+}