@@ -11,14 +11,23 @@ const io = std.io;
1111/// For memory sources, if the supplied byte buffer is const, then `io.Writer` is not available.
1212/// The error set of the stream functions is the error set of the corresponding file functions.
1313pub const StreamSource = union (enum ) {
14+ const has_file = (std .builtin .os .tag != .freestanding );
15+
16+ /// The stream access is redirected to this buffer.
1417 buffer : io .FixedBufferStream ([]u8 ),
18+
19+ /// The stream access is redirected to this buffer.
20+ /// Writing to the source will always yield `error.AccessDenied`.
1521 const_buffer : io .FixedBufferStream ([]const u8 ),
16- file : std.fs.File ,
1722
18- pub const ReadError = std .fs .File .ReadError ;
19- pub const WriteError = std .fs .File .WriteError ;
20- pub const SeekError = std .fs .File .SeekError ;
21- pub const GetSeekPosError = std .fs .File .GetSeekPosError ;
23+ /// The stream access is redirected to this file.
24+ /// On freestanding, this must never be initialized!
25+ file : if (has_file ) std .fs .File else void ,
26+
27+ pub const ReadError = io .FixedBufferStream ([]u8 ).ReadError || (if (has_file ) std .fs .File .ReadError else error {});
28+ pub const WriteError = error {AccessDenied } || io .FixedBufferStream ([]u8 ).WriteError || (if (has_file ) std .fs .File .WriteError else error {});
29+ pub const SeekError = io .FixedBufferStream ([]u8 ).SeekError || (if (has_file ) std .fs .File .SeekError else error {});
30+ pub const GetSeekPosError = io .FixedBufferStream ([]u8 ).GetSeekPosError || (if (has_file ) std .fs .File .GetSeekPosError else error {});
2231
2332 pub const Reader = io .Reader (* StreamSource , ReadError , read );
2433 pub const Writer = io .Writer (* StreamSource , WriteError , write );
@@ -36,47 +45,47 @@ pub const StreamSource = union(enum) {
3645 switch (self .* ) {
3746 .buffer = > | * x | return x .read (dest ),
3847 .const_buffer = > | * x | return x .read (dest ),
39- .file = > | x | return x .read (dest ),
48+ .file = > | x | if ( ! has_file ) unreachable else return x .read (dest ),
4049 }
4150 }
4251
4352 pub fn write (self : * StreamSource , bytes : []const u8 ) WriteError ! usize {
4453 switch (self .* ) {
4554 .buffer = > | * x | return x .write (bytes ),
4655 .const_buffer = > return error .AccessDenied ,
47- .file = > | x | return x .write (bytes ),
56+ .file = > | x | if ( ! has_file ) unreachable else return x .write (bytes ),
4857 }
4958 }
5059
5160 pub fn seekTo (self : * StreamSource , pos : u64 ) SeekError ! void {
5261 switch (self .* ) {
5362 .buffer = > | * x | return x .seekTo (pos ),
5463 .const_buffer = > | * x | return x .seekTo (pos ),
55- .file = > | x | return x .seekTo (pos ),
64+ .file = > | x | if ( ! has_file ) unreachable else return x .seekTo (pos ),
5665 }
5766 }
5867
5968 pub fn seekBy (self : * StreamSource , amt : i64 ) SeekError ! void {
6069 switch (self .* ) {
6170 .buffer = > | * x | return x .seekBy (amt ),
6271 .const_buffer = > | * x | return x .seekBy (amt ),
63- .file = > | x | return x .seekBy (amt ),
72+ .file = > | x | if ( ! has_file ) unreachable else return x .seekBy (amt ),
6473 }
6574 }
6675
6776 pub fn getEndPos (self : * StreamSource ) GetSeekPosError ! u64 {
6877 switch (self .* ) {
6978 .buffer = > | * x | return x .getEndPos (),
7079 .const_buffer = > | * x | return x .getEndPos (),
71- .file = > | x | return x .getEndPos (),
80+ .file = > | x | if ( ! has_file ) unreachable else return x .getEndPos (),
7281 }
7382 }
7483
7584 pub fn getPos (self : * StreamSource ) GetSeekPosError ! u64 {
7685 switch (self .* ) {
7786 .buffer = > | * x | return x .getPos (),
7887 .const_buffer = > | * x | return x .getPos (),
79- .file = > | x | return x .getPos (),
88+ .file = > | x | if ( ! has_file ) unreachable else return x .getPos (),
8089 }
8190 }
8291
@@ -92,3 +101,30 @@ pub const StreamSource = union(enum) {
92101 return .{ .context = self };
93102 }
94103};
104+
105+ test "StreamSource (refs)" {
106+ std .testing .refAllDecls (StreamSource );
107+ }
108+
109+ test "StreamSource (mutable buffer)" {
110+ var buffer : [64 ]u8 = undefined ;
111+ var source = StreamSource { .buffer = std .io .fixedBufferStream (& buffer ) };
112+
113+ var writer = source .writer ();
114+
115+ try writer .writeAll ("Hello, World!" );
116+
117+ try std .testing .expectEqualStrings ("Hello, World!" , source .buffer .getWritten ());
118+ }
119+
120+ test "StreamSource (const buffer)" {
121+ const buffer : [64 ]u8 = "Hello, World!" .* ++ ([1 ]u8 {0xAA } ** 51 );
122+ var source = StreamSource { .const_buffer = std .io .fixedBufferStream (& buffer ) };
123+
124+ var reader = source .reader ();
125+
126+ var dst_buffer : [13 ]u8 = undefined ;
127+ try reader .readNoEof (& dst_buffer );
128+
129+ try std .testing .expectEqualStrings ("Hello, World!" , & dst_buffer );
130+ }
0 commit comments