| ... | @@ -1,5 +1,7 @@ | ... | @@ -1,5 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const string = []const u8; | 2 | const string = []const u8; |
| | 3 | const assert = std.debug.assert; |
| | 4 | |
| 3 | pub const range = @import("range").range; | 5 | pub const range = @import("range").range; |
| 4 | | 6 | |
| 5 | pub fn fmtByteCountIEC(alloc: std.mem.Allocator, b: u64) !string { | 7 | pub fn fmtByteCountIEC(alloc: std.mem.Allocator, b: u64) !string { |
| ... | @@ -288,3 +290,82 @@ fn formatReplacer(self: ReplacerData, comptime fmt: []const u8, options: std.fmt | ... | @@ -288,3 +290,82 @@ fn formatReplacer(self: ReplacerData, comptime fmt: []const u8, options: std.fmt |
| 288 | try writer.writeByte(if (c == self.from) self.to else @intCast(u8, c)); | 290 | try writer.writeByte(if (c == self.from) self.to else @intCast(u8, c)); |
| 289 | } | 291 | } |
| 290 | } | 292 | } |
| | 293 | |
| | 294 | pub fn randomBytes(comptime len: usize) [len]u8 { |
| | 295 | var bytes: [len]u8 = undefined; |
| | 296 | std.crypto.random.bytes(&bytes); |
| | 297 | return bytes; |
| | 298 | } |
| | 299 | |
| | 300 | pub fn writeEnumBig(writer: anytype, comptime E: type, value: E) !void { |
| | 301 | try writer.writeIntBig(@typeInfo(E).Enum.tag_type, @enumToInt(value)); |
| | 302 | } |
| | 303 | |
| | 304 | pub fn readExpected(reader: anytype, expected: []const u8) !bool { |
| | 305 | for (expected) |item, i| { |
| | 306 | const actual = try reader.readByte(); |
| | 307 | if (actual != item) { |
| | 308 | std.log.err("expected '{d}' at index {d}, found: '{d}'", .{ item, i, actual }); |
| | 309 | return false; |
| | 310 | } |
| | 311 | } |
| | 312 | return true; |
| | 313 | } |
| | 314 | |
| | 315 | pub fn readBytes(reader: anytype, comptime len: usize) ![len]u8 { |
| | 316 | var bytes: [len]u8 = undefined; |
| | 317 | assert(try reader.readAll(&bytes) == len); |
| | 318 | return bytes; |
| | 319 | } |
| | 320 | |
| | 321 | pub fn FixedMaxBuffer(comptime max_len: usize) type { |
| | 322 | return struct { |
| | 323 | buf: [max_len]u8, |
| | 324 | len: usize, |
| | 325 | pos: usize, |
| | 326 | |
| | 327 | const Self = @This(); |
| | 328 | pub const Reader = std.io.Reader(*Self, error{}, read); |
| | 329 | |
| | 330 | pub fn init(r: anytype, runtime_len: usize) !Self { |
| | 331 | var fmr = Self{ |
| | 332 | .buf = undefined, |
| | 333 | .len = runtime_len, |
| | 334 | .pos = 0, |
| | 335 | }; |
| | 336 | _ = try r.readAll(fmr.buf[0..runtime_len]); |
| | 337 | return fmr; |
| | 338 | } |
| | 339 | |
| | 340 | pub fn reader(self: *Self) Reader { |
| | 341 | return .{ .context = self }; |
| | 342 | } |
| | 343 | |
| | 344 | fn read(self: *Self, dest: []u8) error{}!usize { |
| | 345 | const buf = self.buf[0..self.len]; |
| | 346 | const size = std.math.min(dest.len, buf.len - self.pos); |
| | 347 | const end = self.pos + size; |
| | 348 | std.mem.copy(u8, dest[0..size], buf[self.pos..end]); |
| | 349 | self.pos = end; |
| | 350 | return size; |
| | 351 | } |
| | 352 | |
| | 353 | pub fn readLen(self: *Self, len: usize) []const u8 { |
| | 354 | assert(self.pos + len <= self.len); |
| | 355 | defer self.pos += len; |
| | 356 | return self.buf[self.pos..][0..len]; |
| | 357 | } |
| | 358 | |
| | 359 | pub fn atEnd(self: *const Self) bool { |
| | 360 | return self.pos == self.len; |
| | 361 | } |
| | 362 | }; |
| | 363 | } |
| | 364 | |
| | 365 | pub fn hashBytes(comptime Algo: type, bytes: []const u8) [Algo.digest_length]u8 { |
| | 366 | var h = Algo.init(.{}); |
| | 367 | var out: [Algo.digest_length]u8 = undefined; |
| | 368 | h.update(bytes); |
| | 369 | h.final(&out); |
| | 370 | return out; |
| | 371 | } |