Hi all, I’m trying to mock up a quick wrapper around bufPrint to be able to turn a formatted string into unicode codepoints.
Here is the code that intends to do that:
pub fn formatAsCodepoints(comptime out_buffer: []Codepoint, comptime format_string: []const u8, arguments: anytype) anyerror![]Codepoint {
var bytes_buffer: [out_buffer.len*4]u8 = undefined;
var printed_bytes: [ ]u8 = try bufPrint(&bytes_buffer, format_string, arguments);
var oidx: usize = 0;
while (printed_bytes.len > 0) {
if (printed_bytes[0] & 0b10000000 == 0b00000000) {
out_buffer[oidx] = .{ .word = @as(u32, printed_bytes[0]) };
printed_bytes = printed_bytes[1..];
} else if (printed_bytes[0] & 0b11100000 == 0b11000000) {
if (printed_bytes.len < 2) return error.UndefindeError;
out_buffer[oidx] = .{ .word = @as(u32, try utf8Decode2(printed_bytes[0..2].*)) };
printed_bytes = printed_bytes[2..];
} else if (printed_bytes[0] & 0b11110000 == 0b11100000) {
if (printed_bytes.len < 3) return error.UndefindeError;
out_buffer[oidx] = .{ .word = @as(u32, try utf8Decode3(printed_bytes[0..3].*)) };
printed_bytes = printed_bytes[3..];
} else {
if (printed_bytes.len < 4) return error.UndefindeError;
out_buffer[oidx] = .{ .word = @as(u32, try utf8Decode4(printed_bytes[0..4].*)) };
printed_bytes = printed_bytes[4..];
}
oidx += 1;
}
return out_buffer[0..oidx];
}
I want to use the out_buffer to determine the size of bytes_buffer for bufPrint so I set it to comptime in the function parameters, but at the call site:
var codepoint_buffer: [1024]Codepoint = undefined;
const formatted: [ ]Codepoint = try tc.formatAsCodepoints(&codepoint_buffer, "hello there!", .{});
print("{any}\n", .{formatted});
I am getting the error:
main.zig:49:73: error: unable to resolve comptime value
const formatted: [ ]Codepoint = try tc.formatAsCodepoints(&codepoint_buffer, "hello there!", .{});
^~~~~~~~~~~~~~~~~
main.zig:49:73: note: argument to comptime parameter must be comptime-known
textcrops.zig:281:27: note: parameter declared comptime here
pub fn formatAsCodepoints(comptime out_buffer: []Codepoint, comptime format_string: []const u8, arguments: anytype) anyerror![]Codepoint {
I figured doing things the way that I did would just work as you seem to be able to just do this with string literals, but is there something important about those technically being *const [:0]u8 that I haven’t considered?
I created this modified version that works:
pub fn formatAsCodepoints(out_buffer_pointer: anytype, comptime format_string: []const u8, arguments: anytype) anyerror![]Codepoint {
if (!(
@typeInfo(@TypeOf(out_buffer_pointer)) == .pointer
and @typeInfo(@typeInfo(@TypeOf(out_buffer_pointer)).pointer.child) == .array
)) @compileError("expected pointer to array");
const out_buffer_length: comptime_int = @typeInfo(@typeInfo(@TypeOf(out_buffer_pointer)).pointer.child).array.len;
const out_buffer: *[out_buffer_length]Codepoint = @constCast(out_buffer_pointer);
var bytes_buffer: [out_buffer_length*4]u8 = undefined;
var printed_bytes: [ ]u8 = try bufPrint(&bytes_buffer, format_string, arguments);
var oidx: usize = 0;
while (printed_bytes.len > 0) {
if (printed_bytes[0] & 0b10000000 == 0b00000000) {
out_buffer.*[oidx] = .{ .word = @as(u32, printed_bytes[0]) };
printed_bytes = printed_bytes[1..];
} else if (printed_bytes[0] & 0b11100000 == 0b11000000) {
if (printed_bytes.len < 2) return error.UndefindeError;
out_buffer.*[oidx] = .{ .word = @as(u32, try utf8Decode2(printed_bytes[0..2].*)) };
printed_bytes = printed_bytes[2..];
} else if (printed_bytes[0] & 0b11110000 == 0b11100000) {
if (printed_bytes.len < 3) return error.UndefindeError;
out_buffer.*[oidx] = .{ .word = @as(u32, try utf8Decode3(printed_bytes[0..3].*)) };
printed_bytes = printed_bytes[3..];
} else {
if (printed_bytes.len < 4) return error.UndefindeError;
out_buffer.*[oidx] = .{ .word = @as(u32, try utf8Decode4(printed_bytes[0..4].*)) };
printed_bytes = printed_bytes[4..];
}
oidx += 1;
}
return out_buffer.*[0..oidx];
}
Is the second way just the way that you’ve got to do it? Or is there a ‘nicer’ way to pass comptime known slices?
Any information or advice is greatly appreciated!