authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-24 03:41:51 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-24 03:41:51 -07:00
log27aef9a965cb9febfa4d1a767d0fb107b0c0f92d
tree1adf0e0d81b28f1be1f751e65a8c190d97588711
parent62170a7ffee9a771bc71c52179e6ae7daa5ea11b
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

add AllocatingWriter


2 files changed, 85 insertions(+), 0 deletions(-)

allocating_writer.zig created+83
...@@ -0,0 +1,83 @@
1const std = @import("std");
2const nio = @import("./nio.zig");
3const builtin = @import("builtin");
4
5const sys = switch (builtin.target.os.tag) {
6 .linux => @import("sys-linux"),
7 else => unreachable,
8};
9
10pub const AllocatingWriter = struct {
11 allocator: std.mem.Allocator,
12 items: []u8,
13 capacity: usize,
14
15 pub fn init(allocator: std.mem.Allocator) AllocatingWriter {
16 return .{
17 .allocator = allocator,
18 .items = "",
19 .capacity = 0,
20 };
21 }
22
23 pub fn deinit(self: *AllocatingWriter) void {
24 self.allocator.free(self.allocatedSlice());
25 }
26
27 pub fn allocatedSlice(self: *AllocatingWriter) []u8 {
28 return self.items.ptr[0..self.capacity];
29 }
30
31 pub fn toOwnedSlice(self: *AllocatingWriter) ![]u8 {
32 if (self.allocator.resize(self.allocatedSlice(), self.items.len)) {
33 defer self.capacity = 0;
34 defer self.items = "";
35 return self.items;
36 }
37 const new_slice = try self.allocator.dupe(u8, self.items);
38 self.allocator.free(self.allocatedSlice());
39 return new_slice;
40 }
41
42 pub fn ensureUnusedCapacity(self: *AllocatingWriter, capacity: usize) !void {
43 if (self.capacity - self.items.len >= capacity) return;
44 const len = self.items.len;
45 const new_capacity = std.math.ceilPowerOfTwo(usize, @max(len + capacity, self.capacity)) catch return error.OutOfMemory;
46 const new_slice = try self.allocator.alloc(u8, new_capacity);
47 @memcpy(new_slice[0..len], self.items);
48 self.allocator.free(self.allocatedSlice());
49 self.items = new_slice;
50 self.items.len = len;
51 self.capacity = new_capacity;
52 }
53
54 fn unusedSlice(self: *AllocatingWriter) []u8 {
55 return self.allocatedSlice()[self.items.len..];
56 }
57
58 const W = nio.Writable(@This(), ._var);
59 pub const writeAll = W.writeAll;
60 pub const writevAll = W.writevAll;
61 pub const writeByteNTimes = W.writeByteNTimes;
62 pub const writeNTimes = W.writeNTimes;
63 pub const writeInt = W.writeInt;
64 pub const writeStruct = W.writeStruct;
65 pub const writeIntPretty = W.writeIntPretty;
66 pub const print = W.print;
67
68 pub const WriteError = std.mem.Allocator.Error;
69
70 pub fn write(self: *AllocatingWriter, bytes: []const u8) WriteError!usize {
71 try self.ensureUnusedCapacity(bytes.len);
72 @memcpy(self.unusedSlice()[0..bytes.len], bytes);
73 self.items.len += bytes.len;
74 return bytes.len;
75 }
76 pub fn writev(self: *AllocatingWriter, iovec: []const sys.struct_iovec) WriteError!usize {
77 var len: usize = 0;
78 for (iovec) |vec| len += vec.len;
79 try self.ensureUnusedCapacity(len);
80 for (iovec) |vec| _ = self.write(vec.base[0..vec.len]) catch unreachable;
81 return len;
82 }
83};
nio.zig+2
...@@ -337,3 +337,5 @@ pub const BufferedWriter = @import("./buffered_writer.zig").BufferedWriter;...@@ -337,3 +337,5 @@ pub const BufferedWriter = @import("./buffered_writer.zig").BufferedWriter;
337pub const CountingWriter = @import("./counting_writer.zig").CountingWriter;337pub const CountingWriter = @import("./counting_writer.zig").CountingWriter;
338338
339pub const NullWriter = @import("./null_writer.zig").NullWriter;339pub const NullWriter = @import("./null_writer.zig").NullWriter;
340
341pub const AllocatingWriter = @import("./allocating_writer.zig").AllocatingWriter;