Created
August 31, 2024 19:42
-
-
Save dadepo/a0c47dda6fc87aaf737260f1a5961a55 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Without printing comptime argument or anytype. | |
const std = @import("std"); | |
const assert = std.debug.assert; | |
pub const Logger = ScopedLogger(null); | |
pub fn ScopedLogger(comptime maybe_scope: ?type) type { | |
return struct { | |
ptr: *anyopaque, | |
writeFn: *const fn (ptr: *anyopaque, buf: []const u8) void, | |
pub fn init(pointer: anytype, comptime writeFn: fn (ptr: @TypeOf(pointer), buf: []const u8) void) ScopedLogger(maybe_scope) { | |
const Ptr = @TypeOf(pointer); | |
assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer | |
assert(@typeInfo(Ptr).Pointer.size == .One); // Must be a single-item pointer | |
assert(@typeInfo(@typeInfo(Ptr).Pointer.child) == .Struct); // Must point to a struct | |
const gen = struct { | |
fn write(ptr: *anyopaque, buf: []const u8) void { | |
const self: Ptr = @ptrCast(@alignCast(ptr)); | |
writeFn(self, buf); | |
} | |
}; | |
return .{ | |
.ptr = pointer, | |
.writeFn = gen.write, | |
}; | |
} | |
pub fn unscope(logger: *ScopedLogger(maybe_scope)) ScopedLogger(null) { | |
return .{ | |
.ptr = logger, | |
.writeFn = logger.writeFn, | |
}; | |
} | |
pub fn log(logger: ScopedLogger(maybe_scope), buf: []const u8) void { | |
if (maybe_scope) |scope| { | |
logger.writeFn(logger.ptr, @typeName(scope)); | |
logger.writeFn(logger.ptr, "-"); | |
logger.writeFn(logger.ptr, buf); | |
} else { | |
logger.writeFn(logger.ptr, "[ - ]"); | |
logger.writeFn(logger.ptr, buf); | |
} | |
} | |
}; | |
} | |
pub const StandardErrLoger = struct { | |
pub fn init() StandardErrLoger { | |
return .{}; | |
} | |
pub fn scopedLogger(self: *StandardErrLoger, comptime scope: type) ScopedLogger(scope) { | |
return ScopedLogger(scope).init(self, write); | |
} | |
pub fn logger(self: *StandardErrLoger) ScopedLogger(null) { | |
return Logger.init(self, write); | |
} | |
fn write(_: *StandardErrLoger, buf: []const u8) void { | |
std.debug.print("{s}", .{buf}); | |
} | |
}; | |
// var std_logger = log.StandardErrLoger.init(); | |
// var scopped_logger = std_logger.scopedLogger(@This()); | |
// scopped_logger.log("Hello world\n"); | |
// var unscopped_logger = scopped_logger.unscope(); | |
// unscopped_logger.log("Hello world"); | |
// zig run src/main.zig | |
// main-Hello world | |
// [ - ]Hello world% | |
// Trying to support printing comptime argument or anytype. | |
// To be able to print k/v fields | |
// var std_logger = log.StandardErrLoger.init(); | |
// var scopped_logger = std_logger.scopedLogger(@This()); | |
// scopped_logger.log("Hello world\n", .{.k1, "v2"}); | |
// Implementation: | |
const std = @import("std"); | |
const assert = std.debug.assert; | |
pub const Logger = ScopedLogger(null); | |
pub fn ScopedLogger(comptime maybe_scope: ?type) type { | |
return struct { | |
ptr: *anyopaque, | |
writeFn: *const fn (ptr: *anyopaque, buf: []const u8, maybe_fields: anytype) void, | |
pub fn init(pointer: anytype, comptime writeFn: fn (ptr: @TypeOf(pointer), buf: []const u8, maybe_fields: anytype) void) ScopedLogger(maybe_scope) { | |
const Ptr = @TypeOf(pointer); | |
assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer | |
assert(@typeInfo(Ptr).Pointer.size == .One); // Must be a single-item pointer | |
assert(@typeInfo(@typeInfo(Ptr).Pointer.child) == .Struct); // Must point to a struct | |
const gen = struct { | |
fn write(ptr: *anyopaque, buf: []const u8, maybe_fields: anytype) void { | |
const self: Ptr = @ptrCast(@alignCast(ptr)); | |
writeFn(self, buf, maybe_fields); | |
} | |
}; | |
return .{ | |
.ptr = pointer, | |
.writeFn = gen.write, | |
}; | |
} | |
pub fn unscope(logger: *ScopedLogger(maybe_scope)) ScopedLogger(null) { | |
return .{ | |
.ptr = logger, | |
.writeFn = logger.writeFn, | |
}; | |
} | |
pub fn log(logger: ScopedLogger(maybe_scope), buf: []const u8, maybe_fields: anytype) void { | |
_ = &maybe_fields; | |
if (maybe_scope) |scope| { | |
logger.writeFn(logger.ptr, @typeName(scope)); | |
logger.writeFn(logger.ptr, "-"); | |
logger.writeFn(logger.ptr, buf); | |
} else { | |
logger.writeFn(logger.ptr, "[ - ]"); | |
logger.writeFn(logger.ptr, buf); | |
} | |
} | |
}; | |
} | |
pub const StandardErrLoger = struct { | |
pub fn init() StandardErrLoger { | |
return .{}; | |
} | |
pub fn scopedLogger(self: *StandardErrLoger, comptime scope: type) ScopedLogger(scope) { | |
return ScopedLogger(scope).init(self, write); | |
} | |
pub fn logger(self: *StandardErrLoger) ScopedLogger(null) { | |
return Logger.init(self, write); | |
} | |
fn write(_: *StandardErrLoger, buf: []const u8, maybe_fields: anytype) void { | |
_ = &maybe_fields; | |
std.debug.print("{s}", .{buf}); | |
} | |
}; | |
// Compilation error | |
zig run src/main.zig | |
src/main.zig:159:36: error: unable to resolve comptime value | |
var scopped_logger = std_logger.scopedLogger(@This()); | |
~~~~~~~~~~^~~~~~~~~~~~~ | |
src/main.zig:159:36: note: argument to function being called at comptime must be comptime-known | |
src/log.zig:53:84: note: expression is evaluated at comptime because the generic function was instantiated with a comptime-only return type | |
pub fn scopedLogger(self: *StandardErrLoger, comptime scope: type) ScopedLogger(scope) { | |
~~~~~~~~~~~~^~~~~~~ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment