aboutsummaryrefslogtreecommitdiff
path: root/std/io.zig
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-02-05 07:38:24 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-02-05 07:38:24 -0500
commitb7bc259093ccad98cdc5661c493c0bdb4771e899 (patch)
tree8f7730bdc0e79c240309ec4394b3c3e977d36653 /std/io.zig
parent893f1088dfe40b0141ac6988a1ae6b165f7cc643 (diff)
downloadzig-b7bc259093ccad98cdc5661c493c0bdb4771e899.tar.gz
zig-b7bc259093ccad98cdc5661c493c0bdb4771e899.zip
make OutStream and InStream take an error set param
Diffstat (limited to 'std/io.zig')
-rw-r--r--std/io.zig284
1 files changed, 148 insertions, 136 deletions
diff --git a/std/io.zig b/std/io.zig
index dbca37745a..50b70db645 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -61,18 +61,21 @@ pub fn getStdIn() GetStdIoErrs!File {
/// Implementation of InStream trait for File
pub const FileInStream = struct {
file: &File,
- stream: InStream,
+ stream: Stream,
+
+ pub const Error = @typeOf(File.read).ReturnType.ErrorSet;
+ pub const Stream = InStream(Error);
pub fn init(file: &File) FileInStream {
return FileInStream {
.file = file,
- .stream = InStream {
+ .stream = Stream {
.readFn = readFn,
},
};
}
- fn readFn(in_stream: &InStream, buffer: []u8) !usize {
+ fn readFn(in_stream: &Stream, buffer: []u8) Error!usize {
const self = @fieldParentPtr(FileInStream, "stream", in_stream);
return self.file.read(buffer);
}
@@ -81,18 +84,21 @@ pub const FileInStream = struct {
/// Implementation of OutStream trait for File
pub const FileOutStream = struct {
file: &File,
- stream: OutStream,
+ stream: Stream,
+
+ pub const Error = File.WriteError;
+ pub const Stream = OutStream(Error);
pub fn init(file: &File) FileOutStream {
return FileOutStream {
.file = file,
- .stream = OutStream {
+ .stream = Stream {
.writeFn = writeFn,
},
};
}
- fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
+ fn writeFn(out_stream: &Stream, bytes: []const u8) !void {
const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
return self.file.write(bytes);
}
@@ -298,6 +304,8 @@ pub const File = struct {
}
}
+ pub const ReadError = error {};
+
pub fn read(self: &File, buffer: []u8) !usize {
if (is_posix) {
var index: usize = 0;
@@ -340,7 +348,7 @@ pub const File = struct {
}
}
- const WriteError = os.WindowsWriteError || os.PosixWriteError;
+ pub const WriteError = os.WindowsWriteError || os.PosixWriteError;
fn write(self: &File, bytes: []const u8) WriteError!void {
if (is_posix) {
@@ -353,161 +361,165 @@ pub const File = struct {
}
};
-pub const InStream = struct {
- // TODO allow specifying the error set
- /// Return the number of bytes read. If the number read is smaller than buf.len, it
- /// means the stream reached the end. Reaching the end of a stream is not an error
- /// condition.
- readFn: fn(self: &InStream, buffer: []u8) error!usize,
-
- /// Replaces `buffer` contents by reading from the stream until it is finished.
- /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
- /// the contents read from the stream are lost.
- pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) !void {
- try buffer.resize(0);
-
- var actual_buf_len: usize = 0;
- while (true) {
- const dest_slice = buffer.toSlice()[actual_buf_len..];
- const bytes_read = try self.readFn(self, dest_slice);
- actual_buf_len += bytes_read;
-
- if (bytes_read != dest_slice.len) {
- buffer.shrink(actual_buf_len);
- return;
- }
-
- const new_buf_size = math.min(max_size, actual_buf_len + os.page_size);
- if (new_buf_size == actual_buf_len)
- return error.StreamTooLong;
- try buffer.resize(new_buf_size);
- }
- }
+pub fn InStream(comptime Error: type) type {
+ return struct {
+ const Self = this;
- /// Allocates enough memory to hold all the contents of the stream. If the allocated
- /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
- /// Caller owns returned memory.
- /// If this function returns an error, the contents from the stream read so far are lost.
- pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) ![]u8 {
- var buf = Buffer.initNull(allocator);
- defer buf.deinit();
+ /// Return the number of bytes read. If the number read is smaller than buf.len, it
+ /// means the stream reached the end. Reaching the end of a stream is not an error
+ /// condition.
+ readFn: fn(self: &Self, buffer: []u8) Error!usize,
- try self.readAllBuffer(&buf, max_size);
- return buf.toOwnedSlice();
- }
+ /// Replaces `buffer` contents by reading from the stream until it is finished.
+ /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
+ /// the contents read from the stream are lost.
+ pub fn readAllBuffer(self: &Self, buffer: &Buffer, max_size: usize) !void {
+ try buffer.resize(0);
- /// Replaces `buffer` contents by reading from the stream until `delimiter` is found.
- /// Does not include the delimiter in the result.
- /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
- /// read from the stream so far are lost.
- pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) !void {
- try buf.resize(0);
+ var actual_buf_len: usize = 0;
+ while (true) {
+ const dest_slice = buffer.toSlice()[actual_buf_len..];
+ const bytes_read = try self.readFn(self, dest_slice);
+ actual_buf_len += bytes_read;
- while (true) {
- var byte: u8 = try self.readByte();
+ if (bytes_read != dest_slice.len) {
+ buffer.shrink(actual_buf_len);
+ return;
+ }
- if (byte == delimiter) {
- return;
+ const new_buf_size = math.min(max_size, actual_buf_len + os.page_size);
+ if (new_buf_size == actual_buf_len)
+ return error.StreamTooLong;
+ try buffer.resize(new_buf_size);
}
+ }
- if (buf.len() == max_size) {
- return error.StreamTooLong;
- }
+ /// Allocates enough memory to hold all the contents of the stream. If the allocated
+ /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
+ /// Caller owns returned memory.
+ /// If this function returns an error, the contents from the stream read so far are lost.
+ pub fn readAllAlloc(self: &Self, allocator: &mem.Allocator, max_size: usize) ![]u8 {
+ var buf = Buffer.initNull(allocator);
+ defer buf.deinit();
- try buf.appendByte(byte);
+ try self.readAllBuffer(&buf, max_size);
+ return buf.toOwnedSlice();
}
- }
- /// Allocates enough memory to read until `delimiter`. If the allocated
- /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
- /// Caller owns returned memory.
- /// If this function returns an error, the contents from the stream read so far are lost.
- pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator,
- delimiter: u8, max_size: usize) ![]u8
- {
- var buf = Buffer.initNull(allocator);
- defer buf.deinit();
-
- try self.readUntilDelimiterBuffer(self, &buf, delimiter, max_size);
- return buf.toOwnedSlice();
- }
+ /// Replaces `buffer` contents by reading from the stream until `delimiter` is found.
+ /// Does not include the delimiter in the result.
+ /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
+ /// read from the stream so far are lost.
+ pub fn readUntilDelimiterBuffer(self: &Self, buffer: &Buffer, delimiter: u8, max_size: usize) !void {
+ try buf.resize(0);
- /// Returns the number of bytes read. If the number read is smaller than buf.len, it
- /// means the stream reached the end. Reaching the end of a stream is not an error
- /// condition.
- pub fn read(self: &InStream, buffer: []u8) !usize {
- return self.readFn(self, buffer);
- }
+ while (true) {
+ var byte: u8 = try self.readByte();
- /// Same as `read` but end of stream returns `error.EndOfStream`.
- pub fn readNoEof(self: &InStream, buf: []u8) !void {
- const amt_read = try self.read(buf);
- if (amt_read < buf.len) return error.EndOfStream;
- }
+ if (byte == delimiter) {
+ return;
+ }
- /// Reads 1 byte from the stream or returns `error.EndOfStream`.
- pub fn readByte(self: &InStream) !u8 {
- var result: [1]u8 = undefined;
- try self.readNoEof(result[0..]);
- return result[0];
- }
+ if (buf.len() == max_size) {
+ return error.StreamTooLong;
+ }
- /// Same as `readByte` except the returned byte is signed.
- pub fn readByteSigned(self: &InStream) !i8 {
- return @bitCast(i8, try self.readByte());
- }
+ try buf.appendByte(byte);
+ }
+ }
- pub fn readIntLe(self: &InStream, comptime T: type) !T {
- return self.readInt(builtin.Endian.Little, T);
- }
+ /// Allocates enough memory to read until `delimiter`. If the allocated
+ /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
+ /// Caller owns returned memory.
+ /// If this function returns an error, the contents from the stream read so far are lost.
+ pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator,
+ delimiter: u8, max_size: usize) ![]u8
+ {
+ var buf = Buffer.initNull(allocator);
+ defer buf.deinit();
+
+ try self.readUntilDelimiterBuffer(self, &buf, delimiter, max_size);
+ return buf.toOwnedSlice();
+ }
- pub fn readIntBe(self: &InStream, comptime T: type) !T {
- return self.readInt(builtin.Endian.Big, T);
- }
+ /// Returns the number of bytes read. If the number read is smaller than buf.len, it
+ /// means the stream reached the end. Reaching the end of a stream is not an error
+ /// condition.
+ pub fn read(self: &Self, buffer: []u8) !usize {
+ return self.readFn(self, buffer);
+ }
- pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) !T {
- var bytes: [@sizeOf(T)]u8 = undefined;
- try self.readNoEof(bytes[0..]);
- return mem.readInt(bytes, T, endian);
- }
+ /// Same as `read` but end of stream returns `error.EndOfStream`.
+ pub fn readNoEof(self: &Self, buf: []u8) !void {
+ const amt_read = try self.read(buf);
+ if (amt_read < buf.len) return error.EndOfStream;
+ }
- pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) !T {
- assert(size <= @sizeOf(T));
- assert(size <= 8);
- var input_buf: [8]u8 = undefined;
- const input_slice = input_buf[0..size];
- try self.readNoEof(input_slice);
- return mem.readInt(input_slice, T, endian);
- }
+ /// Reads 1 byte from the stream or returns `error.EndOfStream`.
+ pub fn readByte(self: &Self) !u8 {
+ var result: [1]u8 = undefined;
+ try self.readNoEof(result[0..]);
+ return result[0];
+ }
+ /// Same as `readByte` except the returned byte is signed.
+ pub fn readByteSigned(self: &Self) !i8 {
+ return @bitCast(i8, try self.readByte());
+ }
-};
+ pub fn readIntLe(self: &Self, comptime T: type) !T {
+ return self.readInt(builtin.Endian.Little, T);
+ }
-pub const OutStream = struct {
- // TODO allow specifying the error set
- writeFn: fn(self: &OutStream, bytes: []const u8) error!void,
+ pub fn readIntBe(self: &Self, comptime T: type) !T {
+ return self.readInt(builtin.Endian.Big, T);
+ }
- pub fn print(self: &OutStream, comptime format: []const u8, args: ...) !void {
- return std.fmt.format(self, error, self.writeFn, format, args);
- }
+ pub fn readInt(self: &Self, endian: builtin.Endian, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try self.readNoEof(bytes[0..]);
+ return mem.readInt(bytes, T, endian);
+ }
- pub fn write(self: &OutStream, bytes: []const u8) !void {
- return self.writeFn(self, bytes);
- }
+ pub fn readVarInt(self: &Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
+ assert(size <= @sizeOf(T));
+ assert(size <= 8);
+ var input_buf: [8]u8 = undefined;
+ const input_slice = input_buf[0..size];
+ try self.readNoEof(input_slice);
+ return mem.readInt(input_slice, T, endian);
+ }
+ };
+}
- pub fn writeByte(self: &OutStream, byte: u8) !void {
- const slice = (&byte)[0..1];
- return self.writeFn(self, slice);
- }
+pub fn OutStream(comptime Error: type) type {
+ return struct {
+ const Self = this;
+
+ writeFn: fn(self: &Self, bytes: []const u8) Error!void,
- pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) !void {
- const slice = (&byte)[0..1];
- var i: usize = 0;
- while (i < n) : (i += 1) {
- try self.writeFn(self, slice);
+ pub fn print(self: &Self, comptime format: []const u8, args: ...) !void {
+ return std.fmt.format(self, error, self.writeFn, format, args);
}
- }
-};
+
+ pub fn write(self: &Self, bytes: []const u8) !void {
+ return self.writeFn(self, bytes);
+ }
+
+ pub fn writeByte(self: &Self, byte: u8) !void {
+ const slice = (&byte)[0..1];
+ return self.writeFn(self, slice);
+ }
+
+ pub fn writeByteNTimes(self: &Self, byte: u8, n: usize) !void {
+ const slice = (&byte)[0..1];
+ var i: usize = 0;
+ while (i < n) : (i += 1) {
+ try self.writeFn(self, slice);
+ }
+ }
+ };
+}
/// `path` may need to be copied in memory to add a null terminating byte. In this case
/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed