@@ -70,13 +70,14 @@ pub const VTable = struct {
70
70
71
71
/// Returns number of bytes written to `data`.
72
72
///
73
- /// `data` may not have nonzero length.
73
+ /// `data` must have nonzero length. `data[0]` may have zero length, in
74
+ /// which case the implementation must write to `Reader.buffer`.
74
75
///
75
76
/// `data` may not contain an alias to `Reader.buffer`.
76
77
///
77
- /// `data` is mutable because the implementation may to temporarily modify
78
- /// the fields in order to handle partial reads. Implementations must
79
- /// restore the original value before returning.
78
+ /// `data` is mutable because the implementation may temporarily modify the
79
+ /// fields in order to handle partial reads. Implementations must restore
80
+ /// the original value before returning.
80
81
///
81
82
/// Implementations may ignore `data`, writing directly to `Reader.buffer`,
82
83
/// modifying `seek` and `end` accordingly, and returning 0 from this
@@ -421,23 +422,29 @@ pub fn readVec(r: *Reader, data: [][]u8) Error!usize {
421
422
422
423
/// Writes to `Reader.buffer` or `data`, whichever has larger capacity.
423
424
pub fn defaultReadVec (r : * Reader , data : [][]u8 ) Error ! usize {
424
- assert (r .seek == r .end );
425
- r .seek = 0 ;
426
- r .end = 0 ;
427
425
const first = data [0 ];
428
- const direct = first .len >= r .buffer .len ;
426
+ if (r .seek == r .end and first .len >= r .buffer .len ) {
427
+ var writer : Writer = .{
428
+ .buffer = first ,
429
+ .end = 0 ,
430
+ .vtable = &.{ .drain = Writer .fixedDrain },
431
+ };
432
+ const limit : Limit = .limited (writer .buffer .len - writer .end );
433
+ return r .vtable .stream (r , & writer , limit ) catch | err | switch (err ) {
434
+ error .WriteFailed = > unreachable ,
435
+ else = > | e | return e ,
436
+ };
437
+ }
429
438
var writer : Writer = .{
430
- .buffer = if ( direct ) first else r .buffer ,
431
- .end = 0 ,
439
+ .buffer = r .buffer ,
440
+ .end = r . end ,
432
441
.vtable = &.{ .drain = Writer .fixedDrain },
433
442
};
434
443
const limit : Limit = .limited (writer .buffer .len - writer .end );
435
- const n = r .vtable .stream (r , & writer , limit ) catch | err | switch (err ) {
444
+ r . end + = r .vtable .stream (r , & writer , limit ) catch | err | switch (err ) {
436
445
error .WriteFailed = > unreachable ,
437
446
else = > | e | return e ,
438
447
};
439
- if (direct ) return n ;
440
- r .end += n ;
441
448
return 0 ;
442
449
}
443
450
@@ -1059,17 +1066,8 @@ pub fn fill(r: *Reader, n: usize) Error!void {
1059
1066
/// increasing by a factor of 5 or more.
1060
1067
fn fillUnbuffered (r : * Reader , n : usize ) Error ! void {
1061
1068
try rebase (r , n );
1062
- var writer : Writer = .{
1063
- .buffer = r .buffer ,
1064
- .vtable = &.{ .drain = Writer .fixedDrain },
1065
- };
1066
- while (r .end < r .seek + n ) {
1067
- writer .end = r .end ;
1068
- r .end += r .vtable .stream (r , & writer , .limited (r .buffer .len - r .end )) catch | err | switch (err ) {
1069
- error .WriteFailed = > unreachable ,
1070
- error .ReadFailed , error .EndOfStream = > | e | return e ,
1071
- };
1072
- }
1069
+ var bufs : [1 ][]u8 = .{"" };
1070
+ while (r .end < r .seek + n ) _ = try r .vtable .readVec (r , & bufs );
1073
1071
}
1074
1072
1075
1073
/// Without advancing the seek position, does exactly one underlying read, filling the buffer as
@@ -1079,15 +1077,8 @@ fn fillUnbuffered(r: *Reader, n: usize) Error!void {
1079
1077
/// Asserts buffer capacity is at least 1.
1080
1078
pub fn fillMore (r : * Reader ) Error ! void {
1081
1079
try rebase (r , 1 );
1082
- var writer : Writer = .{
1083
- .buffer = r .buffer ,
1084
- .end = r .end ,
1085
- .vtable = &.{ .drain = Writer .fixedDrain },
1086
- };
1087
- r .end += r .vtable .stream (r , & writer , .limited (r .buffer .len - r .end )) catch | err | switch (err ) {
1088
- error .WriteFailed = > unreachable ,
1089
- else = > | e | return e ,
1090
- };
1080
+ var bufs : [1 ][]u8 = .{"" };
1081
+ _ = try r .vtable .readVec (r , & bufs );
1091
1082
}
1092
1083
1093
1084
/// Returns the next byte from the stream or returns `error.EndOfStream`.
@@ -1796,18 +1787,26 @@ pub fn Hashed(comptime Hasher: type) type {
1796
1787
1797
1788
fn readVec (r : * Reader , data : [][]u8 ) Error ! usize {
1798
1789
const this : * @This () = @alignCast (@fieldParentPtr ("reader" , r ));
1799
- const n = try this .in .readVec (data );
1790
+ var vecs : [8 ][]u8 = undefined ; // Arbitrarily chosen amount.
1791
+ const dest_n , const data_size = try r .writableVector (& vecs , data );
1792
+ const dest = vecs [0.. dest_n ];
1793
+ const n = try this .in .readVec (dest );
1800
1794
var remaining : usize = n ;
1801
- for (data ) | slice | {
1795
+ for (dest ) | slice | {
1802
1796
if (remaining < slice .len ) {
1803
1797
this .hasher .update (slice [0.. remaining ]);
1804
- return n ;
1798
+ remaining = 0 ;
1799
+ break ;
1805
1800
} else {
1806
1801
remaining -= slice .len ;
1807
1802
this .hasher .update (slice );
1808
1803
}
1809
1804
}
1810
1805
assert (remaining == 0 );
1806
+ if (n > data_size ) {
1807
+ r .end += n - data_size ;
1808
+ return data_size ;
1809
+ }
1811
1810
return n ;
1812
1811
}
1813
1812
@@ -1824,17 +1823,24 @@ pub fn Hashed(comptime Hasher: type) type {
1824
1823
pub fn writableVectorPosix (r : * Reader , buffer : []std.posix.iovec , data : []const []u8 ) Error ! struct { usize , usize } {
1825
1824
var i : usize = 0 ;
1826
1825
var n : usize = 0 ;
1827
- for (data ) | buf | {
1828
- if (buffer .len - i == 0 ) return .{ i , n };
1826
+ if (r .seek == r .end ) {
1827
+ for (data ) | buf | {
1828
+ if (buffer .len - i == 0 ) return .{ i , n };
1829
+ if (buf .len != 0 ) {
1830
+ buffer [i ] = .{ .base = buf .ptr , .len = buf .len };
1831
+ i += 1 ;
1832
+ n += buf .len ;
1833
+ }
1834
+ }
1835
+ const buf = r .buffer ;
1829
1836
if (buf .len != 0 ) {
1837
+ r .seek = 0 ;
1838
+ r .end = 0 ;
1830
1839
buffer [i ] = .{ .base = buf .ptr , .len = buf .len };
1831
1840
i += 1 ;
1832
- n += buf .len ;
1833
1841
}
1834
- }
1835
- assert (r .seek == r .end );
1836
- const buf = r .buffer ;
1837
- if (buf .len != 0 ) {
1842
+ } else {
1843
+ const buf = r .buffer [r .end .. ];
1838
1844
buffer [i ] = .{ .base = buf .ptr , .len = buf .len };
1839
1845
i += 1 ;
1840
1846
}
@@ -1848,28 +1854,62 @@ pub fn writableVectorWsa(
1848
1854
) Error ! struct { usize , usize } {
1849
1855
var i : usize = 0 ;
1850
1856
var n : usize = 0 ;
1851
- for (data ) | buf | {
1852
- if (buffer .len - i == 0 ) return .{ i , n };
1853
- if (buf .len == 0 ) continue ;
1854
- if (std .math .cast (u32 , buf .len )) | len | {
1855
- buffer [i ] = .{ .buf = buf .ptr , .len = len };
1857
+ if (r .seek == r .end ) {
1858
+ for (data ) | buf | {
1859
+ if (buffer .len - i == 0 ) return .{ i , n };
1860
+ if (buf .len == 0 ) continue ;
1861
+ if (std .math .cast (u32 , buf .len )) | len | {
1862
+ buffer [i ] = .{ .buf = buf .ptr , .len = len };
1863
+ i += 1 ;
1864
+ n += len ;
1865
+ continue ;
1866
+ }
1867
+ buffer [i ] = .{ .buf = buf .ptr , .len = std .math .maxInt (u32 ) };
1868
+ i += 1 ;
1869
+ n += std .math .maxInt (u32 );
1870
+ return .{ i , n };
1871
+ }
1872
+ const buf = r .buffer ;
1873
+ if (buf .len != 0 ) {
1874
+ r .seek = 0 ;
1875
+ r .end = 0 ;
1876
+ if (std .math .cast (u32 , buf .len )) | len | {
1877
+ buffer [i ] = .{ .buf = buf .ptr , .len = len };
1878
+ } else {
1879
+ buffer [i ] = .{ .buf = buf .ptr , .len = std .math .maxInt (u32 ) };
1880
+ }
1856
1881
i += 1 ;
1857
- n += len ;
1858
- continue ;
1859
1882
}
1860
- buffer [i ] = .{ .buf = buf .ptr , .len = std .math .maxInt (u32 ) };
1883
+ } else {
1884
+ buffer [i ] = .{
1885
+ .buf = r .buffer .ptr + r .end ,
1886
+ .len = @min (std .math .maxInt (u32 ), r .buffer .len - r .end ),
1887
+ };
1861
1888
i += 1 ;
1862
- n += std .math .maxInt (u32 );
1863
- return .{ i , n };
1864
1889
}
1865
- assert (r .seek == r .end );
1866
- const buf = r .buffer ;
1867
- if (buf .len != 0 ) {
1868
- if (std .math .cast (u32 , buf .len )) | len | {
1869
- buffer [i ] = .{ .buf = buf .ptr , .len = len };
1870
- } else {
1871
- buffer [i ] = .{ .buf = buf .ptr , .len = std .math .maxInt (u32 ) };
1890
+ return .{ i , n };
1891
+ }
1892
+
1893
+ pub fn writableVector (r : * Reader , buffer : [][]u8 , data : []const []u8 ) Error ! struct { usize , usize } {
1894
+ var i : usize = 0 ;
1895
+ var n : usize = 0 ;
1896
+ if (r .seek == r .end ) {
1897
+ for (data ) | buf | {
1898
+ if (buffer .len - i == 0 ) return .{ i , n };
1899
+ if (buf .len != 0 ) {
1900
+ buffer [i ] = buf ;
1901
+ i += 1 ;
1902
+ n += buf .len ;
1903
+ }
1904
+ }
1905
+ if (r .buffer .len != 0 ) {
1906
+ r .seek = 0 ;
1907
+ r .end = 0 ;
1908
+ buffer [i ] = r .buffer ;
1909
+ i += 1 ;
1872
1910
}
1911
+ } else {
1912
+ buffer [i ] = r .buffer [r .end .. ];
1873
1913
i += 1 ;
1874
1914
}
1875
1915
return .{ i , n };
0 commit comments