zig-glib-log/src/main.zig

73 lines
2.3 KiB
Zig

const std = @import("std");
const testing = std.testing;
/// Returns the log function, which must be present in the root module.
pub fn log(
/// The value returned by @cImport.
/// Must include the "glib.h" or "glib/gmessages.h" header.
comptime c: type,
/// The name of the module used for the log output.
comptime module_name: []const u8,
/// The length of the buffer used for the formatted output.
/// This is the maximum length of log messages.
comptime buf_size: usize,
) @TypeOf(LogStruct(c, module_name, buf_size).log) {
return LogStruct(c, module_name, buf_size).log;
}
fn LogStruct(comptime c: type, comptime module_name: []const u8, comptime buf_size: usize) type {
return struct {
threadlocal var fmt_buf: [buf_size]u8 = undefined;
pub fn log(
comptime level: std.log.Level,
comptime scope: @TypeOf(.EnumLiteral),
comptime format: []const u8,
args: anytype,
) void {
const g_level = switch (level) {
.err => c.G_LOG_LEVEL_CRITICAL,
.warn => c.G_LOG_LEVEL_WARNING,
.info => c.G_LOG_LEVEL_INFO,
.debug => c.G_LOG_LEVEL_DEBUG,
};
const s = std.fmt.bufPrintZ(
&@This().fmt_buf,
format,
args,
) catch return;
var fields = [_]c.GLogField{
c.GLogField{
.key = "GLIB_DOMAIN",
.value = @ptrCast(
*const anyopaque,
// don't include scope name if not explicitly specified
if (std.mem.eql(u8, @tagName(scope), "default"))
module_name
else
module_name ++ "-" ++ @tagName(scope),
),
.length = -1,
},
c.GLogField{
.key = "MESSAGE",
.value = @ptrCast(*const anyopaque, s),
.length = -1,
},
};
c.g_log_structured_array(
g_level,
&fields,
fields.len,
);
}
};
}
test {
std.testing.refAllDecls(@This());
}