From 0d6c7b2b9e30257da837ba1d604ab43a85c9b247 Mon Sep 17 00:00:00 2001 From: CGodiksen <36046286+CGodiksen@users.noreply.github.com> Date: Mon, 6 Jul 2026 08:03:53 +0200 Subject: [PATCH 1/3] Use uint64_t in C header --- crates/modelardb_embedded/bindings/c/modelardb_embedded.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/modelardb_embedded/bindings/c/modelardb_embedded.h b/crates/modelardb_embedded/bindings/c/modelardb_embedded.h index 9bbb5b7d..0fe32dcd 100644 --- a/crates/modelardb_embedded/bindings/c/modelardb_embedded.h +++ b/crates/modelardb_embedded/bindings/c/modelardb_embedded.h @@ -197,13 +197,13 @@ int modelardb_embedded_drop(void* maybe_operations_ptr, int modelardb_embedded_vacuum(void* maybe_operations_ptr, bool is_data_folder, const char* table_name_ptr, - const char* retention_period_in_seconds_ptr); + const uint64_t* retention_period_in_seconds_ptr); // Optimize the table by compacting its many small files into fewer larger files. int modelardb_embedded_optimize(void* maybe_operations_ptr, bool is_data_folder, const char* table_name_ptr, - const char* target_size_in_bytes_ptr); + const uint64_t* target_size_in_bytes_ptr); // Return a human-readable representation of the last error on this thread. const char* modelardb_embedded_error(); From 91025ef7b5ce630b3e04d937c4c5ae4faa9f3c4e Mon Sep 17 00:00:00 2001 From: CGodiksen <36046286+CGodiksen@users.noreply.github.com> Date: Mon, 6 Jul 2026 08:12:11 +0200 Subject: [PATCH 2/3] Use uint64_t in FFI in Python interface --- .../bindings/python/modelardb/operations.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/modelardb_embedded/bindings/python/modelardb/operations.py b/crates/modelardb_embedded/bindings/python/modelardb/operations.py index d66883ee..c975767a 100644 --- a/crates/modelardb_embedded/bindings/python/modelardb/operations.py +++ b/crates/modelardb_embedded/bindings/python/modelardb/operations.py @@ -668,12 +668,7 @@ def vacuum(self, table_name: str, retention_period_in_seconds: None | int = None table_name_ptr = ffi.new("char[]", bytes(table_name, "UTF-8")) if retention_period_in_seconds is not None: - # Convert the retention period to a string to avoid issues with converting an int to a C type that uses - # an inconsistent amount of bits across platforms and then converting that to a 64-bit integer in Rust. - # The string is converted directly to an unsigned 64-bit integer in Rust. - retention_period_in_seconds_ptr = ffi.new( - "char[]", bytes(str(retention_period_in_seconds), "UTF-8") - ) + retention_period_in_seconds_ptr = ffi.new("uint64_t*", retention_period_in_seconds) else: retention_period_in_seconds_ptr = ffi.NULL @@ -699,12 +694,7 @@ def optimize(self, table_name: str, target_size_in_bytes: None | int = None): table_name_ptr = ffi.new("char[]", bytes(table_name, "UTF-8")) if target_size_in_bytes is not None: - # Convert the target size to a string to avoid issues with converting an int to a C type that uses - # an inconsistent amount of bits across platforms and then converting that to a 64-bit integer in Rust. - # The string is converted directly to an unsigned 64-bit integer in Rust. - target_size_in_bytes_ptr = ffi.new( - "char[]", bytes(str(target_size_in_bytes), "UTF-8") - ) + target_size_in_bytes_ptr = ffi.new("uint64_t*", target_size_in_bytes) else: target_size_in_bytes_ptr = ffi.NULL From 47f06267769477f04855d175c95b98317d54f54f Mon Sep 17 00:00:00 2001 From: CGodiksen <36046286+CGodiksen@users.noreply.github.com> Date: Mon, 6 Jul 2026 08:21:18 +0200 Subject: [PATCH 3/3] Use u64 in C-API and removed type coercion --- crates/modelardb_embedded/src/capi.rs | 53 +++++++-------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/crates/modelardb_embedded/src/capi.rs b/crates/modelardb_embedded/src/capi.rs index eec6d78e..66f2550e 100644 --- a/crates/modelardb_embedded/src/capi.rs +++ b/crates/modelardb_embedded/src/capi.rs @@ -967,18 +967,17 @@ unsafe fn drop( } /// Vacuums the table with the name in `table_name_ptr` in the [`DataFolder`] or [`Client`] in -/// `maybe_operations_ptr` by deleting stale files that are older than `retention_period_in_seconds_ptr` -/// seconds. Assumes `maybe_operations_ptr` points to a [`DataFolder`] or [`Client`]; -/// `table_name_ptr` points to a valid C string; and `retention_period_in_seconds_ptr` points to a -/// valid C string, or is null to use the default retention period. A C string is used for the -/// retention period to avoid issues with different platforms using an inconsistent amount of bits -/// for integer types. The string is converted directly to an unsigned 64-bit integer in Rust. +/// `maybe_operations_ptr` by deleting stale files that are older than +/// `retention_period_in_seconds_ptr` seconds. Assumes `maybe_operations_ptr` points to a +/// [`DataFolder`] or [`Client`]; `table_name_ptr` points to a valid C string; and +/// `retention_period_in_seconds_ptr` points to a valid `u64`, or is null to use the default +/// retention period. #[unsafe(no_mangle)] pub unsafe extern "C" fn modelardb_embedded_vacuum( maybe_operations_ptr: *mut c_void, is_data_folder: bool, table_name_ptr: *const c_char, - retention_period_in_seconds_ptr: *const c_char, + retention_period_in_seconds_ptr: *const u64, ) -> c_int { let maybe_unit = unsafe { vacuum( @@ -996,24 +995,12 @@ unsafe fn vacuum( maybe_operations_ptr: *mut c_void, is_data_folder: bool, table_name_ptr: *const c_char, - retention_period_in_seconds_ptr: *const c_char, + retention_period_in_seconds_ptr: *const u64, ) -> Result<()> { let modelardb = unsafe { c_void_to_operations(maybe_operations_ptr, is_data_folder)? }; let table_name = unsafe { c_char_ptr_to_str(table_name_ptr)? }; - let maybe_retention_period_in_seconds_str = - unsafe { c_char_ptr_to_maybe_str(retention_period_in_seconds_ptr)? }; - - let maybe_retention_period_in_seconds = maybe_retention_period_in_seconds_str - .map(|retention_period_in_seconds_str| { - retention_period_in_seconds_str - .parse::() - .map_err(|error| { - ModelarDbEmbeddedError::InvalidArgument(format!( - "Retention period is not a valid u64: {error}" - )) - }) - }) - .transpose()?; + let maybe_retention_period_in_seconds = + unsafe { retention_period_in_seconds_ptr.as_ref().copied() }; TOKIO_RUNTIME.block_on(modelardb.vacuum(table_name, maybe_retention_period_in_seconds)) } @@ -1022,16 +1009,13 @@ unsafe fn vacuum( /// `maybe_operations_ptr` by compacting its many small files into fewer larger files of /// approximately `target_size_in_bytes_ptr` bytes. Assumes `maybe_operations_ptr` points to a /// [`DataFolder`] or [`Client`]; `table_name_ptr` points to a valid C string; and -/// `target_size_in_bytes_ptr` points to a valid C string, or is null to use the default target -/// size. A C string is used for the target size to avoid issues with different platforms using an -/// inconsistent amount of bits for integer types. The string is converted directly to an unsigned -/// 64-bit integer in Rust. +/// `target_size_in_bytes_ptr` points to a valid `u64`, or is null to use the default target size. #[unsafe(no_mangle)] pub unsafe extern "C" fn modelardb_embedded_optimize( maybe_operations_ptr: *mut c_void, is_data_folder: bool, table_name_ptr: *const c_char, - target_size_in_bytes_ptr: *const c_char, + target_size_in_bytes_ptr: *const u64, ) -> c_int { let maybe_unit = unsafe { optimize( @@ -1049,22 +1033,11 @@ unsafe fn optimize( maybe_operations_ptr: *mut c_void, is_data_folder: bool, table_name_ptr: *const c_char, - target_size_in_bytes_ptr: *const c_char, + target_size_in_bytes_ptr: *const u64, ) -> Result<()> { let modelardb = unsafe { c_void_to_operations(maybe_operations_ptr, is_data_folder)? }; let table_name = unsafe { c_char_ptr_to_str(table_name_ptr)? }; - let maybe_target_size_in_bytes_str = - unsafe { c_char_ptr_to_maybe_str(target_size_in_bytes_ptr)? }; - - let maybe_target_size_in_bytes = maybe_target_size_in_bytes_str - .map(|target_size_in_bytes_str| { - target_size_in_bytes_str.parse::().map_err(|error| { - ModelarDbEmbeddedError::InvalidArgument(format!( - "Target size is not a valid u64: {error}" - )) - }) - }) - .transpose()?; + let maybe_target_size_in_bytes = unsafe { target_size_in_bytes_ptr.as_ref().copied() }; TOKIO_RUNTIME.block_on(modelardb.optimize(table_name, maybe_target_size_in_bytes)) }