@@ -10,6 +10,7 @@ const fs = std.fs;
1010const mem = std .mem ;
1111const meta = std .meta ;
1212const File = std .fs .File ;
13+ const Allocator = std .mem .Allocator ;
1314
1415pub const Mode = enum {
1516 /// I/O operates normally, waiting for the operating system syscalls to complete.
@@ -105,7 +106,240 @@ pub fn getStdIn() File {
105106 };
106107}
107108
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+
122+ pub inline fn read (self : Self , buffer : []u8 ) Error ! usize {
123+ return readFn (self .context , buffer );
124+ }
125+
126+ pub inline fn readAll (self : Self , buffer : []u8 ) Error ! usize {
127+ return @errSetCast (self .typeErased ().readAll (buffer ));
128+ }
129+
130+ pub inline fn readAtLeast (self : Self , buffer : []u8 , len : usize ) Error ! usize {
131+ return @errSetCast (self .typeErased ().readAtLeast (buffer , len ));
132+ }
133+
134+ pub inline fn readNoEof (self : Self , buf : []u8 ) (Error || error {EndOfStream })! void {
135+ return @errSetCast (self .typeErased ().readNoEof (buf ));
136+ }
137+
138+ pub inline fn readAllArrayList (
139+ self : Self ,
140+ array_list : * std .ArrayList (u8 ),
141+ max_append_size : usize ,
142+ ) (error {StreamTooLong } || Error )! void {
143+ return @errSetCast (self .typeErased ().readAllArrayList (array_list , max_append_size ));
144+ }
145+
146+ pub inline fn readAllArrayListAligned (
147+ self : Self ,
148+ comptime alignment : ? u29 ,
149+ array_list : * std .ArrayListAligned (u8 , alignment ),
150+ max_append_size : usize ,
151+ ) (error {StreamTooLong } || Error )! void {
152+ return @errSetCast (self .typeErased ().readAllArrayListAligned (
153+ alignment ,
154+ array_list ,
155+ max_append_size ,
156+ ));
157+ }
158+
159+ pub inline fn readAllAlloc (self : Self , allocator : Allocator , max_size : usize ) Error ! []u8 {
160+ return @errSetCast (self .typeErased ().readAllAlloc (allocator , max_size ));
161+ }
162+
163+ pub inline fn readUntilDelimiterArrayList (
164+ self : Self ,
165+ array_list : * std .ArrayList (u8 ),
166+ delimiter : u8 ,
167+ max_size : usize ,
168+ ) Error ! void {
169+ return @errSetCast (self .typeErased ().readUntilDelimiterArrayList (
170+ array_list ,
171+ delimiter ,
172+ max_size ,
173+ ));
174+ }
175+
176+ pub inline fn readUntilDelimiterAlloc (
177+ self : Self ,
178+ allocator : Allocator ,
179+ delimiter : u8 ,
180+ max_size : usize ,
181+ ) Error ! []u8 {
182+ return @errSetCast (self .typeErased ().readUntilDelimiterAlloc (
183+ allocator ,
184+ delimiter ,
185+ max_size ,
186+ ));
187+ }
188+
189+ pub inline fn readUntilDelimiter (self : Self , buf : []u8 , delimiter : u8 ) Error ! []u8 {
190+ return @errSetCast (self .typeErased ().readUntilDelimiter (buf , delimiter ));
191+ }
192+
193+ pub inline fn readUntilDelimiterOrEofAlloc (
194+ self : Self ,
195+ allocator : Allocator ,
196+ delimiter : u8 ,
197+ max_size : usize ,
198+ ) Error ! ? []u8 {
199+ return @errSetCast (self .typeErased ().readUntilDelimiterOrEofAlloc (
200+ allocator ,
201+ delimiter ,
202+ max_size ,
203+ ));
204+ }
205+
206+ pub inline fn readUntilDelimiterOrEof (self : Self , buf : []u8 , delimiter : u8 ) Error ! ? []u8 {
207+ return @errSetCast (self .typeErased ().readUntilDelimiterOrEof (buf , delimiter ));
208+ }
209+
210+ pub inline fn streamUntilDelimiter (
211+ self : Self ,
212+ writer : anytype ,
213+ delimiter : u8 ,
214+ optional_max_size : ? usize ,
215+ ) (Error || error { EndOfStream , StreamTooLong } || @TypeOf (writer ).Error )! void {
216+ return @errSetCast (self .typeErased ().streamUntilDelimiter (
217+ writer .typeErased (),
218+ delimiter ,
219+ optional_max_size ,
220+ ));
221+ }
222+
223+ pub inline fn skipUntilDelimiterOrEof (self : Self , delimiter : u8 ) Error ! void {
224+ return @errSetCast (self .typeErased ().skipUntilDelimiterOrEof (delimiter ));
225+ }
226+
227+ pub inline fn readByte (self : Self ) (Error || error {EndOfStream })! u8 {
228+ return @errSetCast (self .typeErased ().readByte ());
229+ }
230+
231+ pub inline fn readByteSigned (self : Self ) (Error || error {EndOfStream })! i8 {
232+ return @errSetCast (self .typeErased ().readByteSigned ());
233+ }
234+
235+ pub inline fn readBytesNoEof (
236+ self : Self ,
237+ comptime num_bytes : usize ,
238+ ) (Error || error {EndOfStream })! [num_bytes ]u8 {
239+ return @errSetCast (self .typeErased ().readBytesNoEof (num_bytes ));
240+ }
241+
242+ pub inline fn readIntoBoundedBytes (
243+ self : Self ,
244+ comptime num_bytes : usize ,
245+ bounded : * std .BoundedArray (u8 , num_bytes ),
246+ ) Error ! void {
247+ return @errSetCast (self .typeErased ().readIntoBoundedBytes (num_bytes , bounded ));
248+ }
249+
250+ pub inline fn readBoundedBytes (
251+ self : Self ,
252+ comptime num_bytes : usize ,
253+ ) Error ! std. BoundedArray (u8 , num_bytes ) {
254+ return @errSetCast (self .typeErased ().readBoundedBytes (num_bytes ));
255+ }
256+
257+ pub inline fn readIntNative (self : Self , comptime T : type ) (Error || error {EndOfStream })! T {
258+ return @errSetCast (self .typeErased ().readIntNative (T ));
259+ }
260+
261+ pub inline fn readIntForeign (self : Self , comptime T : type ) (Error || error {EndOfStream })! T {
262+ return @errSetCast (self .typeErased ().readIntForeign (T ));
263+ }
264+
265+ pub inline fn readIntLittle (self : Self , comptime T : type ) Error ! T {
266+ return @errSetCast (self .typeErased ().readIntLittle (T ));
267+ }
268+
269+ pub inline fn readIntBig (self : Self , comptime T : type ) Error ! T {
270+ return @errSetCast (self .typeErased ().readIntBig (T ));
271+ }
272+
273+ pub inline fn readInt (self : Self , comptime T : type , endian : std.builtin.Endian ) Error ! T {
274+ return @errSetCast (self .typeErased ().readInt (T , endian ));
275+ }
276+
277+ pub inline fn readVarInt (
278+ self : Self ,
279+ comptime ReturnType : type ,
280+ endian : std.builtin.Endian ,
281+ size : usize ,
282+ ) ! ReturnType {
283+ return @errSetCast (self .typeErased ().readVarInt (ReturnType , endian , size ));
284+ }
285+
286+ pub const SkipBytesOptions = TypeErasedReader .SkipBytesOptions ;
287+
288+ pub inline fn skipBytes (
289+ self : Self ,
290+ num_bytes : u64 ,
291+ comptime options : SkipBytesOptions ,
292+ ) Error ! void {
293+ return @errSetCast (self .typeErased ().skipBytes (num_bytes , options ));
294+ }
295+
296+ pub inline fn isBytes (self : Self , slice : []const u8 ) Error ! bool {
297+ return @errSetCast (self .typeErased ().isBytes (slice ));
298+ }
299+
300+ pub fn readStruct (self : Self , comptime T : type ) Error ! T {
301+ return @errSetCast (self .typeErased ().readStruct (T ));
302+ }
303+
304+ pub inline fn readStructBig (self : Self , comptime T : type ) Error ! T {
305+ return @errSetCast (self .typeErased ().readStructBig (T ));
306+ }
307+
308+ pub const ReadEnumError = Error || error {
309+ /// An integer was read, but it did not match any of the tags in the supplied enum.
310+ InvalidValue ,
311+ };
312+
313+ pub inline fn readEnum (
314+ self : Self ,
315+ comptime Enum : type ,
316+ endian : std.builtin.Endian ,
317+ ) ReadEnumError ! Enum {
318+ return @errSetCast (self .typeErased ().readEnum (Enum , endian ));
319+ }
320+
321+ pub inline fn typeErased (self : * const Self ) TypeErasedReader {
322+ return .{
323+ .context = @ptrCast (& self .context ),
324+ .readFn = typeErasedReadFn ,
325+ };
326+ }
327+
328+ const Self = @This ();
329+
330+ fn typeErasedReadFn (context : * const anyopaque , buffer : []u8 ) anyerror ! usize {
331+ const ptr : * const Context = @alignCast (@ptrCast (context ));
332+ return readFn (ptr .* , buffer );
333+ }
334+ };
335+ }
336+
337+ /// Deprecated; consider switching to `TypeErasedReader` or use `GenericReader`
338+ /// to use previous API.
339+ pub const Reader = GenericReader ;
340+
341+ pub const TypeErasedReader = @import ("io/Reader.zig" );
342+
109343pub const Writer = @import ("io/writer.zig" ).Writer ;
110344pub const SeekableStream = @import ("io/seekable_stream.zig" ).SeekableStream ;
111345
@@ -168,7 +402,7 @@ test "null_writer" {
168402}
169403
170404pub fn poll (
171- allocator : std.mem. Allocator ,
405+ allocator : Allocator ,
172406 comptime StreamEnum : type ,
173407 files : PollFiles (StreamEnum ),
174408) Poller (StreamEnum ) {
@@ -418,6 +652,7 @@ pub fn PollFiles(comptime StreamEnum: type) type {
418652}
419653
420654test {
655+ _ = TypeErasedReader ;
421656 _ = @import ("io/bit_reader.zig" );
422657 _ = @import ("io/bit_writer.zig" );
423658 _ = @import ("io/buffered_atomic_file.zig" );
@@ -427,7 +662,6 @@ test {
427662 _ = @import ("io/counting_writer.zig" );
428663 _ = @import ("io/counting_reader.zig" );
429664 _ = @import ("io/fixed_buffer_stream.zig" );
430- _ = @import ("io/reader.zig" );
431665 _ = @import ("io/writer.zig" );
432666 _ = @import ("io/peek_stream.zig" );
433667 _ = @import ("io/seekable_stream.zig" );
0 commit comments