I have a fixed buffer (i.e. [128]u8) that I want to print into. I could use std.fmt.bufPrint or Writer.print, however, these will error if what I want to print is over the buffer length. Normally, that’s a good thing. However, for my use case, I want to fill up the buffer as much as possible, all the way to the length and stop writing at that point and return.
What is the best way to do this?
var buf: [128]u8 = undefined;
// Some writer setup or something
var writer: ???;
writer.print("App - {s}", .{some_runtime_known_string});
//Use written
why not just catch |err| if (err != error.WriteFailed) return err?
the written will be buf
I wrote the fn below to a similar thing the past. See if it fits your need:
const std = @import("std");
pub fn writeBuffer(buffer: []u8, str: []const u8, pos: usize) !void {
if (pos >= buffer.len) return error.OutOfRange;
const length = @min(str.len, buffer.len - pos);
@memcpy(buffer[pos..(pos + length)], str[0..length]);
}
pub fn main() !void {
var buf: [128]u8 = [_]u8{0} ** 128;
try writeBuffer(&buf, "The quick brown fox", 0);
std.debug.print("Buf: >>>{s}<<<", .{ buf });
std.debug.print("{s}", .{ "\n" });
try writeBuffer(&buf, " jumps over the lazy dog.", 19);
std.debug.print("Buf: >>>{s}<<<", .{ buf });
}
2 Likes
An Io.Writer.fixed should work I think. Internally it uses fixedDrain which has this to say:
/// When this function is called it usually means the buffer got full, so it's
/// time to return an error. However, we still need to make sure all of the
/// available buffer has been filled. Also, it may be called from `flush` in
/// which case it should return successfully.
pub fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { ... }
So you would get and error, while still having the buffer filled.
1 Like
Now that I think about it, you can, if you already have a writer, wrap it in a limited one. That should likely also work