| ... | ... | @@ -89,6 +89,51 @@ pub fn Readable(T: type, this_kind: enum { _var, _const, _bare }) type { |
| 89 | 89 | }; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | pub fn Writable(T: type, this_kind: enum { _var, _const, _bare }) type { |
| 93 | return struct { |
| 94 | const Error = T.WriteError; |
| 95 | |
| 96 | const Self = switch (this_kind) { |
| 97 | ._var => *T, |
| 98 | ._const => *const T, |
| 99 | ._bare => T, |
| 100 | }; |
| 101 | |
| 102 | // pub fn write(self: Self, bytes: []const u8) Error!usize { |
| 103 | // } |
| 104 | |
| 105 | pub fn writeAll(self: Self, bytes: []const u8) Error!void { |
| 106 | var index: usize = 0; |
| 107 | while (index != bytes.len) { |
| 108 | index += try self.write(bytes[index..]); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void { |
| 113 | var bytes: [1024]u8 = undefined; |
| 114 | @memset(bytes[0..], byte); |
| 115 | var remaining: usize = n; |
| 116 | while (remaining > 0) { |
| 117 | const to_write = @min(remaining, bytes.len); |
| 118 | try self.writeAll(bytes[0..to_write]); |
| 119 | remaining -= to_write; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | pub fn writeInt(self: Self, comptime I: type, value: I, endian: std.builtin.Endian) Error!void { |
| 124 | var bytes: [@as(u16, @intCast((@as(u17, @typeInfo(I).Int.bits) + 7) / 8))]u8 = undefined; |
| 125 | std.mem.writeInt(std.math.ByteAlignedInt(I), &bytes, value, endian); |
| 126 | return self.writeAll(&bytes); |
| 127 | } |
| 128 | |
| 129 | pub fn writeStruct(self: Self, value: anytype) Error!void { |
| 130 | // Only extern and packed structs have defined in-memory layout. |
| 131 | comptime std.debug.assert(@typeInfo(@TypeOf(value)).Struct.layout != .Auto); |
| 132 | return self.writeAll(std.mem.asBytes(&value)); |
| 133 | } |
| 134 | }; |
| 135 | } |
| 136 | |
| 92 | 137 | pub const AnyReadable = @import("./AnyReadable.zig"); |
| 93 | 138 | |
| 94 | 139 | pub const FixedBufferStream = @import("./fixed_buffer_stream.zig").FixedBufferStream; |