2020-08-20 03:40:15 +01:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-12-31 23:07:36 +00:00
|
|
|
// Copyright (c) 2015-2021 Zig Contributors
|
2020-08-20 03:40:15 +01:00
|
|
|
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
|
|
|
// The MIT license requires this copyright notice to be included in all copies
|
|
|
|
// and substantial portions of the software.
|
2020-06-08 07:33:02 +01:00
|
|
|
const std = @import("../std.zig");
|
2021-03-01 10:47:11 +00:00
|
|
|
const assert = std.debug.assert;
|
2020-06-08 07:33:02 +01:00
|
|
|
const builtin = std.builtin;
|
|
|
|
const mem = std.mem;
|
|
|
|
|
|
|
|
pub fn Writer(
|
|
|
|
comptime Context: type,
|
|
|
|
comptime WriteError: type,
|
|
|
|
comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
|
|
|
|
) type {
|
|
|
|
return struct {
|
|
|
|
context: Context,
|
|
|
|
|
|
|
|
const Self = @This();
|
|
|
|
pub const Error = WriteError;
|
|
|
|
|
|
|
|
pub fn write(self: Self, bytes: []const u8) Error!usize {
|
|
|
|
return writeFn(self.context, bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn writeAll(self: Self, bytes: []const u8) Error!void {
|
|
|
|
var index: usize = 0;
|
|
|
|
while (index != bytes.len) {
|
|
|
|
index += try self.write(bytes[index..]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
pub fn print(self: Self, comptime format: []const u8, args: anytype) Error!void {
|
2020-06-08 07:33:02 +01:00
|
|
|
return std.fmt.format(self, format, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn writeByte(self: Self, byte: u8) Error!void {
|
|
|
|
const array = [1]u8{byte};
|
|
|
|
return self.writeAll(&array);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
|
|
|
|
var bytes: [256]u8 = undefined;
|
|
|
|
mem.set(u8, bytes[0..], byte);
|
|
|
|
|
|
|
|
var remaining: usize = n;
|
|
|
|
while (remaining > 0) {
|
|
|
|
const to_write = std.math.min(remaining, bytes.len);
|
|
|
|
try self.writeAll(bytes[0..to_write]);
|
|
|
|
remaining -= to_write;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Write a native-endian integer.
|
|
|
|
/// TODO audit non-power-of-two int sizes
|
|
|
|
pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {
|
2020-09-03 16:09:55 +01:00
|
|
|
var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
|
2020-06-08 07:33:02 +01:00
|
|
|
mem.writeIntNative(T, &bytes, value);
|
|
|
|
return self.writeAll(&bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Write a foreign-endian integer.
|
|
|
|
/// TODO audit non-power-of-two int sizes
|
|
|
|
pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {
|
2020-09-03 16:09:55 +01:00
|
|
|
var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
|
2020-06-08 07:33:02 +01:00
|
|
|
mem.writeIntForeign(T, &bytes, value);
|
|
|
|
return self.writeAll(&bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO audit non-power-of-two int sizes
|
|
|
|
pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {
|
2020-09-03 16:09:55 +01:00
|
|
|
var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
|
2020-06-08 07:33:02 +01:00
|
|
|
mem.writeIntLittle(T, &bytes, value);
|
|
|
|
return self.writeAll(&bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO audit non-power-of-two int sizes
|
|
|
|
pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {
|
2020-09-03 16:09:55 +01:00
|
|
|
var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
|
2020-06-08 07:33:02 +01:00
|
|
|
mem.writeIntBig(T, &bytes, value);
|
|
|
|
return self.writeAll(&bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO audit non-power-of-two int sizes
|
|
|
|
pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
|
2020-09-03 16:09:55 +01:00
|
|
|
var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
|
2020-06-08 07:33:02 +01:00
|
|
|
mem.writeInt(T, &bytes, value, endian);
|
|
|
|
return self.writeAll(&bytes);
|
|
|
|
}
|
2021-03-01 10:47:11 +00:00
|
|
|
|
|
|
|
pub fn writeStruct(self: Self, value: anytype) Error!void {
|
|
|
|
// Only extern and packed structs have defined in-memory layout.
|
|
|
|
comptime assert(@typeInfo(@TypeOf(value)).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
|
|
|
|
return self.writeAll(mem.asBytes(&value));
|
|
|
|
}
|
2020-06-08 07:33:02 +01:00
|
|
|
};
|
|
|
|
}
|