Skip to content

Commit c49c90a

Browse files
committed
fetch: update API usage
1 parent 4c04835 commit c49c90a

File tree

5 files changed

+227
-207
lines changed

5 files changed

+227
-207
lines changed

lib/std/Io/Reader.zig

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,18 @@ pub const VTable = struct {
7474
///
7575
/// `data` may not contain an alias to `Reader.buffer`.
7676
///
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.
80+
///
7781
/// Implementations may ignore `data`, writing directly to `Reader.buffer`,
7882
/// modifying `seek` and `end` accordingly, and returning 0 from this
7983
/// function. Implementations are encouraged to take advantage of this if
8084
/// it simplifies the logic.
8185
///
8286
/// The default implementation calls `stream` with either `data[0]` or
8387
/// `Reader.buffer`, whichever is bigger.
84-
readVec: *const fn (r: *Reader, data: []const []u8) Error!usize = defaultReadVec,
88+
readVec: *const fn (r: *Reader, data: [][]u8) Error!usize = defaultReadVec,
8589

8690
/// Ensures `capacity` more data can be buffered without rebasing.
8791
///
@@ -446,8 +450,8 @@ pub fn bufferedLen(r: *const Reader) usize {
446450
return r.end - r.seek;
447451
}
448452

449-
pub fn hashed(r: *Reader, hasher: anytype) Hashed(@TypeOf(hasher)) {
450-
return .{ .in = r, .hasher = hasher };
453+
pub fn hashed(r: *Reader, hasher: anytype, buffer: []u8) Hashed(@TypeOf(hasher)) {
454+
return .init(r, hasher, buffer);
451455
}
452456

453457
pub fn readVecAll(r: *Reader, data: [][]u8) Error!void {
@@ -1764,15 +1768,16 @@ pub fn Hashed(comptime Hasher: type) type {
17641768
return struct {
17651769
in: *Reader,
17661770
hasher: Hasher,
1767-
interface: Reader,
1771+
reader: Reader,
17681772

17691773
pub fn init(in: *Reader, hasher: Hasher, buffer: []u8) @This() {
17701774
return .{
17711775
.in = in,
17721776
.hasher = hasher,
1773-
.interface = .{
1777+
.reader = .{
17741778
.vtable = &.{
1775-
.read = @This().read,
1779+
.stream = @This().stream,
1780+
.readVec = @This().readVec,
17761781
.discard = @This().discard,
17771782
},
17781783
.buffer = buffer,
@@ -1782,33 +1787,39 @@ pub fn Hashed(comptime Hasher: type) type {
17821787
};
17831788
}
17841789

1785-
fn read(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1786-
const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1787-
const data = w.writableVector(limit);
1790+
fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
1791+
const this: *@This() = @alignCast(@fieldParentPtr("reader", r));
1792+
const data = limit.slice(try w.writableSliceGreedy(1));
1793+
var vec: [1][]u8 = .{data};
1794+
const n = try this.in.readVec(&vec);
1795+
this.hasher.update(data[0..n]);
1796+
w.advance(n);
1797+
return n;
1798+
}
1799+
1800+
fn readVec(r: *Reader, data: [][]u8) Error!usize {
1801+
const this: *@This() = @alignCast(@fieldParentPtr("reader", r));
17881802
const n = try this.in.readVec(data);
1789-
const result = w.advanceVector(n);
17901803
var remaining: usize = n;
17911804
for (data) |slice| {
17921805
if (remaining < slice.len) {
17931806
this.hasher.update(slice[0..remaining]);
1794-
return result;
1807+
return n;
17951808
} else {
17961809
remaining -= slice.len;
17971810
this.hasher.update(slice);
17981811
}
17991812
}
18001813
assert(remaining == 0);
1801-
return result;
1814+
return n;
18021815
}
18031816

18041817
fn discard(r: *Reader, limit: Limit) Error!usize {
1805-
const this: *@This() = @alignCast(@fieldParentPtr("interface", r));
1806-
var w = this.hasher.writer(&.{});
1807-
const n = this.in.stream(&w, limit) catch |err| switch (err) {
1808-
error.WriteFailed => unreachable,
1809-
else => |e| return e,
1810-
};
1811-
return n;
1818+
const this: *@This() = @alignCast(@fieldParentPtr("reader", r));
1819+
const peeked = limit.slice(try this.in.peekGreedy(1));
1820+
this.hasher.update(peeked);
1821+
this.in.toss(peeked.len);
1822+
return peeked.len;
18121823
}
18131824
};
18141825
}

lib/std/Io/Writer.zig

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,6 +2296,8 @@ pub fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usiz
22962296
/// generic. A better solution will involve creating a writer for each hash
22972297
/// function, where the splat buffer can be tailored to the hash implementation
22982298
/// details.
2299+
///
2300+
/// Contrast with `Hashing` which terminates the stream pipeline.
22992301
pub fn Hashed(comptime Hasher: type) type {
23002302
return struct {
23012303
out: *Writer,
@@ -2368,6 +2370,52 @@ pub fn Hashed(comptime Hasher: type) type {
23682370
};
23692371
}
23702372

2373+
/// Provides a `Writer` implementation based on calling `Hasher.update`,
2374+
/// discarding all data.
2375+
///
2376+
/// This implementation makes suboptimal buffering decisions due to being
2377+
/// generic. A better solution will involve creating a writer for each hash
2378+
/// function, where the splat buffer can be tailored to the hash implementation
2379+
/// details.
2380+
///
2381+
/// The total number of bytes written is stored in `hasher`.
2382+
///
2383+
/// Contrast with `Hashed` which also passes the data to an underlying stream.
2384+
pub fn Hashing(comptime Hasher: type) type {
2385+
return struct {
2386+
hasher: Hasher,
2387+
writer: Writer,
2388+
2389+
pub fn init(buffer: []u8) @This() {
2390+
return .initHasher(.init(.{}), buffer);
2391+
}
2392+
2393+
pub fn initHasher(hasher: Hasher, buffer: []u8) @This() {
2394+
return .{
2395+
.hasher = hasher,
2396+
.writer = .{
2397+
.buffer = buffer,
2398+
.vtable = &.{ .drain = @This().drain },
2399+
},
2400+
};
2401+
}
2402+
2403+
fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
2404+
const this: *@This() = @alignCast(@fieldParentPtr("writer", w));
2405+
const hasher = &this.hasher;
2406+
hasher.update(w.buffered());
2407+
w.end = 0;
2408+
var n: usize = 0;
2409+
for (data[0 .. data.len - 1]) |slice| {
2410+
hasher.update(slice);
2411+
n += slice.len;
2412+
}
2413+
for (0..splat) |_| hasher.update(data[data.len - 1]);
2414+
return n + splat;
2415+
}
2416+
};
2417+
}
2418+
23712419
/// Maintains `Writer` state such that it writes to the unused capacity of an
23722420
/// array list, filling it up completely before making a call through the
23732421
/// vtable, causing a resize. Consequently, the same, optimized, non-generic

lib/std/net.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,8 @@ pub const Stream = struct {
19321932

19331933
fn stream(io_r: *Io.Reader, io_w: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize {
19341934
const dest = limit.slice(try io_w.writableSliceGreedy(1));
1935-
const n = try readVec(io_r, &.{dest});
1935+
var bufs: [1][]u8 = .{dest};
1936+
const n = try readVec(io_r, &bufs);
19361937
io_w.advance(n);
19371938
return n;
19381939
}

src/Package/Fetch.zig

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,18 +1394,20 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U
13941394

13951395
var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true });
13961396
defer index_file.close();
1397+
var index_file_buffer: [2000]u8 = undefined;
1398+
var index_file_writer = index_file.writer(&index_file_buffer);
13971399
{
13981400
const index_prog_node = f.prog_node.start("Index pack", 0);
13991401
defer index_prog_node.end();
1400-
var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter());
1401-
try git.indexPack(gpa, object_format, &pack_file_reader, index_buffered_writer.writer());
1402-
try index_buffered_writer.flush();
1402+
try git.indexPack(gpa, object_format, &pack_file_reader, &index_file_writer);
14031403
}
14041404

14051405
{
1406+
var index_file_reader = index_file.reader(&index_file_buffer);
14061407
const checkout_prog_node = f.prog_node.start("Checkout", 0);
14071408
defer checkout_prog_node.end();
1408-
var repository = try git.Repository.init(gpa, object_format, &pack_file_reader, index_file);
1409+
var repository: git.Repository = undefined;
1410+
try repository.init(gpa, object_format, &pack_file_reader, &index_file_reader);
14091411
defer repository.deinit();
14101412
var diagnostics: git.Diagnostics = .{ .allocator = arena };
14111413
try repository.checkout(out_dir, resource.want_oid, &diagnostics);

0 commit comments

Comments
 (0)