@@ -58,7 +58,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
58
58
.reader = .{
59
59
.vtable = &.{
60
60
.stream = stream ,
61
- .rebase = rebase ,
61
+ .rebase = rebaseFallible ,
62
62
.discard = discard ,
63
63
.readVec = readVec ,
64
64
},
@@ -78,12 +78,19 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress {
78
78
};
79
79
}
80
80
81
- fn rebase (r : * Reader , capacity : usize ) Reader.RebaseError ! void {
81
+ fn rebaseFallible (r : * Reader , capacity : usize ) Reader.RebaseError ! void {
82
+ const d : * Decompress = @alignCast (@fieldParentPtr ("reader" , r ));
83
+ rebase (d , capacity );
84
+ }
85
+
86
+ fn rebase (d : * Decompress , capacity : usize ) void {
87
+ const r = & d .reader ;
82
88
assert (capacity <= r .buffer .len - flate .history_len );
83
89
assert (r .end + capacity > r .buffer .len );
84
90
const discard_n = r .end - flate .history_len ;
85
91
const keep = r .buffer [discard_n .. r .end ];
86
92
@memmove (r .buffer [0.. keep .len ], keep );
93
+ assert (keep .len != 0 );
87
94
r .end = keep .len ;
88
95
r .seek -= discard_n ;
89
96
}
@@ -101,6 +108,7 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
101
108
.end = r .end ,
102
109
};
103
110
defer {
111
+ assert (writer .end != 0 );
104
112
r .end = writer .end ;
105
113
r .seek = r .end ;
106
114
}
@@ -115,14 +123,20 @@ fn discard(r: *Reader, limit: std.Io.Limit) Reader.Error!usize {
115
123
116
124
fn readVec (r : * Reader , data : [][]u8 ) Reader.Error ! usize {
117
125
_ = data ;
118
- assert (r .seek == r .end );
119
- r .rebase (flate .history_len ) catch unreachable ;
126
+ const d : * Decompress = @alignCast (@fieldParentPtr ("reader" , r ));
127
+ return streamIndirect (d );
128
+ }
129
+
130
+ fn streamIndirect (d : * Decompress ) Reader.Error ! usize {
131
+ const r = & d .reader ;
132
+ if (r .end + flate .history_len > r .buffer .len ) rebase (d , flate .history_len );
120
133
var writer : Writer = .{
121
134
.buffer = r .buffer ,
122
135
.end = r .end ,
123
136
.vtable = &.{ .drain = Writer .fixedDrain },
124
137
};
125
- r .end += r .vtable .stream (r , & writer , .limited (writer .buffer .len - writer .end )) catch | err | switch (err ) {
138
+ defer r .end = writer .end ;
139
+ _ = streamFallible (d , & writer , .limited (writer .buffer .len - writer .end )) catch | err | switch (err ) {
126
140
error .WriteFailed = > unreachable ,
127
141
else = > | e | return e ,
128
142
};
@@ -188,7 +202,12 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {
188
202
189
203
pub fn stream (r : * Reader , w : * Writer , limit : std.Io.Limit ) Reader.StreamError ! usize {
190
204
const d : * Decompress = @alignCast (@fieldParentPtr ("reader" , r ));
191
- return readInner (d , w , limit ) catch | err | switch (err ) {
205
+ if (w .end >= r .end ) return streamFallible (d , w , limit );
206
+ return streamIndirect (d );
207
+ }
208
+
209
+ fn streamFallible (d : * Decompress , w : * Writer , limit : std.Io.Limit ) Reader.StreamError ! usize {
210
+ return streamInner (d , w , limit ) catch | err | switch (err ) {
192
211
error .EndOfStream = > {
193
212
if (d .state == .end ) {
194
213
return error .EndOfStream ;
@@ -207,7 +226,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us
207
226
};
208
227
}
209
228
210
- fn readInner (d : * Decompress , w : * Writer , limit : std.Io.Limit ) (Error || Reader .StreamError )! usize {
229
+ fn streamInner (d : * Decompress , w : * Writer , limit : std.Io.Limit ) (Error || Reader .StreamError )! usize {
211
230
var remaining = @intFromEnum (limit );
212
231
const in = d .input ;
213
232
sw : switch (d .state ) {
0 commit comments