Skip to content

Commit 4675d76

Browse files
committed
fix: Format code examples with proper indentation
1 parent fdf560a commit 4675d76

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

content/post/2025-09-18-new-writer.smd

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ fn write(w: *Writer, data: []const u8) Error!usize
2828
事实证明`std.Io.Writer`有内置的缓冲。例如,如果我们想要一个`Writer`为 A`std.fs.File`我们需要提供缓冲:
2929

3030
```zig
31-
var buffer: [1024]u8 = undefined; var writer = my_file.writer(&buffer);
31+
var buffer: [1024]u8 = undefined;
32+
var writer = my_file.writer(&buffer);
3233
```
3334

3435
当然,如果我们不想要缓冲,我们总能传递一个空的缓冲区:
@@ -42,7 +43,11 @@ var writer = my_file.writer(&.{});
4243
最简单的实现方法`drain`,在进行这次更大的大修时,Zig标准库已经升级了很多,是:
4344

4445
```zig
45-
fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) !usize { _ = splat; const self: *@This() = @fieldParentPtr("interface", io_w); return self.writeAll(data[0]) catch return error.WriteFailed; }
46+
fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) !usize {
47+
_ = splat;
48+
const self: *@This() = @fieldParentPtr("interface", io_w);
49+
return self.writeAll(data[0]) catch return error.WriteFailed;
50+
}
4651
```
4752

4853
我们忽略了`splat`参数,只需在中写第一个值`data`(`data.len > 0`保证是真实的)。这 转`drain`进入什么更简单`write`方法会看起来像。因为我们返回写入的字节长度,`std.Io.Writer`会知道我们可能没有写所有数据并调用`drain`再次,如果有必要,与其余的数据。
@@ -56,7 +61,28 @@ fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) !usize {
5661
这种简化`File`显示三种类型之间的关系:
5762

5863
```zig
59-
pub const File = struct { pub fn writer(self: *File, buffer: []u8) Writer{ return .{ .file = self, .interface = std.Io.Writer{ .buffer = buffer, .vtable = .{.drain = Writer.drain}, } }; } pub const Writer = struct { file: *File, interface: std.Io.Writer, // this has a bunch of other fields fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) !usize { const self: *Writer = @fieldParentPtr("interface", io_w); // .... } } }
64+
pub const File = struct {
65+
pub fn writer(self: *File, buffer: []u8) Writer {
66+
return .{
67+
.file = self,
68+
.interface = std.Io.Writer{
69+
.buffer = buffer,
70+
.vtable = .{.drain = Writer.drain},
71+
}
72+
};
73+
}
74+
75+
pub const Writer = struct {
76+
file: *File,
77+
interface: std.Io.Writer,
78+
// this has a bunch of other fields
79+
80+
fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) !usize {
81+
const self: *Writer = @fieldParentPtr("interface", io_w);
82+
// ....
83+
}
84+
}
85+
}
6086
```
6187

6288
实例`File.Writer`需要存在于某个地方(例如在堆栈上),因为那是`std.Io.Writer`接口存在。有可能 那个`File`可以直接有一个`writer_interface: std.Io.Writer`字段,但这会限制你每个文件一个写入器,并且会膨胀`File`结构。
@@ -70,7 +96,12 @@ pub const File = struct { pub fn writer(self: *File, buffer: []u8) Writer{ retur
7096
迁移时,_可能会遇到以下错误:在“...”中没有名为“adaptToNewApi”的字段或成员函数。_你可以看到为什么发生这种情况,通过查看更新的实现`std.fmt.format`:
7197

7298
```zig
73-
pub fn format(writer: anytype, comptime fmt: []const u8, args: anytype) !void { var adapter = writer.adaptToNewApi(); return adapter.new_interface.print(fmt, args) catch |err| switch (err) { error.WriteFailed => return adapter.err.?, }; }
99+
pub fn format(writer: anytype, comptime fmt: []const u8, args: anytype) !void {
100+
var adapter = writer.adaptToNewApi();
101+
return adapter.new_interface.print(fmt, args) catch |err| switch (err) {
102+
error.WriteFailed => return adapter.err.?,
103+
};
104+
}
74105
```
75106

76107
因为这个功能被移动到`std.Io.Writer`, 任何`writer`传入`format`必须能够升级到新接口。这是完成的,同样,只是惯例,通过让“老” Writer 揭露一个`adaptToNewApi`返回一个类型的方法,它暴露了一个`new_interface: std.Io.Writer`领域。这是很容易实现使用基本`drain`实现,你可以在标准库中找到一些例子,但如果你不控制传统作者,那就没什么帮助了。

0 commit comments

Comments
 (0)