@@ -10,6 +10,7 @@ const fs = std.fs;
10
10
const mem = std .mem ;
11
11
const meta = std .meta ;
12
12
const File = std .fs .File ;
13
+ const Allocator = std .mem .Allocator ;
13
14
14
15
pub const Mode = enum {
15
16
/// I/O operates normally, waiting for the operating system syscalls to complete.
@@ -105,7 +106,255 @@ pub fn getStdIn() File {
105
106
};
106
107
}
107
108
108
- pub const Reader = @import ("io/reader.zig" ).Reader ;
109
+ pub fn GenericReader (
110
+ comptime Context : type ,
111
+ comptime ReadError : type ,
112
+ /// Returns the number of bytes read. It may be less than buffer.len.
113
+ /// If the number of bytes read is 0, it means end of stream.
114
+ /// End of stream is not an error condition.
115
+ comptime readFn : fn (context : Context , buffer : []u8 ) ReadError ! usize ,
116
+ ) type {
117
+ return struct {
118
+ context : Context ,
119
+
120
+ pub const Error = ReadError ;
121
+ pub const NoEofError = ReadError || error {
122
+ EndOfStream ,
123
+ };
124
+
125
+ pub inline fn read (self : Self , buffer : []u8 ) Error ! usize {
126
+ return readFn (self .context , buffer );
127
+ }
128
+
129
+ pub inline fn readAll (self : Self , buffer : []u8 ) Error ! usize {
130
+ return @errorCast (self .typeErased ().readAll (buffer ));
131
+ }
132
+
133
+ pub inline fn readAtLeast (self : Self , buffer : []u8 , len : usize ) Error ! usize {
134
+ return @errorCast (self .typeErased ().readAtLeast (buffer , len ));
135
+ }
136
+
137
+ pub inline fn readNoEof (self : Self , buf : []u8 ) NoEofError ! void {
138
+ return @errorCast (self .typeErased ().readNoEof (buf ));
139
+ }
140
+
141
+ pub inline fn readAllArrayList (
142
+ self : Self ,
143
+ array_list : * std .ArrayList (u8 ),
144
+ max_append_size : usize ,
145
+ ) (error {StreamTooLong } || Error )! void {
146
+ return @errorCast (self .typeErased ().readAllArrayList (array_list , max_append_size ));
147
+ }
148
+
149
+ pub inline fn readAllArrayListAligned (
150
+ self : Self ,
151
+ comptime alignment : ? u29 ,
152
+ array_list : * std .ArrayListAligned (u8 , alignment ),
153
+ max_append_size : usize ,
154
+ ) (error {StreamTooLong } || Error )! void {
155
+ return @errorCast (self .typeErased ().readAllArrayListAligned (
156
+ alignment ,
157
+ array_list ,
158
+ max_append_size ,
159
+ ));
160
+ }
161
+
162
+ pub inline fn readAllAlloc (
163
+ self : Self ,
164
+ allocator : Allocator ,
165
+ max_size : usize ,
166
+ ) (Error || error {StreamTooLong })! []u8 {
167
+ return @errorCast (self .typeErased ().readAllAlloc (allocator , max_size ));
168
+ }
169
+
170
+ pub inline fn readUntilDelimiterArrayList (
171
+ self : Self ,
172
+ array_list : * std .ArrayList (u8 ),
173
+ delimiter : u8 ,
174
+ max_size : usize ,
175
+ ) (NoEofError || error {StreamTooLong })! void {
176
+ return @errorCast (self .typeErased ().readUntilDelimiterArrayList (
177
+ array_list ,
178
+ delimiter ,
179
+ max_size ,
180
+ ));
181
+ }
182
+
183
+ pub inline fn readUntilDelimiterAlloc (
184
+ self : Self ,
185
+ allocator : Allocator ,
186
+ delimiter : u8 ,
187
+ max_size : usize ,
188
+ ) (NoEofError || error {StreamTooLong })! []u8 {
189
+ return @errorCast (self .typeErased ().readUntilDelimiterAlloc (
190
+ allocator ,
191
+ delimiter ,
192
+ max_size ,
193
+ ));
194
+ }
195
+
196
+ pub inline fn readUntilDelimiter (
197
+ self : Self ,
198
+ buf : []u8 ,
199
+ delimiter : u8 ,
200
+ ) (NoEofError || error {StreamTooLong })! []u8 {
201
+ return @errorCast (self .typeErased ().readUntilDelimiter (buf , delimiter ));
202
+ }
203
+
204
+ pub inline fn readUntilDelimiterOrEofAlloc (
205
+ self : Self ,
206
+ allocator : Allocator ,
207
+ delimiter : u8 ,
208
+ max_size : usize ,
209
+ ) (Error || error {StreamTooLong })! ? []u8 {
210
+ return @errorCast (self .typeErased ().readUntilDelimiterOrEofAlloc (
211
+ allocator ,
212
+ delimiter ,
213
+ max_size ,
214
+ ));
215
+ }
216
+
217
+ pub inline fn readUntilDelimiterOrEof (
218
+ self : Self ,
219
+ buf : []u8 ,
220
+ delimiter : u8 ,
221
+ ) (Error || error {StreamTooLong })! ? []u8 {
222
+ return @errorCast (self .typeErased ().readUntilDelimiterOrEof (buf , delimiter ));
223
+ }
224
+
225
+ pub inline fn streamUntilDelimiter (
226
+ self : Self ,
227
+ writer : anytype ,
228
+ delimiter : u8 ,
229
+ optional_max_size : ? usize ,
230
+ ) (NoEofError || error {StreamTooLong } || @TypeOf (writer ).Error )! void {
231
+ return @errorCast (self .typeErased ().streamUntilDelimiter (
232
+ writer ,
233
+ delimiter ,
234
+ optional_max_size ,
235
+ ));
236
+ }
237
+
238
+ pub inline fn skipUntilDelimiterOrEof (self : Self , delimiter : u8 ) Error ! void {
239
+ return @errorCast (self .typeErased ().skipUntilDelimiterOrEof (delimiter ));
240
+ }
241
+
242
+ pub inline fn readByte (self : Self ) NoEofError ! u8 {
243
+ return @errorCast (self .typeErased ().readByte ());
244
+ }
245
+
246
+ pub inline fn readByteSigned (self : Self ) NoEofError ! i8 {
247
+ return @errorCast (self .typeErased ().readByteSigned ());
248
+ }
249
+
250
+ pub inline fn readBytesNoEof (
251
+ self : Self ,
252
+ comptime num_bytes : usize ,
253
+ ) NoEofError ! [num_bytes ]u8 {
254
+ return @errorCast (self .typeErased ().readBytesNoEof (num_bytes ));
255
+ }
256
+
257
+ pub inline fn readIntoBoundedBytes (
258
+ self : Self ,
259
+ comptime num_bytes : usize ,
260
+ bounded : * std .BoundedArray (u8 , num_bytes ),
261
+ ) Error ! void {
262
+ return @errorCast (self .typeErased ().readIntoBoundedBytes (num_bytes , bounded ));
263
+ }
264
+
265
+ pub inline fn readBoundedBytes (
266
+ self : Self ,
267
+ comptime num_bytes : usize ,
268
+ ) Error ! std. BoundedArray (u8 , num_bytes ) {
269
+ return @errorCast (self .typeErased ().readBoundedBytes (num_bytes ));
270
+ }
271
+
272
+ pub inline fn readIntNative (self : Self , comptime T : type ) NoEofError ! T {
273
+ return @errorCast (self .typeErased ().readIntNative (T ));
274
+ }
275
+
276
+ pub inline fn readIntForeign (self : Self , comptime T : type ) NoEofError ! T {
277
+ return @errorCast (self .typeErased ().readIntForeign (T ));
278
+ }
279
+
280
+ pub inline fn readIntLittle (self : Self , comptime T : type ) NoEofError ! T {
281
+ return @errorCast (self .typeErased ().readIntLittle (T ));
282
+ }
283
+
284
+ pub inline fn readIntBig (self : Self , comptime T : type ) NoEofError ! T {
285
+ return @errorCast (self .typeErased ().readIntBig (T ));
286
+ }
287
+
288
+ pub inline fn readInt (self : Self , comptime T : type , endian : std.builtin.Endian ) NoEofError ! T {
289
+ return @errorCast (self .typeErased ().readInt (T , endian ));
290
+ }
291
+
292
+ pub inline fn readVarInt (
293
+ self : Self ,
294
+ comptime ReturnType : type ,
295
+ endian : std.builtin.Endian ,
296
+ size : usize ,
297
+ ) NoEofError ! ReturnType {
298
+ return @errorCast (self .typeErased ().readVarInt (ReturnType , endian , size ));
299
+ }
300
+
301
+ pub const SkipBytesOptions = TypeErasedReader .SkipBytesOptions ;
302
+
303
+ pub inline fn skipBytes (
304
+ self : Self ,
305
+ num_bytes : u64 ,
306
+ comptime options : SkipBytesOptions ,
307
+ ) NoEofError ! void {
308
+ return @errorCast (self .typeErased ().skipBytes (num_bytes , options ));
309
+ }
310
+
311
+ pub inline fn isBytes (self : Self , slice : []const u8 ) Error ! bool {
312
+ return @errorCast (self .typeErased ().isBytes (slice ));
313
+ }
314
+
315
+ pub fn readStruct (self : Self , comptime T : type ) Error ! T {
316
+ return @errorCast (self .typeErased ().readStruct (T ));
317
+ }
318
+
319
+ pub inline fn readStructBig (self : Self , comptime T : type ) Error ! T {
320
+ return @errorCast (self .typeErased ().readStructBig (T ));
321
+ }
322
+
323
+ pub const ReadEnumError = Error || error {
324
+ /// An integer was read, but it did not match any of the tags in the supplied enum.
325
+ InvalidValue ,
326
+ };
327
+
328
+ pub inline fn readEnum (
329
+ self : Self ,
330
+ comptime Enum : type ,
331
+ endian : std.builtin.Endian ,
332
+ ) ReadEnumError ! Enum {
333
+ return @errorCast (self .typeErased ().readEnum (Enum , endian ));
334
+ }
335
+
336
+ pub inline fn typeErased (self : * const Self ) TypeErasedReader {
337
+ return .{
338
+ .context = @ptrCast (& self .context ),
339
+ .readFn = typeErasedReadFn ,
340
+ };
341
+ }
342
+
343
+ const Self = @This ();
344
+
345
+ fn typeErasedReadFn (context : * const anyopaque , buffer : []u8 ) anyerror ! usize {
346
+ const ptr : * const Context = @alignCast (@ptrCast (context ));
347
+ return readFn (ptr .* , buffer );
348
+ }
349
+ };
350
+ }
351
+
352
+ /// Deprecated; consider switching to `TypeErasedReader` or use `GenericReader`
353
+ /// to use previous API.
354
+ pub const Reader = GenericReader ;
355
+
356
+ pub const TypeErasedReader = @import ("io/Reader.zig" );
357
+
109
358
pub const Writer = @import ("io/writer.zig" ).Writer ;
110
359
pub const SeekableStream = @import ("io/seekable_stream.zig" ).SeekableStream ;
111
360
@@ -168,7 +417,7 @@ test "null_writer" {
168
417
}
169
418
170
419
pub fn poll (
171
- allocator : std.mem. Allocator ,
420
+ allocator : Allocator ,
172
421
comptime StreamEnum : type ,
173
422
files : PollFiles (StreamEnum ),
174
423
) Poller (StreamEnum ) {
@@ -418,6 +667,7 @@ pub fn PollFiles(comptime StreamEnum: type) type {
418
667
}
419
668
420
669
test {
670
+ _ = TypeErasedReader ;
421
671
_ = @import ("io/bit_reader.zig" );
422
672
_ = @import ("io/bit_writer.zig" );
423
673
_ = @import ("io/buffered_atomic_file.zig" );
@@ -427,7 +677,6 @@ test {
427
677
_ = @import ("io/counting_writer.zig" );
428
678
_ = @import ("io/counting_reader.zig" );
429
679
_ = @import ("io/fixed_buffer_stream.zig" );
430
- _ = @import ("io/reader.zig" );
431
680
_ = @import ("io/writer.zig" );
432
681
_ = @import ("io/peek_stream.zig" );
433
682
_ = @import ("io/seekable_stream.zig" );
0 commit comments