From 7d4d8fa55b98269666a8fc1f73795a78c10bd073 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Thu, 23 Nov 2023 21:35:16 +0100 Subject: add the fasFn helper --- helpers.zig | 16 ++++++++++++++++ sqlite.zig | 2 +- vtab.zig | 20 ++++++++++---------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/helpers.zig b/helpers.zig index 1a56231..7bb695e 100644 --- a/helpers.zig +++ b/helpers.zig @@ -86,3 +86,19 @@ fn sliceFromValue(sqlite_value: *c.sqlite3_value) []const u8 { return value[0..size]; } + +// Returns true if the type T has a function named `name`. +pub fn hasFn(comptime T: type, comptime name: []const u8) bool { + if (!@hasDecl(T, name)) { + return false; + } + + const decl = @field(T, name); + const decl_type = @TypeOf(decl); + const decl_type_info = @typeInfo(decl_type); + + return switch (decl_type_info) { + .Fn => true, + else => false, + }; +} diff --git a/sqlite.zig b/sqlite.zig index c3ecb84..3759884 100644 --- a/sqlite.zig +++ b/sqlite.zig @@ -1693,7 +1693,7 @@ pub const DynamicStatement = struct { try self.bindField(info.backing_integer.?, options, field_name, i, @as(info.backing_integer.?, @bitCast(field))); return; } - if (!comptime std.meta.trait.hasFn("bindField")(FieldType)) { + if (!comptime helpers.hasFn(FieldType, "bindField")) { @compileError("cannot bind field " ++ field_name ++ " of type " ++ @typeName(FieldType) ++ ", consider implementing the bindField() method"); } diff --git a/vtab.zig b/vtab.zig index 7c2dafe..eb73990 100644 --- a/vtab.zig +++ b/vtab.zig @@ -318,7 +318,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.init function must have the signature `fn init(allocator: std.mem.Allocator, parent: *Table) InitError!*Cursor` ; - if (!meta.trait.hasFn("init")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "init")) { @compileError("the Cursor type must have an init function, " ++ error_message); } @@ -336,7 +336,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.deinit function must have the signature `fn deinit(cursor: *Cursor) void` ; - if (!meta.trait.hasFn("deinit")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "deinit")) { @compileError("the Cursor type must have a deinit function, " ++ error_message); } @@ -357,7 +357,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.next function must have the signature `fn next(cursor: *Cursor, diags: *sqlite.vtab.VTabDiagnostics) NextError!void` ; - if (!meta.trait.hasFn("next")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "next")) { @compileError("the Cursor type must have a next function, " ++ error_message); } @@ -379,7 +379,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.hasNext function must have the signature `fn hasNext(cursor: *Cursor, diags: *sqlite.vtab.VTabDiagnostics) HasNextError!bool` ; - if (!meta.trait.hasFn("hasNext")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "hasNext")) { @compileError("the Cursor type must have a hasNext function, " ++ error_message); } @@ -401,7 +401,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.filter function must have the signature `fn filter(cursor: *Cursor, diags: *sqlite.vtab.VTabDiagnostics, index: sqlite.vtab.IndexIdentifier, args: []FilterArg) FilterError!bool` ; - if (!meta.trait.hasFn("filter")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "filter")) { @compileError("the Cursor type must have a filter function, " ++ error_message); } @@ -428,7 +428,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.column function must have the signature `fn column(cursor: *Cursor, diags: *sqlite.vtab.VTabDiagnostics, column_number: i32) ColumnError!Column` ; - if (!meta.trait.hasFn("column")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "column")) { @compileError("the Cursor type must have a column function, " ++ error_message); } @@ -451,7 +451,7 @@ fn validateCursorType(comptime Table: type) void { \\the Cursor.rowId function must have the signature `fn rowId(cursor: *Cursor, diags: *sqlite.vtab.VTabDiagnostics) RowIDError!i64` ; - if (!meta.trait.hasFn("rowId")(Cursor)) { + if (!comptime helpers.hasFn(Cursor, "rowId")) { @compileError("the Cursor type must have a rowId function, " ++ error_message); } @@ -476,7 +476,7 @@ fn validateTableType(comptime Table: type) void { \\the Table.init function must have the signature `fn init(allocator: std.mem.Allocator, diags: *sqlite.vtab.VTabDiagnostics, args: []const ModuleArgument) InitError!*Table` ; - if (!meta.trait.hasFn("init")(Table)) { + if (!comptime helpers.hasFn(Table, "init")) { @compileError("the Table type must have a init function, " ++ error_message); } @@ -496,7 +496,7 @@ fn validateTableType(comptime Table: type) void { \\the Table.deinit function must have the signature `fn deinit(table: *Table, allocator: std.mem.Allocator) void` ; - if (!meta.trait.hasFn("deinit")(Table)) { + if (!comptime helpers.hasFn(Table, "deinit")) { @compileError("the Table type must have a deinit function, " ++ error_message); } @@ -518,7 +518,7 @@ fn validateTableType(comptime Table: type) void { \\the Table.buildBestIndex function must have the signature `fn buildBestIndex(table: *Table, diags: *sqlite.vtab.VTabDiagnostics, builder: *sqlite.vtab.BestIndexBuilder) BuildBestIndexError!void` ; - if (!meta.trait.hasFn("buildBestIndex")(Table)) { + if (!comptime helpers.hasFn(Table, "buildBestIndex")) { @compileError("the Table type must have a buildBestIndex function, " ++ error_message); } -- cgit v1.2.3