はじめに
zig
のバージョン0.15.1
において、Writergate
の名の下にstd.io.Reader
やstd.io.Writer
が廃止され、std.Io.Reader
やstd.Io.Writer
に置き換えられた。12
気付いた範囲での変更点のメモ。
std.fs.FileからのReaderの取得
(旧) std.fs.File.reader(self: *File) Reader
(新)std.fs.File.reader(self: *File, buffer: []u8) Reader
新APIではバッファを要求するようになった。
var file = try std.fs.openFileAbsolute("/path/to/");
defer file.deinit();
var buffer: [4096]u8 = undefined; // お好きなサイズで
var reader = file.reader(&buffer);
ファイルの一括読み込み
(旧)std.fs.File.readToEndAlloc(self: File, allocator: Allocator, max_bytes: usize) ![]u8
(新)std.Io.Reader.allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8
完全にお引越。
新APIではmax_bytes
がlimit
に置き換わった。
Limit
の定義は以下。
pub const Limit = enum(usize) {
nothing = 0,
unlimited = std.math.maxInt(usize),
pub fn limited(n: usize) Limit { ...} // 任意サイズ
pub fn limited64(n: u64) Limit { ...} // 任意サイズ
// (snip)
}
allocRemaining
の中で呼んでいるappendRemaining
のコードを見ると、
-
nothing
: 読まずに.StreamTooLong
を返す -
unlimited
: ストリームの末端まで読む(ファイルなら一括読み込み) - limited/limited64: 指定した上限まで読み込む。読みきれなければ
.StreamTooLong
を返す
std.fs.FileからのReaderの取得に従ってReaderを取得して、Limit
に.unlimited
を指定することで、ファイルの一括読み込みができる。
std.fs.File.Reader
のinterface
フィールドを経由することでstd.Io.Reader
が取得できる。
0.13.1: https://ziglang.org/documentation/0.13.0/std/#std.fs.File.readToEndAlloc
0.15.1: https://ziglang.org/documentation/0.15.1/std/#std.Io.Reader.allocRemaining
センチネル付きでファイルを読み込む
(旧)readToEndAllocOptions( self: File, allocator: Allocator, max_bytes: usize, size_hint: ?usize, comptime alignment: u29, comptime optional_sentinel: ?u8, ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8)
(新)なくなりました〜
バージョン0.15.1
では後方互換性で旧APIがまだ使えるので、これで耐え凌ぎましょう。
開発バージョンの0.16.0
では
(新)allocRemainingAlignedSentinel( r: *Reader, gpa: Allocator, limit: Limit, comptime alignment: std.mem.Alignment, comptime sentinel: ?u8, ) LimitedAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8)
が追加されている。
旧APiの引数の違いとして、alignmentがcomptime u29
からstd.mem.Alignment
に変更。
std.mem.Alignment
の定義は以下
pub const Alignment = enum(math.Log2Int(usize)) {
@"1" = 0,
@"2" = 1,
@"4" = 2,
@"8" = 3,
@"16" = 4,
@"32" = 5,
@"64" = 6,
// (snip)
Null終端C文字列として読みたい場合は.@"8"
を指定すればよい。
ちなみに0.16.0において、std.fs.Dir
には、readFileAllocOptions
がまだ残ってる。
なんだこのチグハグなAPIは(毒)
0.13.1: https://ziglang.org/documentation/0.13.0/std/#std.fs.File.readToEndAllocOptions
0.16.0: https://ziglang.org/documentation/master/std/#std.Io.Reader.allocRemainingAlignedSentinel
Writer経由でのバッファへの書き出し
0.13.1
まではstd.ArrayList
を構築、ついでstd.ArrayList.reader
でジェネリックReader
を取得して、書き出しが行えた。
0.15.1
ではジェネリックReader
の廃止に伴い、std.Io.Writer.Allocating
が追加されたのでこれを使う。
std.Io.Writer.Allocating.writer
フィールドを経由することでstd.Io.Writer
が取得できる。
何だこの一貫性のないAPIは(毒)
const hello = "Hello world";
var writer = std.Io.Writer.Allocating.init(allocator);
writer.deinit();
try writer.writer.writeAll(hello);
const content = try writer.toOwnedSlice();
0.13.1: https://ziglang.org/documentation/0.13.0/std/#std.io.Reader
0.15.1: https://ziglang.org/documentation/0.15.1/std/#std.Io.Writer.Allocating
std.fs.AtomicFileのコンストラクタ
(旧)init( dest_basename: []const u8, mode: File.Mode, dir: Dir, close_dir_on_deinit: bool, ) InitError!AtomicFile
(新)init( dest_basename: []const u8, mode: File.Mode, dir: Dir, close_dir_on_deinit: bool, write_buffer: []u8, ) InitError!AtomicFile
引数が一つ足され、バッファを要求している。
std.fs.FileからのReaderの取得と同様に、バッファを渡す。
var buffer: [4096]u8 = undefined;
var tmp_file = try std.fs.AtomicFile.init("/path/to/", std.fs.File.default_mode, std.fs.cwd(), false, &buffer);
defer tmp_file.deinit();
try tmp_file.file_writer.interface.writeAll(new_content);
try tmp_file.finish();
0.13.1: https://ziglang.org/documentation/0.13.0/std/#std.fs.AtomicFile.init
0.15.1: https://ziglang.org/documentation/0.15.1/std/#std.fs.AtomicFile.init