authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2020-06-08 00:33:02-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-08 22:59:28-04:00
log748158277441343e9b54c56e2b9e0725833a43ce
tree185638b4b74d36da81e0feb27ae4b00ed4d32944
parentf5b584cc137b2fb0bdc790f5f9fbba0989e5fbe2

support Writer instead of OutStream

Start implementing https://github.com/ziglang/zig/issues/4917 which is to rename instream/outstream to reader/writer. This first change allows code to use Writer/writer instead of OutStream/outStream, but still maintains the old outstream names with "Deprecated" comments.

18 files changed, 585 insertions(+), 488 deletions(-)

lib/std/debug.zig+3-3
...@@ -53,7 +53,7 @@ pub const LineInfo = struct {...@@ -53,7 +53,7 @@ pub const LineInfo = struct {
53/// Tries to write to stderr, unbuffered, and ignores any error returned.53/// Tries to write to stderr, unbuffered, and ignores any error returned.
54/// Does not append a newline.54/// Does not append a newline.
55var stderr_file: File = undefined;55var stderr_file: File = undefined;
56var stderr_file_out_stream: File.OutStream = undefined;56var stderr_file_writer: File.Writer = undefined;
5757
58var stderr_stream: ?*File.OutStream = null;58var stderr_stream: ?*File.OutStream = null;
59var stderr_mutex = std.Mutex.init();59var stderr_mutex = std.Mutex.init();
...@@ -70,8 +70,8 @@ pub fn getStderrStream() *File.OutStream {...@@ -70,8 +70,8 @@ pub fn getStderrStream() *File.OutStream {
70 return st;70 return st;
71 } else {71 } else {
72 stderr_file = io.getStdErr();72 stderr_file = io.getStdErr();
73 stderr_file_out_stream = stderr_file.outStream();73 stderr_file_writer = stderr_file.outStream();
74 const st = &stderr_file_out_stream;74 const st = &stderr_file_writer;
75 stderr_stream = st;75 stderr_stream = st;
76 return st;76 return st;
77 }77 }
lib/std/fs/file.zig+10-2
...@@ -648,9 +648,17 @@ pub const File = struct {...@@ -648,9 +648,17 @@ pub const File = struct {
648 return .{ .context = file };648 return .{ .context = file };
649 }649 }
650650
651 pub const OutStream = io.OutStream(File, WriteError, write);651 pub const Writer = io.Writer(File, WriteError, write);
652652
653 pub fn outStream(file: File) OutStream {653 /// Deprecated: use `Writer`
654 pub const OutStream = Writer;
655
656 pub fn writer(file: File) Writer {
657 return .{ .context = file };
658 }
659
660 /// Deprecated: use `writer`
661 pub fn outStream(file: File) Writer {
654 return .{ .context = file };662 return .{ .context = file };
655 }663 }
656664
lib/std/io.zig+50-23
...@@ -102,11 +102,17 @@ pub fn getStdIn() File {...@@ -102,11 +102,17 @@ pub fn getStdIn() File {
102}102}
103103
104pub const InStream = @import("io/in_stream.zig").InStream;104pub const InStream = @import("io/in_stream.zig").InStream;
105pub const OutStream = @import("io/out_stream.zig").OutStream;105pub const Writer = @import("io/writer.zig").Writer;
106/// Deprecated: use `Writer`
107pub const OutStream = Writer;
106pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;108pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
107109
108pub const BufferedOutStream = @import("io/buffered_out_stream.zig").BufferedOutStream;110pub const BufferedWriter = @import("io/buffered_writer.zig").BufferedWriter;
109pub const bufferedOutStream = @import("io/buffered_out_stream.zig").bufferedOutStream;111pub const bufferedWriter = @import("io/buffered_writer.zig").bufferedWriter;
112/// Deprecated: use `BufferedWriter`
113pub const BufferedOutStream = BufferedWriter;
114/// Deprecated: use `bufferedWriter`
115pub const bufferedOutStream = bufferedWriter;
110116
111pub const BufferedInStream = @import("io/buffered_in_stream.zig").BufferedInStream;117pub const BufferedInStream = @import("io/buffered_in_stream.zig").BufferedInStream;
112pub const bufferedInStream = @import("io/buffered_in_stream.zig").bufferedInStream;118pub const bufferedInStream = @import("io/buffered_in_stream.zig").bufferedInStream;
...@@ -117,20 +123,36 @@ pub const peekStream = @import("io/peek_stream.zig").peekStream;...@@ -117,20 +123,36 @@ pub const peekStream = @import("io/peek_stream.zig").peekStream;
117pub const FixedBufferStream = @import("io/fixed_buffer_stream.zig").FixedBufferStream;123pub const FixedBufferStream = @import("io/fixed_buffer_stream.zig").FixedBufferStream;
118pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferStream;124pub const fixedBufferStream = @import("io/fixed_buffer_stream.zig").fixedBufferStream;
119125
120pub const COutStream = @import("io/c_out_stream.zig").COutStream;126pub const CWriter = @import("io/c_writer.zig").CWriter;
121pub const cOutStream = @import("io/c_out_stream.zig").cOutStream;127pub const cWriter = @import("io/c_writer.zig").cWriter;
122128/// Deprecated: use `CWriter`
123pub const CountingOutStream = @import("io/counting_out_stream.zig").CountingOutStream;129pub const COutStream = CWriter;
124pub const countingOutStream = @import("io/counting_out_stream.zig").countingOutStream;130/// Deprecated: use `cWriter`
125131pub const cOutStream = cWriter;
126pub const MultiOutStream = @import("io/multi_out_stream.zig").MultiOutStream;132
127pub const multiOutStream = @import("io/multi_out_stream.zig").multiOutStream;133pub const CountingWriter = @import("io/counting_writer.zig").CountingWriter;
134pub const countingWriter = @import("io/counting_writer.zig").countingWriter;
135/// Deprecated: use `CountingWriter`
136pub const CountingOutStream = CountingWriter;
137/// Deprecated: use `countingWriter`
138pub const countingOutStream = countingWriter;
139
140pub const MultiWriter = @import("io/multi_writer.zig").MultiWriter;
141pub const multiWriter = @import("io/multi_writer.zig").multiWriter;
142/// Deprecated: use `MultiWriter`
143pub const MultiOutStream = MultiWriter;
144/// Deprecated: use `multiWriter`
145pub const multiOutStream = multiWriter;
128146
129pub const BitInStream = @import("io/bit_in_stream.zig").BitInStream;147pub const BitInStream = @import("io/bit_in_stream.zig").BitInStream;
130pub const bitInStream = @import("io/bit_in_stream.zig").bitInStream;148pub const bitInStream = @import("io/bit_in_stream.zig").bitInStream;
131149
132pub const BitOutStream = @import("io/bit_out_stream.zig").BitOutStream;150pub const BitWriter = @import("io/bit_writer.zig").BitWriter;
133pub const bitOutStream = @import("io/bit_out_stream.zig").bitOutStream;151pub const bitWriter = @import("io/bit_writer.zig").bitWriter;
152/// Deprecated: use `BitWriter`
153pub const BitOutStream = BitWriter;
154/// Deprecated: use `bitWriter`
155pub const bitOutStream = bitWriter;
134156
135pub const Packing = @import("io/serialization.zig").Packing;157pub const Packing = @import("io/serialization.zig").Packing;
136158
...@@ -144,29 +166,34 @@ pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAt...@@ -144,29 +166,34 @@ pub const BufferedAtomicFile = @import("io/buffered_atomic_file.zig").BufferedAt
144166
145pub const StreamSource = @import("io/stream_source.zig").StreamSource;167pub const StreamSource = @import("io/stream_source.zig").StreamSource;
146168
147/// An OutStream that doesn't write to anything.169/// A Writer that doesn't write to anything.
148pub const null_out_stream = @as(NullOutStream, .{ .context = {} });170pub const null_writer = @as(NullWriter, .{ .context = {} });
171
172/// Deprecated: use `null_writer`
173pub const null_out_stream = null_writer;
149174
150const NullOutStream = OutStream(void, error{}, dummyWrite);175const NullWriter = Writer(void, error{}, dummyWrite);
176/// Deprecated: use NullWriter
177const NullOutStream = NullWriter;
151fn dummyWrite(context: void, data: []const u8) error{}!usize {178fn dummyWrite(context: void, data: []const u8) error{}!usize {
152 return data.len;179 return data.len;
153}180}
154181
155test "null_out_stream" {182test "null_writer" {
156 null_out_stream.writeAll("yay" ** 10) catch |err| switch (err) {};183 null_writer.writeAll("yay" ** 10) catch |err| switch (err) {};
157}184}
158185
159test "" {186test "" {
160 _ = @import("io/bit_in_stream.zig");187 _ = @import("io/bit_in_stream.zig");
161 _ = @import("io/bit_out_stream.zig");188 _ = @import("io/bit_writer.zig");
162 _ = @import("io/buffered_atomic_file.zig");189 _ = @import("io/buffered_atomic_file.zig");
163 _ = @import("io/buffered_in_stream.zig");190 _ = @import("io/buffered_in_stream.zig");
164 _ = @import("io/buffered_out_stream.zig");191 _ = @import("io/buffered_writer.zig");
165 _ = @import("io/c_out_stream.zig");192 _ = @import("io/c_writer.zig");
166 _ = @import("io/counting_out_stream.zig");193 _ = @import("io/counting_writer.zig");
167 _ = @import("io/fixed_buffer_stream.zig");194 _ = @import("io/fixed_buffer_stream.zig");
168 _ = @import("io/in_stream.zig");195 _ = @import("io/in_stream.zig");
169 _ = @import("io/out_stream.zig");196 _ = @import("io/writer.zig");
170 _ = @import("io/peek_stream.zig");197 _ = @import("io/peek_stream.zig");
171 _ = @import("io/seekable_stream.zig");198 _ = @import("io/seekable_stream.zig");
172 _ = @import("io/serialization.zig");199 _ = @import("io/serialization.zig");
lib/std/io/bit_out_stream.zig+4-196
...@@ -1,197 +1,5 @@...@@ -1,197 +1,5 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.bit_writer.BitWriter`
2const builtin = std.builtin;2pub const BitOutStream = @import("./bit_writer.zig").BitWriter;
3const io = std.io;
4const testing = std.testing;
5const assert = std.debug.assert;
6const trait = std.meta.trait;
7const meta = std.meta;
8const math = std.math;
93
10/// Creates a stream which allows for writing bit fields to another stream4/// Deprecated: use `std.io.bit_writer.bitWriter`
11pub fn BitOutStream(endian: builtin.Endian, comptime OutStreamType: type) type {5pub const bitOutStream = @import("./bit_writer.zig").bitWriter;
12 return struct {
13 out_stream: OutStreamType,
14 bit_buffer: u8,
15 bit_count: u4,
16
17 pub const Error = OutStreamType.Error;
18 pub const OutStream = io.OutStream(*Self, Error, write);
19
20 const Self = @This();
21 const u8_bit_count = comptime meta.bitCount(u8);
22 const u4_bit_count = comptime meta.bitCount(u4);
23
24 pub fn init(out_stream: OutStreamType) Self {
25 return Self{
26 .out_stream = out_stream,
27 .bit_buffer = 0,
28 .bit_count = 0,
29 };
30 }
31
32 /// Write the specified number of bits to the stream from the least significant bits of
33 /// the specified unsigned int value. Bits will only be written to the stream when there
34 /// are enough to fill a byte.
35 pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
36 if (bits == 0) return;
37
38 const U = @TypeOf(value);
39 comptime assert(trait.isUnsignedInt(U));
40
41 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
42 // related to shifting and casting.
43 const u_bit_count = comptime meta.bitCount(U);
44 const buf_bit_count = bc: {
45 assert(u_bit_count >= bits);
46 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
47 };
48 const Buf = std.meta.Int(false, buf_bit_count);
49 const BufShift = math.Log2Int(Buf);
50
51 const buf_value = @intCast(Buf, value);
52
53 const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
54 var in_buffer = switch (endian) {
55 .Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
56 .Little => buf_value,
57 };
58 var in_bits = bits;
59
60 if (self.bit_count > 0) {
61 const bits_remaining = u8_bit_count - self.bit_count;
62 const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
63 switch (endian) {
64 .Big => {
65 const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
66 const v = @intCast(u8, in_buffer >> shift);
67 self.bit_buffer |= v;
68 in_buffer <<= n;
69 },
70 .Little => {
71 const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
72 self.bit_buffer |= v;
73 in_buffer >>= n;
74 },
75 }
76 self.bit_count += n;
77 in_bits -= n;
78
79 //if we didn't fill the buffer, it's because bits < bits_remaining;
80 if (self.bit_count != u8_bit_count) return;
81 try self.out_stream.writeByte(self.bit_buffer);
82 self.bit_buffer = 0;
83 self.bit_count = 0;
84 }
85 //at this point we know bit_buffer is empty
86
87 //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
88 while (in_bits >= u8_bit_count) {
89 switch (endian) {
90 .Big => {
91 const v = @intCast(u8, in_buffer >> high_byte_shift);
92 try self.out_stream.writeByte(v);
93 in_buffer <<= @intCast(u3, u8_bit_count - 1);
94 in_buffer <<= 1;
95 },
96 .Little => {
97 const v = @truncate(u8, in_buffer);
98 try self.out_stream.writeByte(v);
99 in_buffer >>= @intCast(u3, u8_bit_count - 1);
100 in_buffer >>= 1;
101 },
102 }
103 in_bits -= u8_bit_count;
104 }
105
106 if (in_bits > 0) {
107 self.bit_count = @intCast(u4, in_bits);
108 self.bit_buffer = switch (endian) {
109 .Big => @truncate(u8, in_buffer >> high_byte_shift),
110 .Little => @truncate(u8, in_buffer),
111 };
112 }
113 }
114
115 /// Flush any remaining bits to the stream.
116 pub fn flushBits(self: *Self) Error!void {
117 if (self.bit_count == 0) return;
118 try self.out_stream.writeByte(self.bit_buffer);
119 self.bit_buffer = 0;
120 self.bit_count = 0;
121 }
122
123 pub fn write(self: *Self, buffer: []const u8) Error!usize {
124 // TODO: I'm not sure this is a good idea, maybe flushBits should be forced
125 if (self.bit_count > 0) {
126 for (buffer) |b, i|
127 try self.writeBits(b, u8_bit_count);
128 return buffer.len;
129 }
130
131 return self.out_stream.write(buffer);
132 }
133
134 pub fn outStream(self: *Self) OutStream {
135 return .{ .context = self };
136 }
137 };
138}
139
140pub fn bitOutStream(
141 comptime endian: builtin.Endian,
142 underlying_stream: var,
143) BitOutStream(endian, @TypeOf(underlying_stream)) {
144 return BitOutStream(endian, @TypeOf(underlying_stream)).init(underlying_stream);
145}
146
147test "api coverage" {
148 var mem_be = [_]u8{0} ** 2;
149 var mem_le = [_]u8{0} ** 2;
150
151 var mem_out_be = io.fixedBufferStream(&mem_be);
152 var bit_stream_be = bitOutStream(.Big, mem_out_be.outStream());
153
154 try bit_stream_be.writeBits(@as(u2, 1), 1);
155 try bit_stream_be.writeBits(@as(u5, 2), 2);
156 try bit_stream_be.writeBits(@as(u128, 3), 3);
157 try bit_stream_be.writeBits(@as(u8, 4), 4);
158 try bit_stream_be.writeBits(@as(u9, 5), 5);
159 try bit_stream_be.writeBits(@as(u1, 1), 1);
160
161 testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
162
163 mem_out_be.pos = 0;
164
165 try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15);
166 try bit_stream_be.flushBits();
167 testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
168
169 mem_out_be.pos = 0;
170 try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16);
171 testing.expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
172
173 try bit_stream_be.writeBits(@as(u0, 0), 0);
174
175 var mem_out_le = io.fixedBufferStream(&mem_le);
176 var bit_stream_le = bitOutStream(.Little, mem_out_le.outStream());
177
178 try bit_stream_le.writeBits(@as(u2, 1), 1);
179 try bit_stream_le.writeBits(@as(u5, 2), 2);
180 try bit_stream_le.writeBits(@as(u128, 3), 3);
181 try bit_stream_le.writeBits(@as(u8, 4), 4);
182 try bit_stream_le.writeBits(@as(u9, 5), 5);
183 try bit_stream_le.writeBits(@as(u1, 1), 1);
184
185 testing.expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
186
187 mem_out_le.pos = 0;
188 try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15);
189 try bit_stream_le.flushBits();
190 testing.expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
191
192 mem_out_le.pos = 0;
193 try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16);
194 testing.expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
195
196 try bit_stream_le.writeBits(@as(u0, 0), 0);
197}
lib/std/io/bit_writer.zig created+203
...@@ -0,0 +1,203 @@
1const std = @import("../std.zig");
2const builtin = std.builtin;
3const io = std.io;
4const testing = std.testing;
5const assert = std.debug.assert;
6const trait = std.meta.trait;
7const meta = std.meta;
8const math = std.math;
9
10/// Creates a stream which allows for writing bit fields to another stream
11pub fn BitWriter(endian: builtin.Endian, comptime WriterType: type) type {
12 return struct {
13 forward_writer: WriterType,
14 bit_buffer: u8,
15 bit_count: u4,
16
17 pub const Error = WriterType.Error;
18 pub const Writer = io.Writer(*Self, Error, write);
19 /// Deprecated: use `Writer`
20 pub const OutStream = io.OutStream(*Self, Error, write);
21
22 const Self = @This();
23 const u8_bit_count = comptime meta.bitCount(u8);
24 const u4_bit_count = comptime meta.bitCount(u4);
25
26 pub fn init(forward_writer: WriterType) Self {
27 return Self{
28 .forward_writer = forward_writer,
29 .bit_buffer = 0,
30 .bit_count = 0,
31 };
32 }
33
34 /// Write the specified number of bits to the stream from the least significant bits of
35 /// the specified unsigned int value. Bits will only be written to the stream when there
36 /// are enough to fill a byte.
37 pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
38 if (bits == 0) return;
39
40 const U = @TypeOf(value);
41 comptime assert(trait.isUnsignedInt(U));
42
43 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
44 // related to shifting and casting.
45 const u_bit_count = comptime meta.bitCount(U);
46 const buf_bit_count = bc: {
47 assert(u_bit_count >= bits);
48 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
49 };
50 const Buf = std.meta.Int(false, buf_bit_count);
51 const BufShift = math.Log2Int(Buf);
52
53 const buf_value = @intCast(Buf, value);
54
55 const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
56 var in_buffer = switch (endian) {
57 .Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
58 .Little => buf_value,
59 };
60 var in_bits = bits;
61
62 if (self.bit_count > 0) {
63 const bits_remaining = u8_bit_count - self.bit_count;
64 const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
65 switch (endian) {
66 .Big => {
67 const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
68 const v = @intCast(u8, in_buffer >> shift);
69 self.bit_buffer |= v;
70 in_buffer <<= n;
71 },
72 .Little => {
73 const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
74 self.bit_buffer |= v;
75 in_buffer >>= n;
76 },
77 }
78 self.bit_count += n;
79 in_bits -= n;
80
81 //if we didn't fill the buffer, it's because bits < bits_remaining;
82 if (self.bit_count != u8_bit_count) return;
83 try self.forward_writer.writeByte(self.bit_buffer);
84 self.bit_buffer = 0;
85 self.bit_count = 0;
86 }
87 //at this point we know bit_buffer is empty
88
89 //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
90 while (in_bits >= u8_bit_count) {
91 switch (endian) {
92 .Big => {
93 const v = @intCast(u8, in_buffer >> high_byte_shift);
94 try self.forward_writer.writeByte(v);
95 in_buffer <<= @intCast(u3, u8_bit_count - 1);
96 in_buffer <<= 1;
97 },
98 .Little => {
99 const v = @truncate(u8, in_buffer);
100 try self.forward_writer.writeByte(v);
101 in_buffer >>= @intCast(u3, u8_bit_count - 1);
102 in_buffer >>= 1;
103 },
104 }
105 in_bits -= u8_bit_count;
106 }
107
108 if (in_bits > 0) {
109 self.bit_count = @intCast(u4, in_bits);
110 self.bit_buffer = switch (endian) {
111 .Big => @truncate(u8, in_buffer >> high_byte_shift),
112 .Little => @truncate(u8, in_buffer),
113 };
114 }
115 }
116
117 /// Flush any remaining bits to the stream.
118 pub fn flushBits(self: *Self) Error!void {
119 if (self.bit_count == 0) return;
120 try self.forward_writer.writeByte(self.bit_buffer);
121 self.bit_buffer = 0;
122 self.bit_count = 0;
123 }
124
125 pub fn write(self: *Self, buffer: []const u8) Error!usize {
126 // TODO: I'm not sure this is a good idea, maybe flushBits should be forced
127 if (self.bit_count > 0) {
128 for (buffer) |b, i|
129 try self.writeBits(b, u8_bit_count);
130 return buffer.len;
131 }
132
133 return self.forward_writer.write(buffer);
134 }
135
136 pub fn writer(self: *Self) Writer {
137 return .{ .context = self };
138 }
139 /// Deprecated: use `writer`
140 pub fn outStream(self: *Self) OutStream {
141 return .{ .context = self };
142 }
143 };
144}
145
146pub fn bitWriter(
147 comptime endian: builtin.Endian,
148 underlying_stream: var,
149) BitWriter(endian, @TypeOf(underlying_stream)) {
150 return BitWriter(endian, @TypeOf(underlying_stream)).init(underlying_stream);
151}
152
153test "api coverage" {
154 var mem_be = [_]u8{0} ** 2;
155 var mem_le = [_]u8{0} ** 2;
156
157 var mem_out_be = io.fixedBufferStream(&mem_be);
158 var bit_stream_be = bitWriter(.Big, mem_out_be.writer());
159
160 try bit_stream_be.writeBits(@as(u2, 1), 1);
161 try bit_stream_be.writeBits(@as(u5, 2), 2);
162 try bit_stream_be.writeBits(@as(u128, 3), 3);
163 try bit_stream_be.writeBits(@as(u8, 4), 4);
164 try bit_stream_be.writeBits(@as(u9, 5), 5);
165 try bit_stream_be.writeBits(@as(u1, 1), 1);
166
167 testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
168
169 mem_out_be.pos = 0;
170
171 try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15);
172 try bit_stream_be.flushBits();
173 testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
174
175 mem_out_be.pos = 0;
176 try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16);
177 testing.expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
178
179 try bit_stream_be.writeBits(@as(u0, 0), 0);
180
181 var mem_out_le = io.fixedBufferStream(&mem_le);
182 var bit_stream_le = bitWriter(.Little, mem_out_le.writer());
183
184 try bit_stream_le.writeBits(@as(u2, 1), 1);
185 try bit_stream_le.writeBits(@as(u5, 2), 2);
186 try bit_stream_le.writeBits(@as(u128, 3), 3);
187 try bit_stream_le.writeBits(@as(u8, 4), 4);
188 try bit_stream_le.writeBits(@as(u9, 5), 5);
189 try bit_stream_le.writeBits(@as(u1, 1), 1);
190
191 testing.expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
192
193 mem_out_le.pos = 0;
194 try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15);
195 try bit_stream_le.flushBits();
196 testing.expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
197
198 mem_out_le.pos = 0;
199 try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16);
200 testing.expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
201
202 try bit_stream_le.writeBits(@as(u0, 0), 0);
203}
lib/std/io/buffered_atomic_file.zig+1-1
...@@ -34,7 +34,7 @@ pub const BufferedAtomicFile = struct {...@@ -34,7 +34,7 @@ pub const BufferedAtomicFile = struct {
34 errdefer self.atomic_file.deinit();34 errdefer self.atomic_file.deinit();
3535
36 self.file_stream = self.atomic_file.file.outStream();36 self.file_stream = self.atomic_file.file.outStream();
37 self.buffered_stream = .{ .unbuffered_out_stream = self.file_stream };37 self.buffered_stream = .{ .unbuffered_writer = self.file_stream };
38 return self;38 return self;
39 }39 }
4040
lib/std/io/buffered_out_stream.zig+4-40
...@@ -1,41 +1,5 @@...@@ -1,41 +1,5 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.buffered_writer.BufferedWriter`
2const io = std.io;2pub const BufferedOutStream = @import("./buffered_writer.zig").BufferedWriter;
33
4pub fn BufferedOutStream(comptime buffer_size: usize, comptime OutStreamType: type) type {4/// Deprecated: use `std.io.buffered_writer.bufferedWriter`
5 return struct {5pub const bufferedOutStream = @import("./buffered_writer.zig").bufferedWriter
6 unbuffered_out_stream: OutStreamType,
7 fifo: FifoType = FifoType.init(),
8
9 pub const Error = OutStreamType.Error;
10 pub const OutStream = io.OutStream(*Self, Error, write);
11
12 const Self = @This();
13 const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
14
15 pub fn flush(self: *Self) !void {
16 while (true) {
17 const slice = self.fifo.readableSlice(0);
18 if (slice.len == 0) break;
19 try self.unbuffered_out_stream.writeAll(slice);
20 self.fifo.discard(slice.len);
21 }
22 }
23
24 pub fn outStream(self: *Self) OutStream {
25 return .{ .context = self };
26 }
27
28 pub fn write(self: *Self, bytes: []const u8) Error!usize {
29 if (bytes.len >= self.fifo.writableLength()) {
30 try self.flush();
31 return self.unbuffered_out_stream.write(bytes);
32 }
33 self.fifo.writeAssumeCapacity(bytes);
34 return bytes.len;
35 }
36 };
37}
38
39pub fn bufferedOutStream(underlying_stream: var) BufferedOutStream(4096, @TypeOf(underlying_stream)) {
40 return .{ .unbuffered_out_stream = underlying_stream };
41}
lib/std/io/buffered_writer.zig created+48
...@@ -0,0 +1,48 @@
1const std = @import("../std.zig");
2const io = std.io;
3
4pub fn BufferedWriter(comptime buffer_size: usize, comptime WriterType: type) type {
5 return struct {
6 unbuffered_writer: WriterType,
7 fifo: FifoType = FifoType.init(),
8
9 pub const Error = WriterType.Error;
10 pub const Writer = io.Writer(*Self, Error, write);
11 /// Deprecated: use `Writer`
12 pub const OutStream = Writer;
13
14 const Self = @This();
15 const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
16
17 pub fn flush(self: *Self) !void {
18 while (true) {
19 const slice = self.fifo.readableSlice(0);
20 if (slice.len == 0) break;
21 try self.unbuffered_writer.writeAll(slice);
22 self.fifo.discard(slice.len);
23 }
24 }
25
26 pub fn writer(self: *Self) Writer {
27 return .{ .context = self };
28 }
29
30 /// Deprecated: use writer
31 pub fn outStream(self: *Self) Writer {
32 return .{ .context = self };
33 }
34
35 pub fn write(self: *Self, bytes: []const u8) Error!usize {
36 if (bytes.len >= self.fifo.writableLength()) {
37 try self.flush();
38 return self.unbuffered_writer.write(bytes);
39 }
40 self.fifo.writeAssumeCapacity(bytes);
41 return bytes.len;
42 }
43 };
44}
45
46pub fn bufferedWriter(underlying_stream: var) BufferedWriter(4096, @TypeOf(underlying_stream)) {
47 return .{ .unbuffered_writer = underlying_stream };
48}
lib/std/io/c_out_stream.zig+4-43
...@@ -1,44 +1,5 @@...@@ -1,44 +1,5 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.c_writer.CWriter`
2const builtin = std.builtin;2pub const COutStream = @import("./c_writer.zig").CWriter;
3const io = std.io;
4const testing = std.testing;
53
6pub const COutStream = io.OutStream(*std.c.FILE, std.fs.File.WriteError, cOutStreamWrite);4/// Deprecated: use `std.io.c_writer.cWriter`
75pub const cOutStream = @import("./c_writer.zig").cWriter;
8pub fn cOutStream(c_file: *std.c.FILE) COutStream {
9 return .{ .context = c_file };
10}
11
12fn cOutStreamWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!usize {
13 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, c_file);
14 if (amt_written >= 0) return amt_written;
15 switch (std.c._errno().*) {
16 0 => unreachable,
17 os.EINVAL => unreachable,
18 os.EFAULT => unreachable,
19 os.EAGAIN => unreachable, // this is a blocking API
20 os.EBADF => unreachable, // always a race condition
21 os.EDESTADDRREQ => unreachable, // connect was never called
22 os.EDQUOT => return error.DiskQuota,
23 os.EFBIG => return error.FileTooBig,
24 os.EIO => return error.InputOutput,
25 os.ENOSPC => return error.NoSpaceLeft,
26 os.EPERM => return error.AccessDenied,
27 os.EPIPE => return error.BrokenPipe,
28 else => |err| return os.unexpectedErrno(@intCast(usize, err)),
29 }
30}
31
32test "" {
33 if (!builtin.link_libc) return error.SkipZigTest;
34
35 const filename = "tmp_io_test_file.txt";
36 const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
37 defer {
38 _ = std.c.fclose(out_file);
39 std.fs.cwd().deleteFileZ(filename) catch {};
40 }
41
42 const out_stream = cOutStream(out_file);
43 try out_stream.print("hi: {}\n", .{@as(i32, 123)});
44}
lib/std/io/c_writer.zig created+44
...@@ -0,0 +1,44 @@
1const std = @import("../std.zig");
2const builtin = std.builtin;
3const io = std.io;
4const testing = std.testing;
5
6pub const CWriter = io.Writer(*std.c.FILE, std.fs.File.WriteError, cWriterWrite);
7
8pub fn cWriter(c_file: *std.c.FILE) CWriter {
9 return .{ .context = c_file };
10}
11
12fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!usize {
13 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, c_file);
14 if (amt_written >= 0) return amt_written;
15 switch (std.c._errno().*) {
16 0 => unreachable,
17 os.EINVAL => unreachable,
18 os.EFAULT => unreachable,
19 os.EAGAIN => unreachable, // this is a blocking API
20 os.EBADF => unreachable, // always a race condition
21 os.EDESTADDRREQ => unreachable, // connect was never called
22 os.EDQUOT => return error.DiskQuota,
23 os.EFBIG => return error.FileTooBig,
24 os.EIO => return error.InputOutput,
25 os.ENOSPC => return error.NoSpaceLeft,
26 os.EPERM => return error.AccessDenied,
27 os.EPIPE => return error.BrokenPipe,
28 else => |err| return os.unexpectedErrno(@intCast(usize, err)),
29 }
30}
31
32test "" {
33 if (!builtin.link_libc) return error.SkipZigTest;
34
35 const filename = "tmp_io_test_file.txt";
36 const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
37 defer {
38 _ = std.c.fclose(out_file);
39 std.fs.cwd().deleteFileZ(filename) catch {};
40 }
41
42 const writer = cWriter(out_file);
43 try writer.print("hi: {}\n", .{@as(i32, 123)});
44}
lib/std/io/counting_out_stream.zig+4-38
...@@ -1,39 +1,5 @@...@@ -1,39 +1,5 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.counting_writer.CountingWriter`
2const io = std.io;2pub const CountingOutStream = @import("./counting_writer.zig").CountingWriter;
3const testing = std.testing;
43
5/// An OutStream that counts how many bytes has been written to it.4/// Deprecated: use `std.io.counting_writer.countingWriter`
6pub fn CountingOutStream(comptime OutStreamType: type) type {5pub const countingOutStream = @import("./counting_writer.zig").countingWriter;
7 return struct {
8 bytes_written: u64,
9 child_stream: OutStreamType,
10
11 pub const Error = OutStreamType.Error;
12 pub const OutStream = io.OutStream(*Self, Error, write);
13
14 const Self = @This();
15
16 pub fn write(self: *Self, bytes: []const u8) Error!usize {
17 const amt = try self.child_stream.write(bytes);
18 self.bytes_written += amt;
19 return amt;
20 }
21
22 pub fn outStream(self: *Self) OutStream {
23 return .{ .context = self };
24 }
25 };
26}
27
28pub fn countingOutStream(child_stream: var) CountingOutStream(@TypeOf(child_stream)) {
29 return .{ .bytes_written = 0, .child_stream = child_stream };
30}
31
32test "io.CountingOutStream" {
33 var counting_stream = countingOutStream(std.io.null_out_stream);
34 const stream = counting_stream.outStream();
35
36 const bytes = "yay" ** 100;
37 stream.writeAll(bytes) catch unreachable;
38 testing.expect(counting_stream.bytes_written == bytes.len);
39}
lib/std/io/counting_writer.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("../std.zig");
2const io = std.io;
3const testing = std.testing;
4
5/// A Writer that counts how many bytes has been written to it.
6pub fn CountingWriter(comptime WriterType: type) type {
7 return struct {
8 bytes_written: u64,
9 child_stream: WriterType,
10
11 pub const Error = WriterType.Error;
12 pub const Writer = io.Writer(*Self, Error, write);
13 /// Deprecated: use `Writer`
14 pub const OutStream = Writer;
15
16 const Self = @This();
17
18 pub fn write(self: *Self, bytes: []const u8) Error!usize {
19 const amt = try self.child_stream.write(bytes);
20 self.bytes_written += amt;
21 return amt;
22 }
23
24 pub fn writer(self: *Self) Writer {
25 return .{ .context = self };
26 }
27
28 /// Deprecated: use `writer`
29 pub fn outStream(self: *Self) OutStream {
30 return .{ .context = self };
31 }
32 };
33}
34
35pub fn countingWriter(child_stream: var) CountingWriter(@TypeOf(child_stream)) {
36 return .{ .bytes_written = 0, .child_stream = child_stream };
37}
38
39test "io.CountingWriter" {
40 var counting_stream = countingWriter(std.io.null_writer);
41 const stream = counting_stream.writer();
42
43 const bytes = "yay" ** 100;
44 stream.writeAll(bytes) catch unreachable;
45 testing.expect(counting_stream.bytes_written == bytes.len);
46}
lib/std/io/fixed_buffer_stream.zig+13-6
...@@ -18,7 +18,9 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -18,7 +18,9 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
18 pub const GetSeekPosError = error{};18 pub const GetSeekPosError = error{};
1919
20 pub const InStream = io.InStream(*Self, ReadError, read);20 pub const InStream = io.InStream(*Self, ReadError, read);
21 pub const OutStream = io.OutStream(*Self, WriteError, write);21 pub const Writer = io.Writer(*Self, WriteError, write);
22 /// Deprecated: use `Writer`
23 pub const OutStream = Writer;
2224
23 pub const SeekableStream = io.SeekableStream(25 pub const SeekableStream = io.SeekableStream(
24 *Self,26 *Self,
...@@ -36,6 +38,11 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -36,6 +38,11 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
36 return .{ .context = self };38 return .{ .context = self };
37 }39 }
3840
41 pub fn writer(self: *Self) Writer {
42 return .{ .context = self };
43 }
44
45 /// Deprecated: use `writer`
39 pub fn outStream(self: *Self) OutStream {46 pub fn outStream(self: *Self) OutStream {
40 return .{ .context = self };47 return .{ .context = self };
41 }48 }
...@@ -126,7 +133,7 @@ fn NonSentinelSpan(comptime T: type) type {...@@ -126,7 +133,7 @@ fn NonSentinelSpan(comptime T: type) type {
126test "FixedBufferStream output" {133test "FixedBufferStream output" {
127 var buf: [255]u8 = undefined;134 var buf: [255]u8 = undefined;
128 var fbs = fixedBufferStream(&buf);135 var fbs = fixedBufferStream(&buf);
129 const stream = fbs.outStream();136 const stream = fbs.writer();
130137
131 try stream.print("{}{}!", .{ "Hello", "World" });138 try stream.print("{}{}!", .{ "Hello", "World" });
132 testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());139 testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten());
...@@ -136,19 +143,19 @@ test "FixedBufferStream output 2" {...@@ -136,19 +143,19 @@ test "FixedBufferStream output 2" {
136 var buffer: [10]u8 = undefined;143 var buffer: [10]u8 = undefined;
137 var fbs = fixedBufferStream(&buffer);144 var fbs = fixedBufferStream(&buffer);
138145
139 try fbs.outStream().writeAll("Hello");146 try fbs.writer().writeAll("Hello");
140 testing.expect(mem.eql(u8, fbs.getWritten(), "Hello"));147 testing.expect(mem.eql(u8, fbs.getWritten(), "Hello"));
141148
142 try fbs.outStream().writeAll("world");149 try fbs.writer().writeAll("world");
143 testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));150 testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
144151
145 testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("!"));152 testing.expectError(error.NoSpaceLeft, fbs.writer().writeAll("!"));
146 testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));153 testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld"));
147154
148 fbs.reset();155 fbs.reset();
149 testing.expect(fbs.getWritten().len == 0);156 testing.expect(fbs.getWritten().len == 0);
150157
151 testing.expectError(error.NoSpaceLeft, fbs.outStream().writeAll("Hello world!"));158 testing.expectError(error.NoSpaceLeft, fbs.writer().writeAll("Hello world!"));
152 testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl"));159 testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl"));
153}160}
154161
lib/std/io/multi_out_stream.zig+4-50
...@@ -1,51 +1,5 @@...@@ -1,51 +1,5 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.multi_writer.MultiWriter`
2const io = std.io;2pub const MultiOutStream = @import("./multi_writer.zig").MultiWriter;
3const testing = std.testing;
43
5/// Takes a tuple of streams, and constructs a new stream that writes to all of them4/// Deprecated: use `std.io.multi_writer.multiWriter`
6pub fn MultiOutStream(comptime OutStreams: type) type {5pub const multiOutStream = @import("./multi_writer.zig").multiWriter;
7 comptime var ErrSet = error{};
8 inline for (@typeInfo(OutStreams).Struct.fields) |field| {
9 const StreamType = field.field_type;
10 ErrSet = ErrSet || StreamType.Error;
11 }
12
13 return struct {
14 const Self = @This();
15
16 streams: OutStreams,
17
18 pub const Error = ErrSet;
19 pub const OutStream = io.OutStream(*Self, Error, write);
20 pub fn outStream(self: *Self) OutStream {
21 return .{ .context = self };
22 }
23
24 pub fn write(self: *Self, bytes: []const u8) Error!usize {
25 var batch = std.event.Batch(Error!void, self.streams.len, .auto_async).init();
26 comptime var i = 0;
27 inline while (i < self.streams.len) : (i += 1) {
28 const stream = self.streams[i];
29 // TODO: remove ptrCast: https://github.com/ziglang/zig/issues/5258
30 batch.add(@ptrCast(anyframe->Error!void, &async stream.writeAll(bytes)));
31 }
32 try batch.wait();
33 return bytes.len;
34 }
35 };
36}
37
38pub fn multiOutStream(streams: var) MultiOutStream(@TypeOf(streams)) {
39 return .{ .streams = streams };
40}
41
42test "MultiOutStream" {
43 var buf1: [255]u8 = undefined;
44 var fbs1 = io.fixedBufferStream(&buf1);
45 var buf2: [255]u8 = undefined;
46 var fbs2 = io.fixedBufferStream(&buf2);
47 var stream = multiOutStream(.{ fbs1.outStream(), fbs2.outStream() });
48 try stream.outStream().print("HI", .{});
49 testing.expectEqualSlices(u8, "HI", fbs1.getWritten());
50 testing.expectEqualSlices(u8, "HI", fbs2.getWritten());
51}
lib/std/io/multi_writer.zig created+59
...@@ -0,0 +1,59 @@
1const std = @import("../std.zig");
2const io = std.io;
3const testing = std.testing;
4
5/// Takes a tuple of streams, and constructs a new stream that writes to all of them
6pub fn MultiWriter(comptime Writers: type) type {
7 comptime var ErrSet = error{};
8 inline for (@typeInfo(Writers).Struct.fields) |field| {
9 const StreamType = field.field_type;
10 ErrSet = ErrSet || StreamType.Error;
11 }
12
13 return struct {
14 const Self = @This();
15
16 streams: Writers,
17
18 pub const Error = ErrSet;
19 pub const Writer = io.Writer(*Self, Error, write);
20 /// Deprecated: use `Writer`
21 pub const OutStream = Writer;
22
23 pub fn writer(self: *Self) Writer {
24 return .{ .context = self };
25 }
26
27 /// Deprecated: use `writer`
28 pub fn outStream(self: *Self) OutStream {
29 return .{ .context = self };
30 }
31
32 pub fn write(self: *Self, bytes: []const u8) Error!usize {
33 var batch = std.event.Batch(Error!void, self.streams.len, .auto_async).init();
34 comptime var i = 0;
35 inline while (i < self.streams.len) : (i += 1) {
36 const stream = self.streams[i];
37 // TODO: remove ptrCast: https://github.com/ziglang/zig/issues/5258
38 batch.add(@ptrCast(anyframe->Error!void, &async stream.writeAll(bytes)));
39 }
40 try batch.wait();
41 return bytes.len;
42 }
43 };
44}
45
46pub fn multiWriter(streams: var) MultiWriter(@TypeOf(streams)) {
47 return .{ .streams = streams };
48}
49
50test "MultiWriter" {
51 var buf1: [255]u8 = undefined;
52 var fbs1 = io.fixedBufferStream(&buf1);
53 var buf2: [255]u8 = undefined;
54 var fbs2 = io.fixedBufferStream(&buf2);
55 var stream = multiWriter(.{ fbs1.writer(), fbs2.writer() });
56 try stream.writer().print("HI", .{});
57 testing.expectEqualSlices(u8, "HI", fbs1.getWritten());
58 testing.expectEqualSlices(u8, "HI", fbs2.getWritten());
59}
lib/std/io/out_stream.zig+2-85
...@@ -1,85 +1,2 @@...@@ -1,85 +1,2 @@
1const std = @import("../std.zig");1/// Deprecated: use `std.io.writer.Writer`
2const builtin = std.builtin;2pub const OutStream = @import("./writer.zig").Writer;
3const mem = std.mem;
4
5pub fn OutStream(
6 comptime Context: type,
7 comptime WriteError: type,
8 comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
9) type {
10 return struct {
11 context: Context,
12
13 const Self = @This();
14 pub const Error = WriteError;
15
16 pub fn write(self: Self, bytes: []const u8) Error!usize {
17 return writeFn(self.context, bytes);
18 }
19
20 pub fn writeAll(self: Self, bytes: []const u8) Error!void {
21 var index: usize = 0;
22 while (index != bytes.len) {
23 index += try self.write(bytes[index..]);
24 }
25 }
26
27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
28 return std.fmt.format(self, format, args);
29 }
30
31 pub fn writeByte(self: Self, byte: u8) Error!void {
32 const array = [1]u8{byte};
33 return self.writeAll(&array);
34 }
35
36 pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
37 var bytes: [256]u8 = undefined;
38 mem.set(u8, bytes[0..], byte);
39
40 var remaining: usize = n;
41 while (remaining > 0) {
42 const to_write = std.math.min(remaining, bytes.len);
43 try self.writeAll(bytes[0..to_write]);
44 remaining -= to_write;
45 }
46 }
47
48 /// Write a native-endian integer.
49 /// TODO audit non-power-of-two int sizes
50 pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {
51 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
52 mem.writeIntNative(T, &bytes, value);
53 return self.writeAll(&bytes);
54 }
55
56 /// Write a foreign-endian integer.
57 /// TODO audit non-power-of-two int sizes
58 pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {
59 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
60 mem.writeIntForeign(T, &bytes, value);
61 return self.writeAll(&bytes);
62 }
63
64 /// TODO audit non-power-of-two int sizes
65 pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {
66 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
67 mem.writeIntLittle(T, &bytes, value);
68 return self.writeAll(&bytes);
69 }
70
71 /// TODO audit non-power-of-two int sizes
72 pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {
73 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
74 mem.writeIntBig(T, &bytes, value);
75 return self.writeAll(&bytes);
76 }
77
78 /// TODO audit non-power-of-two int sizes
79 pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
80 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
81 mem.writeInt(T, &bytes, value, endian);
82 return self.writeAll(&bytes);
83 }
84 };
85}
lib/std/io/writer.zig created+85
...@@ -0,0 +1,85 @@
1const std = @import("../std.zig");
2const builtin = std.builtin;
3const mem = std.mem;
4
5pub fn Writer(
6 comptime Context: type,
7 comptime WriteError: type,
8 comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
9) type {
10 return struct {
11 context: Context,
12
13 const Self = @This();
14 pub const Error = WriteError;
15
16 pub fn write(self: Self, bytes: []const u8) Error!usize {
17 return writeFn(self.context, bytes);
18 }
19
20 pub fn writeAll(self: Self, bytes: []const u8) Error!void {
21 var index: usize = 0;
22 while (index != bytes.len) {
23 index += try self.write(bytes[index..]);
24 }
25 }
26
27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
28 return std.fmt.format(self, format, args);
29 }
30
31 pub fn writeByte(self: Self, byte: u8) Error!void {
32 const array = [1]u8{byte};
33 return self.writeAll(&array);
34 }
35
36 pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
37 var bytes: [256]u8 = undefined;
38 mem.set(u8, bytes[0..], byte);
39
40 var remaining: usize = n;
41 while (remaining > 0) {
42 const to_write = std.math.min(remaining, bytes.len);
43 try self.writeAll(bytes[0..to_write]);
44 remaining -= to_write;
45 }
46 }
47
48 /// Write a native-endian integer.
49 /// TODO audit non-power-of-two int sizes
50 pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {
51 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
52 mem.writeIntNative(T, &bytes, value);
53 return self.writeAll(&bytes);
54 }
55
56 /// Write a foreign-endian integer.
57 /// TODO audit non-power-of-two int sizes
58 pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {
59 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
60 mem.writeIntForeign(T, &bytes, value);
61 return self.writeAll(&bytes);
62 }
63
64 /// TODO audit non-power-of-two int sizes
65 pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {
66 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
67 mem.writeIntLittle(T, &bytes, value);
68 return self.writeAll(&bytes);
69 }
70
71 /// TODO audit non-power-of-two int sizes
72 pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {
73 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
74 mem.writeIntBig(T, &bytes, value);
75 return self.writeAll(&bytes);
76 }
77
78 /// TODO audit non-power-of-two int sizes
79 pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
80 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
81 mem.writeInt(T, &bytes, value, endian);
82 return self.writeAll(&bytes);
83 }
84 };
85}
lib/std/zig/render.zig+1-1
...@@ -49,7 +49,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(...@@ -49,7 +49,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(
49 .source_index = 0,49 .source_index = 0,
50 .source = tree.source,50 .source = tree.source,
51 };51 };
52 const my_stream_stream: std.io.OutStream(*MyStream, MyStream.StreamError, MyStream.write) = .{52 const my_stream_stream: std.io.Writer(*MyStream, MyStream.StreamError, MyStream.write) = .{
53 .context = &my_stream,53 .context = &my_stream,
54 };54 };
5555