From c72edf38dcdb0865b8086b853bafae07d4072b44 Mon Sep 17 00:00:00 2001 From: Vincent Rischmann Date: Tue, 16 Aug 2022 00:21:40 +0200 Subject: move setFunctionArgument to helpers.setTypeFromValue Will be used in the virtual table implementation --- helpers.zig | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'helpers.zig') diff --git a/helpers.zig b/helpers.zig index 17a5b64..aa04f54 100644 --- a/helpers.zig +++ b/helpers.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const debug = std.debug; const c = @import("c.zig").c; @@ -39,3 +40,49 @@ pub fn setResult(ctx: ?*c.sqlite3_context, result: anytype) void { }, } } + +/// Sets a type using the provided value. +/// +/// Determines at compile time which sqlite3_value_XYZ function to use based on the type `ArgType`. +pub fn setTypeFromValue(comptime ArgType: type, arg: *ArgType, sqlite_value: *c.sqlite3_value) void { + switch (ArgType) { + Text => arg.*.data = sliceFromValue(sqlite_value), + Blob => arg.*.data = sliceFromValue(sqlite_value), + else => switch (@typeInfo(ArgType)) { + .Int => |info| if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 32) { + const value = c.sqlite3_value_int(sqlite_value); + arg.* = @intCast(ArgType, value); + } else if ((info.bits + if (info.signedness == .unsigned) 1 else 0) <= 64) { + const value = c.sqlite3_value_int64(sqlite_value); + arg.* = @intCast(ArgType, value); + } else { + @compileError("integer " ++ @typeName(ArgType) ++ " is not representable in sqlite"); + }, + .Float => { + const value = c.sqlite3_value_double(sqlite_value); + arg.* = @floatCast(ArgType, value); + }, + .Bool => { + const value = c.sqlite3_value_int(sqlite_value); + arg.* = value > 0; + }, + .Pointer => |ptr| switch (ptr.size) { + .Slice => switch (ptr.child) { + u8 => arg.* = sliceFromValue(sqlite_value), + else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)), + }, + else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)), + }, + else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)), + }, + } +} + +fn sliceFromValue(sqlite_value: *c.sqlite3_value) []const u8 { + const size = @intCast(usize, c.sqlite3_value_bytes(sqlite_value)); + + const value = c.sqlite3_value_text(sqlite_value); + debug.assert(value != null); // TODO(vincent): how do we handle this properly ? + + return value.?[0..size]; +} -- cgit v1.2.3