| ... | ... | @@ -19,6 +19,10 @@ buffer: std.ArrayListUnmanaged(u8), |
| 19 | 19 | /// equals number of bytes provided. This property is exploited by |
| 20 | 20 | /// `std.io.AllocatingWriter` for example. |
| 21 | 21 | unbuffered_writer: Writer, |
| 22 | /// Tracks total number of bytes written to this `BufferedWriter`. This value |
| 23 | /// only increases. In the case of fixed mode, this value always equals |
| 24 | /// `buffer.items.len`. |
| 25 | bytes_written: usize = 0, |
| 22 | 26 | |
| 23 | 27 | /// Number of slices to store on the stack, when trying to send as many byte |
| 24 | 28 | /// vectors through the underlying write calls as possible. |
| ... | ... | @@ -106,6 +110,7 @@ pub fn advance(bw: *BufferedWriter, n: usize) void { |
| 106 | 110 | const list = &bw.buffer; |
| 107 | 111 | list.items.len += n; |
| 108 | 112 | assert(list.items.len <= list.capacity); |
| 113 | bw.bytes_written += n; |
| 109 | 114 | } |
| 110 | 115 | |
| 111 | 116 | /// The `data` parameter is mutable because this function needs to mutate the |
| ... | ... | @@ -114,8 +119,9 @@ pub fn writevAll(bw: *BufferedWriter, data: [][]const u8) anyerror!void { |
| 114 | 119 | var i: usize = 0; |
| 115 | 120 | while (true) { |
| 116 | 121 | var n = try passthru_writeSplat(bw, data[i..], 1); |
| 117 | | while (n >= data[i].len) { |
| 118 | | n -= data[i].len; |
| 122 | const len = data[i].len; |
| 123 | while (n >= len) { |
| 124 | n -= len; |
| 119 | 125 | i += 1; |
| 120 | 126 | if (i >= data.len) return; |
| 121 | 127 | } |
| ... | ... | @@ -147,7 +153,7 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 147 | 153 | end = new_end; |
| 148 | 154 | continue; |
| 149 | 155 | } |
| 150 | | if (end == 0) return bw.unbuffered_writer.writeSplat(data, splat); |
| 156 | if (end == 0) return track(&bw.bytes_written, try bw.unbuffered_writer.writeSplat(data, splat)); |
| 151 | 157 | buffers[0] = buffer[0..end]; |
| 152 | 158 | const remaining_data = data[i..]; |
| 153 | 159 | const remaining_buffers = buffers[1..]; |
| ... | ... | @@ -163,10 +169,10 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 163 | 169 | const remainder = buffer[n..end]; |
| 164 | 170 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 165 | 171 | list.items.len = remainder.len; |
| 166 | | return end - start_end; |
| 172 | return track(&bw.bytes_written, end - start_end); |
| 167 | 173 | } |
| 168 | 174 | list.items.len = 0; |
| 169 | | return n - start_end; |
| 175 | return track(&bw.bytes_written, n - start_end); |
| 170 | 176 | } |
| 171 | 177 | const n = try bw.unbuffered_writer.writeSplat(send_buffers, 1); |
| 172 | 178 | if (n < end) { |
| ... | ... | @@ -174,10 +180,10 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 174 | 180 | const remainder = buffer[n..end]; |
| 175 | 181 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 176 | 182 | list.items.len = remainder.len; |
| 177 | | return end - start_end; |
| 183 | return track(&bw.bytes_written, end - start_end); |
| 178 | 184 | } |
| 179 | 185 | list.items.len = 0; |
| 180 | | return n - start_end; |
| 186 | return track(&bw.bytes_written, n - start_end); |
| 181 | 187 | } |
| 182 | 188 | |
| 183 | 189 | const pattern = data[data.len - 1]; |
| ... | ... | @@ -187,7 +193,7 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 187 | 193 | // It was added in the loop above; undo it here. |
| 188 | 194 | end -= pattern.len; |
| 189 | 195 | list.items.len = end; |
| 190 | | return end - start_end; |
| 196 | return track(&bw.bytes_written, end - start_end); |
| 191 | 197 | } |
| 192 | 198 | |
| 193 | 199 | const remaining_splat = splat - 1; |
| ... | ... | @@ -195,7 +201,7 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 195 | 201 | switch (pattern.len) { |
| 196 | 202 | 0 => { |
| 197 | 203 | list.items.len = end; |
| 198 | | return end - start_end; |
| 204 | return track(&bw.bytes_written, end - start_end); |
| 199 | 205 | }, |
| 200 | 206 | 1 => { |
| 201 | 207 | const new_end = end + remaining_splat; |
| ... | ... | @@ -203,7 +209,7 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 203 | 209 | @branchHint(.likely); |
| 204 | 210 | @memset(buffer[end..new_end], pattern[0]); |
| 205 | 211 | list.items.len = new_end; |
| 206 | | return new_end - start_end; |
| 212 | return track(&bw.bytes_written, new_end - start_end); |
| 207 | 213 | } |
| 208 | 214 | buffers[0] = buffer[0..end]; |
| 209 | 215 | buffers[1] = pattern; |
| ... | ... | @@ -213,10 +219,10 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 213 | 219 | const remainder = buffer[n..end]; |
| 214 | 220 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 215 | 221 | list.items.len = remainder.len; |
| 216 | | return end - start_end; |
| 222 | return track(&bw.bytes_written, end - start_end); |
| 217 | 223 | } |
| 218 | 224 | list.items.len = 0; |
| 219 | | return n - start_end; |
| 225 | return track(&bw.bytes_written, n - start_end); |
| 220 | 226 | }, |
| 221 | 227 | else => { |
| 222 | 228 | const new_end = end + pattern.len * remaining_splat; |
| ... | ... | @@ -226,7 +232,7 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 226 | 232 | @memcpy(buffer[end..][0..pattern.len], pattern); |
| 227 | 233 | } |
| 228 | 234 | list.items.len = new_end; |
| 229 | | return new_end - start_end; |
| 235 | return track(&bw.bytes_written, new_end - start_end); |
| 230 | 236 | } |
| 231 | 237 | buffers[0] = buffer[0..end]; |
| 232 | 238 | buffers[1] = pattern; |
| ... | ... | @@ -236,14 +242,19 @@ fn passthru_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: us |
| 236 | 242 | const remainder = buffer[n..end]; |
| 237 | 243 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 238 | 244 | list.items.len = remainder.len; |
| 239 | | return end - start_end; |
| 245 | return track(&bw.bytes_written, end - start_end); |
| 240 | 246 | } |
| 241 | 247 | list.items.len = 0; |
| 242 | | return n - start_end; |
| 248 | return track(&bw.bytes_written, n - start_end); |
| 243 | 249 | }, |
| 244 | 250 | } |
| 245 | 251 | } |
| 246 | 252 | |
| 253 | fn track(bytes_written: *usize, n: usize) usize { |
| 254 | bytes_written.* += n; |
| 255 | return n; |
| 256 | } |
| 257 | |
| 247 | 258 | /// When this function is called it means the buffer got full, so it's time |
| 248 | 259 | /// to return an error. However, we still need to make sure all of the |
| 249 | 260 | /// available buffer has been filled. |
| ... | ... | @@ -256,6 +267,7 @@ fn fixed_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize |
| 256 | 267 | const len = @min(bytes.len, dest.len); |
| 257 | 268 | @memcpy(dest[0..len], bytes[0..len]); |
| 258 | 269 | list.items.len += len; |
| 270 | bw.bytes_written = list.items.len; |
| 259 | 271 | } |
| 260 | 272 | const pattern = data[data.len - 1]; |
| 261 | 273 | const dest = list.unusedCapacitySlice(); |
| ... | ... | @@ -265,6 +277,7 @@ fn fixed_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize |
| 265 | 277 | else => for (0..splat - 1) |i| @memcpy(dest[i * pattern.len ..][0..pattern.len], pattern), |
| 266 | 278 | } |
| 267 | 279 | list.items.len = list.capacity; |
| 280 | bw.bytes_written = list.items.len; |
| 268 | 281 | return error.NoSpaceLeft; |
| 269 | 282 | } |
| 270 | 283 | |
| ... | ... | @@ -284,17 +297,11 @@ pub fn write(bw: *BufferedWriter, bytes: []const u8) anyerror!usize { |
| 284 | 297 | return 0; |
| 285 | 298 | } |
| 286 | 299 | list.items.len = 0; |
| 287 | | return n - end; |
| 300 | return track(&bw.bytes_written, n - end); |
| 288 | 301 | } |
| 289 | 302 | @memcpy(buffer[end..new_end], bytes); |
| 290 | 303 | list.items.len = new_end; |
| 291 | | return bytes.len; |
| 292 | | } |
| 293 | | |
| 294 | | /// Convenience function that calls `writeAll` and then returns `bytes.len`. |
| 295 | | pub fn writeAllCount(bw: *BufferedWriter, bytes: []const u8) anyerror!usize { |
| 296 | | try writeAll(bw, bytes); |
| 297 | | return bytes.len; |
| 304 | return track(&bw.bytes_written, bytes.len); |
| 298 | 305 | } |
| 299 | 306 | |
| 300 | 307 | /// Calls `write` as many times as necessary such that all of `bytes` are |
| ... | ... | @@ -305,17 +312,7 @@ pub fn writeAll(bw: *BufferedWriter, bytes: []const u8) anyerror!void { |
| 305 | 312 | } |
| 306 | 313 | |
| 307 | 314 | pub fn print(bw: *BufferedWriter, comptime format: []const u8, args: anytype) anyerror!void { |
| 308 | | _ = try std.fmt.format(bw, format, args); |
| 309 | | } |
| 310 | | |
| 311 | | pub fn printCount(bw: *BufferedWriter, comptime format: []const u8, args: anytype) anyerror!usize { |
| 312 | | return std.fmt.format(bw, format, args); |
| 313 | | } |
| 314 | | |
| 315 | | /// Returns 0 or 1 indicating how many bytes were written. |
| 316 | | pub fn writeByteCount(bw: *BufferedWriter, byte: u8) anyerror!usize { |
| 317 | | try writeByte(bw, byte); |
| 318 | | return 1; |
| 315 | try std.fmt.format(bw, format, args); |
| 319 | 316 | } |
| 320 | 317 | |
| 321 | 318 | pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void { |
| ... | ... | @@ -325,6 +322,7 @@ pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void { |
| 325 | 322 | @branchHint(.likely); |
| 326 | 323 | buffer.ptr[buffer.len] = byte; |
| 327 | 324 | list.items.len = buffer.len + 1; |
| 325 | bw.bytes_written += 1; |
| 328 | 326 | return; |
| 329 | 327 | } |
| 330 | 328 | var buffers: [2][]const u8 = .{ buffer, &.{byte} }; |
| ... | ... | @@ -333,7 +331,9 @@ pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void { |
| 333 | 331 | if (n == 0) { |
| 334 | 332 | @branchHint(.unlikely); |
| 335 | 333 | continue; |
| 336 | | } else if (n >= buffer.len) { |
| 334 | } |
| 335 | bw.bytes_written += 1; |
| 336 | if (n >= buffer.len) { |
| 337 | 337 | @branchHint(.likely); |
| 338 | 338 | if (n > buffer.len) { |
| 339 | 339 | @branchHint(.likely); |
| ... | ... | @@ -353,12 +353,6 @@ pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void { |
| 353 | 353 | } |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | | /// Convenience function that calls `splatByteAll` and then returns `n`. |
| 357 | | pub fn splatByteAllCount(bw: *BufferedWriter, byte: u8, n: usize) anyerror!usize { |
| 358 | | try splatByteAll(bw, byte, n); |
| 359 | | return n; |
| 360 | | } |
| 361 | | |
| 362 | 356 | /// Writes the same byte many times, performing the underlying write call as |
| 363 | 357 | /// many times as necessary. |
| 364 | 358 | pub fn splatByteAll(bw: *BufferedWriter, byte: u8, n: usize) anyerror!void { |
| ... | ... | @@ -438,7 +432,10 @@ fn passthru_writeFile( |
| 438 | 432 | const bw: *BufferedWriter = @alignCast(@ptrCast(context)); |
| 439 | 433 | const list = &bw.buffer; |
| 440 | 434 | const buffer = list.allocatedSlice(); |
| 441 | | if (buffer.len == 0) return bw.unbuffered_writer.writeFile(file, offset, len, headers_and_trailers, headers_len); |
| 435 | if (buffer.len == 0) return track( |
| 436 | &bw.bytes_written, |
| 437 | try bw.unbuffered_writer.writeFile(file, offset, len, headers_and_trailers, headers_len), |
| 438 | ); |
| 442 | 439 | const start_end = list.items.len; |
| 443 | 440 | const headers = headers_and_trailers[0..headers_len]; |
| 444 | 441 | const trailers = headers_and_trailers[headers_len..]; |
| ... | ... | @@ -470,10 +467,10 @@ fn passthru_writeFile( |
| 470 | 467 | const remainder = buffer[n..end]; |
| 471 | 468 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 472 | 469 | list.items.len = remainder.len; |
| 473 | | return end - start_end; |
| 470 | return track(&bw.bytes_written, end - start_end); |
| 474 | 471 | } |
| 475 | 472 | list.items.len = 0; |
| 476 | | return n - start_end; |
| 473 | return track(&bw.bytes_written, n - start_end); |
| 477 | 474 | } |
| 478 | 475 | // Have not made it past the headers yet; must call `writev`. |
| 479 | 476 | const n = try bw.unbuffered_writer.writev(buffers[0 .. buffers_len + 1]); |
| ... | ... | @@ -482,10 +479,10 @@ fn passthru_writeFile( |
| 482 | 479 | const remainder = buffer[n..end]; |
| 483 | 480 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 484 | 481 | list.items.len = remainder.len; |
| 485 | | return end - start_end; |
| 482 | return track(&bw.bytes_written, end - start_end); |
| 486 | 483 | } |
| 487 | 484 | list.items.len = 0; |
| 488 | | return n - start_end; |
| 485 | return track(&bw.bytes_written, n - start_end); |
| 489 | 486 | } |
| 490 | 487 | // All headers written to buffer. |
| 491 | 488 | buffers[0] = buffer[0..end]; |
| ... | ... | @@ -500,10 +497,10 @@ fn passthru_writeFile( |
| 500 | 497 | const remainder = buffer[n..end]; |
| 501 | 498 | std.mem.copyForwards(u8, buffer[0..remainder.len], remainder); |
| 502 | 499 | list.items.len = remainder.len; |
| 503 | | return end - start_end; |
| 500 | return track(&bw.bytes_written, end - start_end); |
| 504 | 501 | } |
| 505 | 502 | list.items.len = 0; |
| 506 | | return n - start_end; |
| 503 | return track(&bw.bytes_written, n - start_end); |
| 507 | 504 | } |
| 508 | 505 | |
| 509 | 506 | pub const WriteFileOptions = struct { |
| ... | ... | @@ -583,54 +580,51 @@ pub fn alignBuffer( |
| 583 | 580 | width: usize, |
| 584 | 581 | alignment: std.fmt.Alignment, |
| 585 | 582 | fill: u8, |
| 586 | | ) anyerror!usize { |
| 583 | ) anyerror!void { |
| 587 | 584 | const padding = if (buffer.len < width) width - buffer.len else 0; |
| 588 | 585 | if (padding == 0) { |
| 589 | 586 | @branchHint(.likely); |
| 590 | | return bw.writeAllCount(buffer); |
| 587 | return bw.writeAll(buffer); |
| 591 | 588 | } |
| 592 | | var n: usize = 0; |
| 593 | 589 | switch (alignment) { |
| 594 | 590 | .left => { |
| 595 | | n += try bw.writeAllCount(buffer); |
| 596 | | n += try bw.splatByteAllCount(fill, padding); |
| 591 | try bw.writeAll(buffer); |
| 592 | try bw.splatByteAll(fill, padding); |
| 597 | 593 | }, |
| 598 | 594 | .center => { |
| 599 | 595 | const left_padding = padding / 2; |
| 600 | 596 | const right_padding = (padding + 1) / 2; |
| 601 | | n += try bw.splatByteAllCount(fill, left_padding); |
| 602 | | n += try bw.writeAllCount(buffer); |
| 603 | | n += try bw.splatByteAllCount(fill, right_padding); |
| 597 | try bw.splatByteAll(fill, left_padding); |
| 598 | try bw.writeAll(buffer); |
| 599 | try bw.splatByteAll(fill, right_padding); |
| 604 | 600 | }, |
| 605 | 601 | .right => { |
| 606 | | n += try bw.splatByteAllCount(fill, padding); |
| 607 | | n += try bw.writeAllCount(buffer); |
| 602 | try bw.splatByteAll(fill, padding); |
| 603 | try bw.writeAll(buffer); |
| 608 | 604 | }, |
| 609 | 605 | } |
| 610 | | return n; |
| 611 | 606 | } |
| 612 | 607 | |
| 613 | | pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.fmt.Options) anyerror!usize { |
| 608 | pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.fmt.Options) anyerror!void { |
| 614 | 609 | return alignBuffer(bw, buffer, options.width orelse buffer.len, options.alignment, options.fill); |
| 615 | 610 | } |
| 616 | 611 | |
| 617 | | pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!usize { |
| 612 | pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void { |
| 618 | 613 | const T = @TypeOf(value); |
| 619 | | var n: usize = 0; |
| 620 | 614 | switch (@typeInfo(T)) { |
| 621 | 615 | .pointer => |info| { |
| 622 | | n += try bw.writeAllCount(@typeName(info.child) ++ "@"); |
| 616 | try bw.writeAll(@typeName(info.child) ++ "@"); |
| 623 | 617 | if (info.size == .slice) |
| 624 | | n += try printIntOptions(bw, @intFromPtr(value.ptr), 16, .lower, .{}) |
| 618 | try printIntOptions(bw, @intFromPtr(value.ptr), 16, .lower, .{}) |
| 625 | 619 | else |
| 626 | | n += try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{}); |
| 627 | | return n; |
| 620 | try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{}); |
| 621 | return; |
| 628 | 622 | }, |
| 629 | 623 | .optional => |info| { |
| 630 | 624 | if (@typeInfo(info.child) == .pointer) { |
| 631 | | n += try bw.writeAll(@typeName(info.child) ++ "@"); |
| 632 | | n += try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{}); |
| 633 | | return n; |
| 625 | try bw.writeAll(@typeName(info.child) ++ "@"); |
| 626 | try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{}); |
| 627 | return; |
| 634 | 628 | } |
| 635 | 629 | }, |
| 636 | 630 | else => {}, |
| ... | ... | @@ -645,7 +639,7 @@ pub fn printValue( |
| 645 | 639 | options: std.fmt.Options, |
| 646 | 640 | value: anytype, |
| 647 | 641 | max_depth: usize, |
| 648 | | ) anyerror!usize { |
| 642 | ) anyerror!void { |
| 649 | 643 | const T = @TypeOf(value); |
| 650 | 644 | const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) |
| 651 | 645 | defaultFormatString(T) |
| ... | ... | @@ -700,104 +694,96 @@ pub fn printValue( |
| 700 | 694 | }, |
| 701 | 695 | .error_set => { |
| 702 | 696 | if (actual_fmt.len > 0 and actual_fmt[0] == 's') { |
| 703 | | return bw.writeAllCount(@errorName(value)); |
| 697 | return bw.writeAll(@errorName(value)); |
| 704 | 698 | } else if (actual_fmt.len != 0) { |
| 705 | 699 | invalidFmtError(fmt, value); |
| 706 | 700 | } else { |
| 707 | | var n: usize = 0; |
| 708 | | n += try bw.writeAllCount("error."); |
| 709 | | n += try bw.writeAllCount(@errorName(value)); |
| 710 | | return n; |
| 701 | try bw.writeAll("error."); |
| 702 | try bw.writeAll(@errorName(value)); |
| 711 | 703 | } |
| 712 | 704 | }, |
| 713 | 705 | .@"enum" => |enum_info| { |
| 714 | | var n: usize = 0; |
| 715 | | n += try bw.writeAllCount(@typeName(T)); |
| 706 | try bw.writeAll(@typeName(T)); |
| 716 | 707 | if (enum_info.is_exhaustive) { |
| 717 | 708 | if (actual_fmt.len != 0) invalidFmtError(fmt, value); |
| 718 | | n += try bw.writeAllCount("."); |
| 719 | | n += try bw.writeAllCount(@tagName(value)); |
| 720 | | return n; |
| 709 | try bw.writeAll("."); |
| 710 | try bw.writeAll(@tagName(value)); |
| 711 | return; |
| 721 | 712 | } |
| 722 | 713 | |
| 723 | 714 | // Use @tagName only if value is one of known fields |
| 724 | 715 | @setEvalBranchQuota(3 * enum_info.fields.len); |
| 725 | 716 | inline for (enum_info.fields) |enumField| { |
| 726 | 717 | if (@intFromEnum(value) == enumField.value) { |
| 727 | | n += try bw.writeAllCount("."); |
| 728 | | n += try bw.writeAllCount(@tagName(value)); |
| 718 | try bw.writeAll("."); |
| 719 | try bw.writeAll(@tagName(value)); |
| 729 | 720 | return; |
| 730 | 721 | } |
| 731 | 722 | } |
| 732 | 723 | |
| 733 | | n += try bw.writeByteCount('('); |
| 734 | | n += try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth); |
| 735 | | n += try bw.writeByteCount(')'); |
| 736 | | return n; |
| 724 | try bw.writeByteCount('('); |
| 725 | try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth); |
| 726 | try bw.writeByteCount(')'); |
| 737 | 727 | }, |
| 738 | 728 | .@"union" => |info| { |
| 739 | 729 | if (actual_fmt.len != 0) invalidFmtError(fmt, value); |
| 740 | | var n: usize = 0; |
| 741 | | n += try bw.writeAllCount(@typeName(T)); |
| 730 | try bw.writeAll(@typeName(T)); |
| 742 | 731 | if (max_depth == 0) { |
| 743 | | n += bw.writeAllCount("{ ... }"); |
| 744 | | return n; |
| 732 | bw.writeAll("{ ... }"); |
| 733 | return; |
| 745 | 734 | } |
| 746 | 735 | if (info.tag_type) |UnionTagType| { |
| 747 | | n += try bw.writeAllCount("{ ."); |
| 748 | | n += try bw.writeAllCount(@tagName(@as(UnionTagType, value))); |
| 749 | | n += try bw.writeAllCount(" = "); |
| 736 | try bw.writeAll("{ ."); |
| 737 | try bw.writeAll(@tagName(@as(UnionTagType, value))); |
| 738 | try bw.writeAll(" = "); |
| 750 | 739 | inline for (info.fields) |u_field| { |
| 751 | 740 | if (value == @field(UnionTagType, u_field.name)) { |
| 752 | | n += try printValue(bw, ANY, options, @field(value, u_field.name), max_depth - 1); |
| 741 | try printValue(bw, ANY, options, @field(value, u_field.name), max_depth - 1); |
| 753 | 742 | } |
| 754 | 743 | } |
| 755 | | n += try bw.writeAllCount(" }"); |
| 744 | try bw.writeAll(" }"); |
| 756 | 745 | } else { |
| 757 | | n += try bw.writeByte('@'); |
| 758 | | n += try bw.printIntOptions(@intFromPtr(&value), 16, .lower); |
| 746 | try bw.writeByte('@'); |
| 747 | try bw.printIntOptions(@intFromPtr(&value), 16, .lower); |
| 759 | 748 | } |
| 760 | | return n; |
| 761 | 749 | }, |
| 762 | 750 | .@"struct" => |info| { |
| 763 | 751 | if (actual_fmt.len != 0) invalidFmtError(fmt, value); |
| 764 | | var n: usize = 0; |
| 765 | 752 | if (info.is_tuple) { |
| 766 | 753 | // Skip the type and field names when formatting tuples. |
| 767 | 754 | if (max_depth == 0) { |
| 768 | | n += try bw.writeAllCount("{ ... }"); |
| 769 | | return n; |
| 755 | try bw.writeAll("{ ... }"); |
| 756 | return; |
| 770 | 757 | } |
| 771 | | n += try bw.writeAllCount("{"); |
| 758 | try bw.writeAll("{"); |
| 772 | 759 | inline for (info.fields, 0..) |f, i| { |
| 773 | 760 | if (i == 0) { |
| 774 | | n += try bw.writeAllCount(" "); |
| 761 | try bw.writeAll(" "); |
| 775 | 762 | } else { |
| 776 | | n += try bw.writeAllCount(", "); |
| 763 | try bw.writeAll(", "); |
| 777 | 764 | } |
| 778 | | n += try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1); |
| 765 | try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1); |
| 779 | 766 | } |
| 780 | | n += try bw.writeAllCount(" }"); |
| 781 | | return n; |
| 767 | try bw.writeAll(" }"); |
| 768 | return; |
| 782 | 769 | } |
| 783 | | n += try bw.writeAllCount(@typeName(T)); |
| 770 | try bw.writeAll(@typeName(T)); |
| 784 | 771 | if (max_depth == 0) { |
| 785 | | n += try bw.writeAllCount("{ ... }"); |
| 786 | | return n; |
| 772 | try bw.writeAll("{ ... }"); |
| 773 | return; |
| 787 | 774 | } |
| 788 | | n += try bw.writeAllCount("{"); |
| 775 | try bw.writeAll("{"); |
| 789 | 776 | inline for (info.fields, 0..) |f, i| { |
| 790 | 777 | if (i == 0) { |
| 791 | | n += try bw.writeAllCount(" ."); |
| 778 | try bw.writeAll(" ."); |
| 792 | 779 | } else { |
| 793 | | n += try bw.writeAllCount(", ."); |
| 780 | try bw.writeAll(", ."); |
| 794 | 781 | } |
| 795 | | n += try bw.writeAllCount(f.name); |
| 796 | | n += try bw.writeAllCount(" = "); |
| 797 | | n += try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1); |
| 782 | try bw.writeAll(f.name); |
| 783 | try bw.writeAll(" = "); |
| 784 | try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1); |
| 798 | 785 | } |
| 799 | | n += try bw.writeAllCount(" }"); |
| 800 | | return n; |
| 786 | try bw.writeAll(" }"); |
| 801 | 787 | }, |
| 802 | 788 | .pointer => |ptr_info| switch (ptr_info.size) { |
| 803 | 789 | .one => switch (@typeInfo(ptr_info.child)) { |
| ... | ... | @@ -806,10 +792,9 @@ pub fn printValue( |
| 806 | 792 | }, |
| 807 | 793 | else => { |
| 808 | 794 | var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" }; |
| 809 | | var n: usize = 0; |
| 810 | | n += try writevAll(bw, &buffers); |
| 811 | | n += try printIntOptions(bw, @intFromPtr(value), 16, .lower, options); |
| 812 | | return n; |
| 795 | try writevAll(bw, &buffers); |
| 796 | try printIntOptions(bw, @intFromPtr(value), 16, .lower, options); |
| 797 | return; |
| 813 | 798 | }, |
| 814 | 799 | }, |
| 815 | 800 | .many, .c => { |
| ... | ... | @@ -827,7 +812,7 @@ pub fn printValue( |
| 827 | 812 | if (actual_fmt.len == 0) |
| 828 | 813 | @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})"); |
| 829 | 814 | if (max_depth == 0) { |
| 830 | | return bw.writeAllCount("{ ... }"); |
| 815 | return bw.writeAll("{ ... }"); |
| 831 | 816 | } |
| 832 | 817 | if (ptr_info.child == u8) switch (actual_fmt.len) { |
| 833 | 818 | 1 => switch (actual_fmt[0]) { |
| ... | ... | @@ -841,23 +826,21 @@ pub fn printValue( |
| 841 | 826 | }, |
| 842 | 827 | else => {}, |
| 843 | 828 | }; |
| 844 | | var n: usize = 0; |
| 845 | | n += try bw.writeAllCount("{ "); |
| 829 | try bw.writeAll("{ "); |
| 846 | 830 | for (value, 0..) |elem, i| { |
| 847 | | n += try printValue(bw, actual_fmt, options, elem, max_depth - 1); |
| 831 | try printValue(bw, actual_fmt, options, elem, max_depth - 1); |
| 848 | 832 | if (i != value.len - 1) { |
| 849 | | n += try bw.writeAllCount(", "); |
| 833 | try bw.writeAll(", "); |
| 850 | 834 | } |
| 851 | 835 | } |
| 852 | | n += try bw.writeAllCount(" }"); |
| 853 | | return n; |
| 836 | try bw.writeAll(" }"); |
| 854 | 837 | }, |
| 855 | 838 | }, |
| 856 | 839 | .array => |info| { |
| 857 | 840 | if (actual_fmt.len == 0) |
| 858 | 841 | @compileError("cannot format array without a specifier (i.e. {s} or {any})"); |
| 859 | 842 | if (max_depth == 0) { |
| 860 | | return bw.writeAllCount("{ ... }"); |
| 843 | return bw.writeAll("{ ... }"); |
| 861 | 844 | } |
| 862 | 845 | if (info.child == u8) { |
| 863 | 846 | if (actual_fmt[0] == 's') { |
| ... | ... | @@ -868,32 +851,28 @@ pub fn printValue( |
| 868 | 851 | return printHex(bw, &value, .upper); |
| 869 | 852 | } |
| 870 | 853 | } |
| 871 | | var n: usize = 0; |
| 872 | | n += try bw.writeAllCount("{ "); |
| 854 | try bw.writeAll("{ "); |
| 873 | 855 | for (value, 0..) |elem, i| { |
| 874 | | n += try printValue(bw, actual_fmt, options, elem, max_depth - 1); |
| 856 | try printValue(bw, actual_fmt, options, elem, max_depth - 1); |
| 875 | 857 | if (i < value.len - 1) { |
| 876 | | n += try bw.writeAllCount(", "); |
| 858 | try bw.writeAll(", "); |
| 877 | 859 | } |
| 878 | 860 | } |
| 879 | | n += try bw.writeAllCount(" }"); |
| 880 | | return n; |
| 861 | try bw.writeAll(" }"); |
| 881 | 862 | }, |
| 882 | 863 | .vector => |info| { |
| 883 | 864 | if (max_depth == 0) { |
| 884 | | return bw.writeAllCount("{ ... }"); |
| 865 | return bw.writeAll("{ ... }"); |
| 885 | 866 | } |
| 886 | | var n: usize = 0; |
| 887 | | n += try bw.writeAllCount("{ "); |
| 867 | try bw.writeAll("{ "); |
| 888 | 868 | var i: usize = 0; |
| 889 | 869 | while (i < info.len) : (i += 1) { |
| 890 | | n += try printValue(bw, actual_fmt, options, value[i], max_depth - 1); |
| 870 | try printValue(bw, actual_fmt, options, value[i], max_depth - 1); |
| 891 | 871 | if (i < info.len - 1) { |
| 892 | | n += try bw.writeAllCount(", "); |
| 872 | try bw.writeAll(", "); |
| 893 | 873 | } |
| 894 | 874 | } |
| 895 | | n += try bw.writeAllCount(" }"); |
| 896 | | return n; |
| 875 | try bw.writeAll(" }"); |
| 897 | 876 | }, |
| 898 | 877 | .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), |
| 899 | 878 | .type => { |
| ... | ... | @@ -918,7 +897,7 @@ pub fn printInt( |
| 918 | 897 | comptime fmt: []const u8, |
| 919 | 898 | options: std.fmt.Options, |
| 920 | 899 | value: anytype, |
| 921 | | ) anyerror!usize { |
| 900 | ) anyerror!void { |
| 922 | 901 | const int_value = if (@TypeOf(value) == comptime_int) blk: { |
| 923 | 902 | const Int = std.math.IntFittingRange(value, value); |
| 924 | 903 | break :blk @as(Int, value); |
| ... | ... | @@ -962,15 +941,15 @@ pub fn printInt( |
| 962 | 941 | comptime unreachable; |
| 963 | 942 | } |
| 964 | 943 | |
| 965 | | pub fn printAsciiChar(bw: *BufferedWriter, c: u8, options: std.fmt.Options) anyerror!usize { |
| 944 | pub fn printAsciiChar(bw: *BufferedWriter, c: u8, options: std.fmt.Options) anyerror!void { |
| 966 | 945 | return alignBufferOptions(bw, @as(*const [1]u8, &c), options); |
| 967 | 946 | } |
| 968 | 947 | |
| 969 | | pub fn printAscii(bw: *BufferedWriter, bytes: []const u8, options: std.fmt.Options) anyerror!usize { |
| 948 | pub fn printAscii(bw: *BufferedWriter, bytes: []const u8, options: std.fmt.Options) anyerror!void { |
| 970 | 949 | return alignBufferOptions(bw, bytes, options); |
| 971 | 950 | } |
| 972 | 951 | |
| 973 | | pub fn printUnicodeCodepoint(bw: *BufferedWriter, c: u21, options: std.fmt.Options) anyerror!usize { |
| 952 | pub fn printUnicodeCodepoint(bw: *BufferedWriter, c: u21, options: std.fmt.Options) anyerror!void { |
| 974 | 953 | var buf: [4]u8 = undefined; |
| 975 | 954 | const len = try std.unicode.utf8Encode(c, &buf); |
| 976 | 955 | return alignBufferOptions(bw, buf[0..len], options); |
| ... | ... | @@ -982,7 +961,7 @@ pub fn printIntOptions( |
| 982 | 961 | base: u8, |
| 983 | 962 | case: std.fmt.Case, |
| 984 | 963 | options: std.fmt.Options, |
| 985 | | ) anyerror!usize { |
| 964 | ) anyerror!void { |
| 986 | 965 | assert(base >= 2); |
| 987 | 966 | |
| 988 | 967 | const int_value = if (@TypeOf(value) == comptime_int) blk: { |
| ... | ... | @@ -1049,7 +1028,7 @@ pub fn printFloat( |
| 1049 | 1028 | comptime fmt: []const u8, |
| 1050 | 1029 | options: std.fmt.Options, |
| 1051 | 1030 | value: anytype, |
| 1052 | | ) anyerror!usize { |
| 1031 | ) anyerror!void { |
| 1053 | 1032 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; |
| 1054 | 1033 | |
| 1055 | 1034 | if (fmt.len > 1) invalidFmtError(fmt, value); |
| ... | ... | @@ -1337,7 +1316,7 @@ pub fn printDuration(bw: *BufferedWriter, nanoseconds: anytype, options: std.fmt |
| 1337 | 1316 | return alignBufferOptions(bw, sub_bw.getWritten(), options); |
| 1338 | 1317 | } |
| 1339 | 1318 | |
| 1340 | | pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anyerror!usize { |
| 1319 | pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anyerror!void { |
| 1341 | 1320 | const charset = switch (case) { |
| 1342 | 1321 | .upper => "0123456789ABCDEF", |
| 1343 | 1322 | .lower => "0123456789abcdef", |
| ... | ... | @@ -1346,21 +1325,18 @@ pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anye |
| 1346 | 1325 | try writeByte(bw, charset[c >> 4]); |
| 1347 | 1326 | try writeByte(bw, charset[c & 15]); |
| 1348 | 1327 | } |
| 1349 | | return bytes.len * 2; |
| 1350 | 1328 | } |
| 1351 | 1329 | |
| 1352 | | pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!usize { |
| 1330 | pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!void { |
| 1353 | 1331 | var chunker = std.mem.window(u8, bytes, 3, 3); |
| 1354 | 1332 | var temp: [5]u8 = undefined; |
| 1355 | | var n: usize = 0; |
| 1356 | 1333 | while (chunker.next()) |chunk| { |
| 1357 | | n += try bw.writeAllCount(std.base64.standard.Encoder.encode(&temp, chunk)); |
| 1334 | try bw.writeAll(std.base64.standard.Encoder.encode(&temp, chunk)); |
| 1358 | 1335 | } |
| 1359 | | return n; |
| 1360 | 1336 | } |
| 1361 | 1337 | |
| 1362 | 1338 | /// Write a single unsigned integer as unsigned LEB128 to the given writer. |
| 1363 | | pub fn writeUleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!usize { |
| 1339 | pub fn writeUleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!void { |
| 1364 | 1340 | const Arg = @TypeOf(arg); |
| 1365 | 1341 | const Int = switch (Arg) { |
| 1366 | 1342 | comptime_int => std.math.IntFittingRange(arg, arg), |
| ... | ... | @@ -1368,23 +1344,21 @@ pub fn writeUleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!usize { |
| 1368 | 1344 | }; |
| 1369 | 1345 | const Value = if (@typeInfo(Int).int.bits < 8) u8 else Int; |
| 1370 | 1346 | var value: Value = arg; |
| 1371 | | var n: usize = 0; |
| 1372 | 1347 | |
| 1373 | 1348 | while (true) { |
| 1374 | 1349 | const byte: u8 = @truncate(value & 0x7f); |
| 1375 | 1350 | value >>= 7; |
| 1376 | 1351 | if (value == 0) { |
| 1377 | 1352 | try bw.writeByte(byte); |
| 1378 | | return n + 1; |
| 1353 | return; |
| 1379 | 1354 | } else { |
| 1380 | 1355 | try bw.writeByte(byte | 0x80); |
| 1381 | | n += 1; |
| 1382 | 1356 | } |
| 1383 | 1357 | } |
| 1384 | 1358 | } |
| 1385 | 1359 | |
| 1386 | 1360 | /// Write a single signed integer as signed LEB128 to the given writer. |
| 1387 | | pub fn writeIleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!usize { |
| 1361 | pub fn writeIleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!void { |
| 1388 | 1362 | const Arg = @TypeOf(arg); |
| 1389 | 1363 | const Int = switch (Arg) { |
| 1390 | 1364 | comptime_int => std.math.IntFittingRange(-@abs(arg), @abs(arg)), |
| ... | ... | @@ -1393,7 +1367,6 @@ pub fn writeIleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!usize { |
| 1393 | 1367 | const Signed = if (@typeInfo(Int).int.bits < 8) i8 else Int; |
| 1394 | 1368 | const Unsigned = std.meta.Int(.unsigned, @typeInfo(Signed).int.bits); |
| 1395 | 1369 | var value: Signed = arg; |
| 1396 | | var n: usize = 0; |
| 1397 | 1370 | |
| 1398 | 1371 | while (true) { |
| 1399 | 1372 | const unsigned: Unsigned = @bitCast(value); |
| ... | ... | @@ -1401,11 +1374,10 @@ pub fn writeIleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!usize { |
| 1401 | 1374 | value >>= 6; |
| 1402 | 1375 | if (value == -1 or value == 0) { |
| 1403 | 1376 | try bw.writeByte(byte & 0x7F); |
| 1404 | | return n + 1; |
| 1377 | return; |
| 1405 | 1378 | } else { |
| 1406 | 1379 | value >>= 1; |
| 1407 | 1380 | try bw.writeByte(byte | 0x80); |
| 1408 | | n += 1; |
| 1409 | 1381 | } |
| 1410 | 1382 | } |
| 1411 | 1383 | } |