diff options
| -rw-r--r-- | helpers.zig | 4 | ||||
| -rw-r--r-- | sqlite.zig | 26 |
2 files changed, 13 insertions, 17 deletions
diff --git a/helpers.zig b/helpers.zig index dd7fd4f..344ff02 100644 --- a/helpers.zig +++ b/helpers.zig | |||
| @@ -30,7 +30,7 @@ pub fn setResult(ctx: ?*c.sqlite3_context, result: anytype) void { | |||
| 30 | else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), | 30 | else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), |
| 31 | }, | 31 | }, |
| 32 | .pointer => |ptr| switch (ptr.size) { | 32 | .pointer => |ptr| switch (ptr.size) { |
| 33 | .Slice => switch (ptr.child) { | 33 | .slice => switch (ptr.child) { |
| 34 | u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(result.len), c.sqliteTransientAsDestructor()), | 34 | u8 => c.sqlite3_result_text(ctx, result.ptr, @intCast(result.len), c.sqliteTransientAsDestructor()), |
| 35 | else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), | 35 | else => @compileError("cannot use a result of type " ++ @typeName(ResultType)), |
| 36 | }, | 36 | }, |
| @@ -67,7 +67,7 @@ pub fn setTypeFromValue(comptime ArgType: type, arg: *ArgType, sqlite_value: *c. | |||
| 67 | arg.* = value > 0; | 67 | arg.* = value > 0; |
| 68 | }, | 68 | }, |
| 69 | .pointer => |ptr| switch (ptr.size) { | 69 | .pointer => |ptr| switch (ptr.size) { |
| 70 | .Slice => switch (ptr.child) { | 70 | .slice => switch (ptr.child) { |
| 71 | u8 => arg.* = sliceFromValue(sqlite_value), | 71 | u8 => arg.* = sliceFromValue(sqlite_value), |
| 72 | else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)), | 72 | else => @compileError("cannot use an argument of type " ++ @typeName(ArgType)), |
| 73 | }, | 73 | }, |
| @@ -50,12 +50,12 @@ fn isZigString(comptime T: type) bool { | |||
| 50 | if (ptr.is_volatile or ptr.is_allowzero) break :blk false; | 50 | if (ptr.is_volatile or ptr.is_allowzero) break :blk false; |
| 51 | 51 | ||
| 52 | // If it's already a slice, simple check. | 52 | // If it's already a slice, simple check. |
| 53 | if (ptr.size == .Slice) { | 53 | if (ptr.size == .slice) { |
| 54 | break :blk ptr.child == u8; | 54 | break :blk ptr.child == u8; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | // Otherwise check if it's an array type that coerces to slice. | 57 | // Otherwise check if it's an array type that coerces to slice. |
| 58 | if (ptr.size == .One) { | 58 | if (ptr.size == .one) { |
| 59 | const child = @typeInfo(ptr.child); | 59 | const child = @typeInfo(ptr.child); |
| 60 | if (child == .array) { | 60 | if (child == .array) { |
| 61 | const arr = &child.array; | 61 | const arr = &child.array; |
| @@ -880,7 +880,7 @@ pub const FunctionContext = struct { | |||
| 880 | fn splitPtrTypes(comptime Type: type) SplitPtrTypes { | 880 | fn splitPtrTypes(comptime Type: type) SplitPtrTypes { |
| 881 | switch (@typeInfo(Type)) { | 881 | switch (@typeInfo(Type)) { |
| 882 | .pointer => |ptr_info| switch (ptr_info.size) { | 882 | .pointer => |ptr_info| switch (ptr_info.size) { |
| 883 | .One => return SplitPtrTypes{ | 883 | .one => return SplitPtrTypes{ |
| 884 | .ValueType = ptr_info.child, | 884 | .ValueType = ptr_info.child, |
| 885 | .PointerType = Type, | 885 | .PointerType = Type, |
| 886 | }, | 886 | }, |
| @@ -1211,14 +1211,13 @@ pub fn Iterator(comptime Type: type) type { | |||
| 1211 | u8 => { | 1211 | u8 => { |
| 1212 | const size: usize = @intCast(c.sqlite3_column_bytes(self.stmt, i)); | 1212 | const size: usize = @intCast(c.sqlite3_column_bytes(self.stmt, i)); |
| 1213 | 1213 | ||
| 1214 | if (arr.sentinel) |sentinel_ptr| { | 1214 | if (arr.sentinel()) |sentinel| { |
| 1215 | // An array with a sentinel need to be as big as the data, + 1 byte for the sentinel. | 1215 | // An array with a sentinel need to be as big as the data, + 1 byte for the sentinel. |
| 1216 | if (size >= @as(usize, arr.len)) { | 1216 | if (size >= @as(usize, arr.len)) { |
| 1217 | return error.ArrayTooSmall; | 1217 | return error.ArrayTooSmall; |
| 1218 | } | 1218 | } |
| 1219 | 1219 | ||
| 1220 | // Set the sentinel in the result at the correct position. | 1220 | // Set the sentinel in the result at the correct position. |
| 1221 | const sentinel = @as(*const arr.child, @ptrCast(sentinel_ptr)).*; | ||
| 1222 | ret[size] = sentinel; | 1221 | ret[size] = sentinel; |
| 1223 | } else if (size != arr.len) { | 1222 | } else if (size != arr.len) { |
| 1224 | // An array without a sentinel must have the exact same size as the data because we can't | 1223 | // An array without a sentinel must have the exact same size as the data because we can't |
| @@ -1268,9 +1267,7 @@ pub fn Iterator(comptime Type: type) type { | |||
| 1268 | fn dupeWithSentinel(comptime SliceType: type, allocator: mem.Allocator, data: []const u8) !SliceType { | 1267 | fn dupeWithSentinel(comptime SliceType: type, allocator: mem.Allocator, data: []const u8) !SliceType { |
| 1269 | switch (@typeInfo(SliceType)) { | 1268 | switch (@typeInfo(SliceType)) { |
| 1270 | .pointer => |ptr_info| { | 1269 | .pointer => |ptr_info| { |
| 1271 | if (ptr_info.sentinel) |sentinel_ptr| { | 1270 | if (ptr_info.sentinel()) |sentinel| { |
| 1272 | const sentinel = @as(*const ptr_info.child, @ptrCast(sentinel_ptr)).*; | ||
| 1273 | |||
| 1274 | const slice = try allocator.alloc(u8, data.len + 1); | 1271 | const slice = try allocator.alloc(u8, data.len + 1); |
| 1275 | mem.copyForwards(u8, slice, data); | 1272 | mem.copyForwards(u8, slice, data); |
| 1276 | slice[data.len] = sentinel; | 1273 | slice[data.len] = sentinel; |
| @@ -1347,13 +1344,13 @@ pub fn Iterator(comptime Type: type) type { | |||
| 1347 | switch (@typeInfo(PointerType)) { | 1344 | switch (@typeInfo(PointerType)) { |
| 1348 | .pointer => |ptr| { | 1345 | .pointer => |ptr| { |
| 1349 | switch (ptr.size) { | 1346 | switch (ptr.size) { |
| 1350 | .One => { | 1347 | .one => { |
| 1351 | ret = try options.allocator.create(ptr.child); | 1348 | ret = try options.allocator.create(ptr.child); |
| 1352 | errdefer options.allocator.destroy(ret); | 1349 | errdefer options.allocator.destroy(ret); |
| 1353 | 1350 | ||
| 1354 | ret.* = try self.readField(ptr.child, options, i); | 1351 | ret.* = try self.readField(ptr.child, options, i); |
| 1355 | }, | 1352 | }, |
| 1356 | .Slice => switch (ptr.child) { | 1353 | .slice => switch (ptr.child) { |
| 1357 | u8 => ret = try self.readBytes(PointerType, options.allocator, i, .Text), | 1354 | u8 => ret = try self.readBytes(PointerType, options.allocator, i, .Text), |
| 1358 | else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)), | 1355 | else => @compileError("cannot read pointer of type " ++ @typeName(PointerType)), |
| 1359 | }, | 1356 | }, |
| @@ -1647,10 +1644,10 @@ pub const DynamicStatement = struct { | |||
| 1647 | return convertResultToError(result); | 1644 | return convertResultToError(result); |
| 1648 | }, | 1645 | }, |
| 1649 | .pointer => |ptr| switch (ptr.size) { | 1646 | .pointer => |ptr| switch (ptr.size) { |
| 1650 | .One => { | 1647 | .one => { |
| 1651 | try self.bindField(ptr.child, options, field_name, i, field.*); | 1648 | try self.bindField(ptr.child, options, field_name, i, field.*); |
| 1652 | }, | 1649 | }, |
| 1653 | .Slice => switch (ptr.child) { | 1650 | .slice => switch (ptr.child) { |
| 1654 | u8 => { | 1651 | u8 => { |
| 1655 | // NOTE(vincent): The slice must live until after the prepared statement is finaliuzed, therefore we use SQLITE_STATIC to avoid a copy | 1652 | // NOTE(vincent): The slice must live until after the prepared statement is finaliuzed, therefore we use SQLITE_STATIC to avoid a copy |
| 1656 | const result = c.sqlite3_bind_text(self.stmt, column, field.ptr, @intCast(field.len), c.SQLITE_STATIC); | 1653 | const result = c.sqlite3_bind_text(self.stmt, column, field.ptr, @intCast(field.len), c.SQLITE_STATIC); |
| @@ -1779,7 +1776,7 @@ pub const DynamicStatement = struct { | |||
| 1779 | }, | 1776 | }, |
| 1780 | .pointer => |PointerTypeInfo| { | 1777 | .pointer => |PointerTypeInfo| { |
| 1781 | switch (PointerTypeInfo.size) { | 1778 | switch (PointerTypeInfo.size) { |
| 1782 | .Slice => { | 1779 | .slice => { |
| 1783 | for (values, 0..) |value_to_bind, index| { | 1780 | for (values, 0..) |value_to_bind, index| { |
| 1784 | try self.bindField(PointerTypeInfo.child, options, "unknown", @intCast(index), value_to_bind); | 1781 | try self.bindField(PointerTypeInfo.child, options, "unknown", @intCast(index), value_to_bind); |
| 1785 | } | 1782 | } |
| @@ -2679,8 +2676,7 @@ test "sqlite: read a single text value" { | |||
| 2679 | .pointer => { | 2676 | .pointer => { |
| 2680 | try testing.expectEqualStrings("Vincent", name.?); | 2677 | try testing.expectEqualStrings("Vincent", name.?); |
| 2681 | }, | 2678 | }, |
| 2682 | .array => |arr| if (arr.sentinel) |sentinel_ptr| { | 2679 | .array => |arr| if (arr.sentinel()) |sentinel| { |
| 2683 | const sentinel = @as(*const arr.child, @ptrCast(sentinel_ptr)).*; | ||
| 2684 | const res = mem.sliceTo(&name.?, sentinel); | 2680 | const res = mem.sliceTo(&name.?, sentinel); |
| 2685 | try testing.expectEqualStrings("Vincent", res); | 2681 | try testing.expectEqualStrings("Vincent", res); |
| 2686 | } else { | 2682 | } else { |