authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-05 07:38:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-05 07:38:24-05:00
logb7bc259093ccad98cdc5661c493c0bdb4771e899
tree8f7730bdc0e79c240309ec4394b3c3e977d36653
parent893f1088dfe40b0141ac6988a1ae6b165f7cc643

make OutStream and InStream take an error set param


3 files changed, 198 insertions(+), 173 deletions(-)

src/ir.cpp+22-17
......@@ -7174,32 +7174,37 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
71747174 return ira->codegen->builtin_types.entry_invalid;
71757175 }
71767176 if (err_set_type == nullptr) {
7177 err_set_type = cur_type;
7177 if (prev_type->id == TypeTableEntryIdErrorUnion) {
7178 err_set_type = prev_type->data.error_union.err_set_type;
7179 } else {
7180 err_set_type = cur_type;
7181 }
71787182 errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
71797183 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
71807184 ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i];
71817185 errors[error_entry->value] = error_entry;
71827186 }
7183 continue;
7184 } else {
7185 // check if the cur type error set is a subset
7186 bool prev_is_superset = true;
7187 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
7188 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
7189 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
7190 if (error_entry == nullptr) {
7191 prev_is_superset = false;
7192 break;
7193 }
7194 }
7195 if (prev_is_superset) {
7187 if (err_set_type == cur_type) {
71967188 continue;
71977189 }
7198 // not a subset. invent new error set type, union of both of them
7199 err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type);
7200 assert(errors != nullptr);
7190 }
7191 // check if the cur type error set is a subset
7192 bool prev_is_superset = true;
7193 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
7194 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
7195 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
7196 if (error_entry == nullptr) {
7197 prev_is_superset = false;
7198 break;
7199 }
7200 }
7201 if (prev_is_superset) {
72017202 continue;
72027203 }
7204 // not a subset. invent new error set type, union of both of them
7205 err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type);
7206 assert(errors != nullptr);
7207 continue;
72037208 }
72047209
72057210 if (prev_type->id == TypeTableEntryIdErrorUnion && cur_type->id == TypeTableEntryIdErrorUnion) {
std/debug/index.zig+28-20
......@@ -15,12 +15,12 @@ pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
1515/// TODO atomic/multithread support
1616var stderr_file: io.File = undefined;
1717var stderr_file_out_stream: io.FileOutStream = undefined;
18var stderr_stream: ?&io.OutStream = null;
18var stderr_stream: ?&io.OutStream(io.FileOutStream.Error) = null;
1919pub fn warn(comptime fmt: []const u8, args: ...) void {
2020 const stderr = getStderrStream() catch return;
2121 stderr.print(fmt, args) catch return;
2222}
23fn getStderrStream() !&io.OutStream {
23fn getStderrStream() !&io.OutStream(io.FileOutStream.Error) {
2424 if (stderr_stream) |st| {
2525 return st;
2626 } else {
......@@ -140,7 +140,7 @@ const WHITE = "\x1b[37;1m";
140140const DIM = "\x1b[2m";
141141const RESET = "\x1b[0m";
142142
143pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,
143pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator,
144144 debug_info: &ElfStackTrace, tty_color: bool) !void
145145{
146146 var frame_index: usize = undefined;
......@@ -162,7 +162,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O
162162 }
163163}
164164
165pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator,
165pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
166166 debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) !void
167167{
168168 var ignored_count: usize = 0;
......@@ -179,7 +179,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat
179179 }
180180}
181181
182fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) !void {
182fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: usize) !void {
183183 if (builtin.os == builtin.Os.windows) {
184184 return error.UnsupportedDebugInfo;
185185 }
......@@ -532,7 +532,7 @@ const LineNumberProgram = struct {
532532 }
533533};
534534
535fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) ![]u8 {
535fn readStringRaw(allocator: &mem.Allocator, in_stream: var) ![]u8 {
536536 var buf = ArrayList(u8).init(allocator);
537537 while (true) {
538538 const byte = try in_stream.readByte();
......@@ -549,54 +549,62 @@ fn getString(st: &ElfStackTrace, offset: u64) ![]u8 {
549549 return st.readString();
550550}
551551
552fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) ![]u8 {
552fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8 {
553553 const buf = try global_allocator.alloc(u8, size);
554554 errdefer global_allocator.free(buf);
555555 if ((try in_stream.read(buf)) < size) return error.EndOfFile;
556556 return buf;
557557}
558558
559fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
559fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
560560 const buf = try readAllocBytes(allocator, in_stream, size);
561561 return FormValue { .Block = buf };
562562}
563563
564fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
564fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
565565 const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
566566 return parseFormValueBlockLen(allocator, in_stream, block_len);
567567}
568568
569fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) !FormValue {
569fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
570570 return FormValue { .Const = Constant {
571571 .signed = signed,
572572 .payload = try readAllocBytes(allocator, in_stream, size),
573573 }};
574574}
575575
576fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) !u64 {
576fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
577577 return if (is_64) try in_stream.readIntLe(u64)
578578 else u64(try in_stream.readIntLe(u32)) ;
579579}
580580
581fn parseFormValueTargetAddrSize(in_stream: &io.InStream) !u64 {
581fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
582582 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
583583 else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
584584 else unreachable;
585585}
586586
587fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue {
587fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
588588 const buf = try readAllocBytes(allocator, in_stream, size);
589589 return FormValue { .Ref = buf };
590590}
591591
592fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) !FormValue {
592fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type) !FormValue {
593593 const block_len = try in_stream.readIntLe(T);
594594 return parseFormValueRefLen(allocator, in_stream, block_len);
595595}
596596
597const ParseFormValueError = error {};
597const ParseFormValueError = error {
598 EndOfStream,
599 Io,
600 BadFd,
601 Unexpected,
602 InvalidDebugInfo,
603 EndOfFile,
604 OutOfMemory,
605};
598606
599fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool)
607fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool)
600608 ParseFormValueError!FormValue
601609{
602610 return switch (form_id) {
......@@ -739,7 +747,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
739747 try in_file.seekTo(this_offset);
740748
741749 var is_64: bool = undefined;
742 const unit_length = try readInitialLength(in_stream, &is_64);
750 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
743751 if (unit_length == 0)
744752 return error.MissingDebugInfo;
745753 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
......@@ -914,7 +922,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
914922 try st.self_exe_file.seekTo(this_unit_offset);
915923
916924 var is_64: bool = undefined;
917 const unit_length = try readInitialLength(in_stream, &is_64);
925 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
918926 if (unit_length == 0)
919927 return;
920928 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
......@@ -1014,7 +1022,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
10141022 return error.MissingDebugInfo;
10151023}
10161024
1017fn readInitialLength(in_stream: &io.InStream, is_64: &bool) !u64 {
1025fn readInitialLength(comptime E: type, in_stream: &io.InStream(E), is_64: &bool) !u64 {
10181026 const first_32_bits = try in_stream.readIntLe(u32);
10191027 *is_64 = (first_32_bits == 0xffffffff);
10201028 if (*is_64) {
......@@ -1025,7 +1033,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) !u64 {
10251033 }
10261034}
10271035
1028fn readULeb128(in_stream: &io.InStream) !u64 {
1036fn readULeb128(in_stream: var) !u64 {
10291037 var result: u64 = 0;
10301038 var shift: usize = 0;
10311039
std/io.zig+148-136
......@@ -61,18 +61,21 @@ pub fn getStdIn() GetStdIoErrs!File {
6161/// Implementation of InStream trait for File
6262pub const FileInStream = struct {
6363 file: &File,
64 stream: InStream,
64 stream: Stream,
65
66 pub const Error = @typeOf(File.read).ReturnType.ErrorSet;
67 pub const Stream = InStream(Error);
6568
6669 pub fn init(file: &File) FileInStream {
6770 return FileInStream {
6871 .file = file,
69 .stream = InStream {
72 .stream = Stream {
7073 .readFn = readFn,
7174 },
7275 };
7376 }
7477
75 fn readFn(in_stream: &InStream, buffer: []u8) !usize {
78 fn readFn(in_stream: &Stream, buffer: []u8) Error!usize {
7679 const self = @fieldParentPtr(FileInStream, "stream", in_stream);
7780 return self.file.read(buffer);
7881 }
......@@ -81,18 +84,21 @@ pub const FileInStream = struct {
8184/// Implementation of OutStream trait for File
8285pub const FileOutStream = struct {
8386 file: &File,
84 stream: OutStream,
87 stream: Stream,
88
89 pub const Error = File.WriteError;
90 pub const Stream = OutStream(Error);
8591
8692 pub fn init(file: &File) FileOutStream {
8793 return FileOutStream {
8894 .file = file,
89 .stream = OutStream {
95 .stream = Stream {
9096 .writeFn = writeFn,
9197 },
9298 };
9399 }
94100
95 fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
101 fn writeFn(out_stream: &Stream, bytes: []const u8) !void {
96102 const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
97103 return self.file.write(bytes);
98104 }
......@@ -298,6 +304,8 @@ pub const File = struct {
298304 }
299305 }
300306
307 pub const ReadError = error {};
308
301309 pub fn read(self: &File, buffer: []u8) !usize {
302310 if (is_posix) {
303311 var index: usize = 0;
......@@ -340,7 +348,7 @@ pub const File = struct {
340348 }
341349 }
342350
343 const WriteError = os.WindowsWriteError || os.PosixWriteError;
351 pub const WriteError = os.WindowsWriteError || os.PosixWriteError;
344352
345353 fn write(self: &File, bytes: []const u8) WriteError!void {
346354 if (is_posix) {
......@@ -353,161 +361,165 @@ pub const File = struct {
353361 }
354362};
355363
356pub const InStream = struct {
357 // TODO allow specifying the error set
358 /// Return the number of bytes read. If the number read is smaller than buf.len, it
359 /// means the stream reached the end. Reaching the end of a stream is not an error
360 /// condition.
361 readFn: fn(self: &InStream, buffer: []u8) error!usize,
362
363 /// Replaces `buffer` contents by reading from the stream until it is finished.
364 /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
365 /// the contents read from the stream are lost.
366 pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) !void {
367 try buffer.resize(0);
368
369 var actual_buf_len: usize = 0;
370 while (true) {
371 const dest_slice = buffer.toSlice()[actual_buf_len..];
372 const bytes_read = try self.readFn(self, dest_slice);
373 actual_buf_len += bytes_read;
374
375 if (bytes_read != dest_slice.len) {
376 buffer.shrink(actual_buf_len);
377 return;
378 }
379
380 const new_buf_size = math.min(max_size, actual_buf_len + os.page_size);
381 if (new_buf_size == actual_buf_len)
382 return error.StreamTooLong;
383 try buffer.resize(new_buf_size);
384 }
385 }
364pub fn InStream(comptime Error: type) type {
365 return struct {
366 const Self = this;
386367
387 /// Allocates enough memory to hold all the contents of the stream. If the allocated
388 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
389 /// Caller owns returned memory.
390 /// If this function returns an error, the contents from the stream read so far are lost.
391 pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) ![]u8 {
392 var buf = Buffer.initNull(allocator);
393 defer buf.deinit();
368 /// Return the number of bytes read. If the number read is smaller than buf.len, it
369 /// means the stream reached the end. Reaching the end of a stream is not an error
370 /// condition.
371 readFn: fn(self: &Self, buffer: []u8) Error!usize,
394372
395 try self.readAllBuffer(&buf, max_size);
396 return buf.toOwnedSlice();
397 }
373 /// Replaces `buffer` contents by reading from the stream until it is finished.
374 /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
375 /// the contents read from the stream are lost.
376 pub fn readAllBuffer(self: &Self, buffer: &Buffer, max_size: usize) !void {
377 try buffer.resize(0);
398378
399 /// Replaces `buffer` contents by reading from the stream until `delimiter` is found.
400 /// Does not include the delimiter in the result.
401 /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
402 /// read from the stream so far are lost.
403 pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) !void {
404 try buf.resize(0);
379 var actual_buf_len: usize = 0;
380 while (true) {
381 const dest_slice = buffer.toSlice()[actual_buf_len..];
382 const bytes_read = try self.readFn(self, dest_slice);
383 actual_buf_len += bytes_read;
405384
406 while (true) {
407 var byte: u8 = try self.readByte();
385 if (bytes_read != dest_slice.len) {
386 buffer.shrink(actual_buf_len);
387 return;
388 }
408389
409 if (byte == delimiter) {
410 return;
390 const new_buf_size = math.min(max_size, actual_buf_len + os.page_size);
391 if (new_buf_size == actual_buf_len)
392 return error.StreamTooLong;
393 try buffer.resize(new_buf_size);
411394 }
395 }
412396
413 if (buf.len() == max_size) {
414 return error.StreamTooLong;
415 }
397 /// Allocates enough memory to hold all the contents of the stream. If the allocated
398 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
399 /// Caller owns returned memory.
400 /// If this function returns an error, the contents from the stream read so far are lost.
401 pub fn readAllAlloc(self: &Self, allocator: &mem.Allocator, max_size: usize) ![]u8 {
402 var buf = Buffer.initNull(allocator);
403 defer buf.deinit();
416404
417 try buf.appendByte(byte);
405 try self.readAllBuffer(&buf, max_size);
406 return buf.toOwnedSlice();
418407 }
419 }
420408
421 /// Allocates enough memory to read until `delimiter`. If the allocated
422 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
423 /// Caller owns returned memory.
424 /// If this function returns an error, the contents from the stream read so far are lost.
425 pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator,
426 delimiter: u8, max_size: usize) ![]u8
427 {
428 var buf = Buffer.initNull(allocator);
429 defer buf.deinit();
430
431 try self.readUntilDelimiterBuffer(self, &buf, delimiter, max_size);
432 return buf.toOwnedSlice();
433 }
409 /// Replaces `buffer` contents by reading from the stream until `delimiter` is found.
410 /// Does not include the delimiter in the result.
411 /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
412 /// read from the stream so far are lost.
413 pub fn readUntilDelimiterBuffer(self: &Self, buffer: &Buffer, delimiter: u8, max_size: usize) !void {
414 try buf.resize(0);
434415
435 /// Returns the number of bytes read. If the number read is smaller than buf.len, it
436 /// means the stream reached the end. Reaching the end of a stream is not an error
437 /// condition.
438 pub fn read(self: &InStream, buffer: []u8) !usize {
439 return self.readFn(self, buffer);
440 }
416 while (true) {
417 var byte: u8 = try self.readByte();
441418
442 /// Same as `read` but end of stream returns `error.EndOfStream`.
443 pub fn readNoEof(self: &InStream, buf: []u8) !void {
444 const amt_read = try self.read(buf);
445 if (amt_read < buf.len) return error.EndOfStream;
446 }
419 if (byte == delimiter) {
420 return;
421 }
447422
448 /// Reads 1 byte from the stream or returns `error.EndOfStream`.
449 pub fn readByte(self: &InStream) !u8 {
450 var result: [1]u8 = undefined;
451 try self.readNoEof(result[0..]);
452 return result[0];
453 }
423 if (buf.len() == max_size) {
424 return error.StreamTooLong;
425 }
454426
455 /// Same as `readByte` except the returned byte is signed.
456 pub fn readByteSigned(self: &InStream) !i8 {
457 return @bitCast(i8, try self.readByte());
458 }
427 try buf.appendByte(byte);
428 }
429 }
459430
460 pub fn readIntLe(self: &InStream, comptime T: type) !T {
461 return self.readInt(builtin.Endian.Little, T);
462 }
431 /// Allocates enough memory to read until `delimiter`. If the allocated
432 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
433 /// Caller owns returned memory.
434 /// If this function returns an error, the contents from the stream read so far are lost.
435 pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator,
436 delimiter: u8, max_size: usize) ![]u8
437 {
438 var buf = Buffer.initNull(allocator);
439 defer buf.deinit();
440
441 try self.readUntilDelimiterBuffer(self, &buf, delimiter, max_size);
442 return buf.toOwnedSlice();
443 }
463444
464 pub fn readIntBe(self: &InStream, comptime T: type) !T {
465 return self.readInt(builtin.Endian.Big, T);
466 }
445 /// Returns the number of bytes read. If the number read is smaller than buf.len, it
446 /// means the stream reached the end. Reaching the end of a stream is not an error
447 /// condition.
448 pub fn read(self: &Self, buffer: []u8) !usize {
449 return self.readFn(self, buffer);
450 }
467451
468 pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) !T {
469 var bytes: [@sizeOf(T)]u8 = undefined;
470 try self.readNoEof(bytes[0..]);
471 return mem.readInt(bytes, T, endian);
472 }
452 /// Same as `read` but end of stream returns `error.EndOfStream`.
453 pub fn readNoEof(self: &Self, buf: []u8) !void {
454 const amt_read = try self.read(buf);
455 if (amt_read < buf.len) return error.EndOfStream;
456 }
473457
474 pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) !T {
475 assert(size <= @sizeOf(T));
476 assert(size <= 8);
477 var input_buf: [8]u8 = undefined;
478 const input_slice = input_buf[0..size];
479 try self.readNoEof(input_slice);
480 return mem.readInt(input_slice, T, endian);
481 }
458 /// Reads 1 byte from the stream or returns `error.EndOfStream`.
459 pub fn readByte(self: &Self) !u8 {
460 var result: [1]u8 = undefined;
461 try self.readNoEof(result[0..]);
462 return result[0];
463 }
482464
465 /// Same as `readByte` except the returned byte is signed.
466 pub fn readByteSigned(self: &Self) !i8 {
467 return @bitCast(i8, try self.readByte());
468 }
483469
484};
470 pub fn readIntLe(self: &Self, comptime T: type) !T {
471 return self.readInt(builtin.Endian.Little, T);
472 }
485473
486pub const OutStream = struct {
487 // TODO allow specifying the error set
488 writeFn: fn(self: &OutStream, bytes: []const u8) error!void,
474 pub fn readIntBe(self: &Self, comptime T: type) !T {
475 return self.readInt(builtin.Endian.Big, T);
476 }
489477
490 pub fn print(self: &OutStream, comptime format: []const u8, args: ...) !void {
491 return std.fmt.format(self, error, self.writeFn, format, args);
492 }
478 pub fn readInt(self: &Self, endian: builtin.Endian, comptime T: type) !T {
479 var bytes: [@sizeOf(T)]u8 = undefined;
480 try self.readNoEof(bytes[0..]);
481 return mem.readInt(bytes, T, endian);
482 }
493483
494 pub fn write(self: &OutStream, bytes: []const u8) !void {
495 return self.writeFn(self, bytes);
496 }
484 pub fn readVarInt(self: &Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
485 assert(size <= @sizeOf(T));
486 assert(size <= 8);
487 var input_buf: [8]u8 = undefined;
488 const input_slice = input_buf[0..size];
489 try self.readNoEof(input_slice);
490 return mem.readInt(input_slice, T, endian);
491 }
492 };
493}
497494
498 pub fn writeByte(self: &OutStream, byte: u8) !void {
499 const slice = (&byte)[0..1];
500 return self.writeFn(self, slice);
501 }
495pub fn OutStream(comptime Error: type) type {
496 return struct {
497 const Self = this;
498
499 writeFn: fn(self: &Self, bytes: []const u8) Error!void,
502500
503 pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) !void {
504 const slice = (&byte)[0..1];
505 var i: usize = 0;
506 while (i < n) : (i += 1) {
507 try self.writeFn(self, slice);
501 pub fn print(self: &Self, comptime format: []const u8, args: ...) !void {
502 return std.fmt.format(self, error, self.writeFn, format, args);
508503 }
509 }
510};
504
505 pub fn write(self: &Self, bytes: []const u8) !void {
506 return self.writeFn(self, bytes);
507 }
508
509 pub fn writeByte(self: &Self, byte: u8) !void {
510 const slice = (&byte)[0..1];
511 return self.writeFn(self, slice);
512 }
513
514 pub fn writeByteNTimes(self: &Self, byte: u8, n: usize) !void {
515 const slice = (&byte)[0..1];
516 var i: usize = 0;
517 while (i < n) : (i += 1) {
518 try self.writeFn(self, slice);
519 }
520 }
521 };
522}
511523
512524/// `path` may need to be copied in memory to add a null terminating byte. In this case
513525/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed