sqlite_objs_sys/lib.rs
1//! Raw FFI bindings to the sqlite-objs C library.
2//!
3//! This crate provides low-level unsafe bindings to the sqlite-objs VFS.
4//! Most users should use the `sqlite-objs` crate instead, which provides
5//! a safe, idiomatic Rust API.
6
7#![allow(non_camel_case_types)]
8
9use libc::{c_char, c_int, c_void};
10
11/// Opaque type for Azure operations vtable (defined in azure_client.h)
12#[repr(C)]
13pub struct azure_ops_t {
14 _private: [u8; 0],
15}
16
17/// Configuration for the sqlite-objs VFS.
18///
19/// This struct maps directly to the C `sqlite_objs_config_t` type.
20#[repr(C)]
21#[derive(Debug)]
22pub struct sqlite_objs_config_t {
23 /// Azure Storage account name
24 pub account: *const c_char,
25 /// Blob container name
26 pub container: *const c_char,
27 /// SAS token (preferred), or NULL
28 pub sas_token: *const c_char,
29 /// Shared Key (fallback), or NULL
30 pub account_key: *const c_char,
31 /// Optional custom endpoint (for Azurite), or NULL for Azure
32 pub endpoint: *const c_char,
33 /// Optional: override the Azure operations vtable
34 pub ops: *const azure_ops_t,
35 /// Opaque context pointer passed to ops functions
36 pub ops_ctx: *mut c_void,
37}
38
39extern "C" {
40 /// Register the "sqlite-objs" VFS.
41 ///
42 /// Reads configuration from environment variables:
43 /// - AZURE_STORAGE_ACCOUNT
44 /// - AZURE_STORAGE_CONTAINER
45 /// - AZURE_STORAGE_SAS (checked first)
46 /// - AZURE_STORAGE_KEY (fallback)
47 ///
48 /// If `makeDefault` is non-zero, this VFS becomes the default.
49 /// Returns SQLITE_OK (0) on success, or an appropriate error code.
50 pub fn sqlite_objs_vfs_register(makeDefault: c_int) -> c_int;
51
52 /// Register the "sqlite-objs" VFS with an explicit configuration.
53 ///
54 /// The config struct is copied — the caller may free it after this call.
55 /// If `makeDefault` is non-zero, this VFS becomes the default.
56 /// Returns SQLITE_OK (0) on success, or an appropriate error code.
57 pub fn sqlite_objs_vfs_register_with_config(
58 config: *const sqlite_objs_config_t,
59 makeDefault: c_int,
60 ) -> c_int;
61
62 /// Register the "sqlite-objs" VFS with an explicit ops vtable and context.
63 ///
64 /// Convenience wrapper for test code.
65 pub fn sqlite_objs_vfs_register_with_ops(
66 ops: *mut azure_ops_t,
67 ctx: *mut c_void,
68 makeDefault: c_int,
69 ) -> c_int;
70
71 /// Register the "sqlite-objs" VFS with no global Azure client.
72 ///
73 /// All databases MUST provide Azure credentials via URI parameters:
74 /// `file:mydb.db?azure_account=acct&azure_container=cont&azure_sas=token`
75 ///
76 /// Supported URI parameters:
77 /// - azure_account (required)
78 /// - azure_container
79 /// - azure_sas
80 /// - azure_key
81 /// - azure_endpoint
82 ///
83 /// If `makeDefault` is non-zero, this VFS becomes the default.
84 /// Returns SQLITE_OK (0) on success, or an appropriate error code.
85 pub fn sqlite_objs_vfs_register_uri(makeDefault: c_int) -> c_int;
86}
87
88// SQLite constants
89pub const SQLITE_OK: c_int = 0;
90pub const SQLITE_ERROR: c_int = 1;
91pub const SQLITE_CANTOPEN: c_int = 14;
92pub const SQLITE_NOMEM: c_int = 7;
93
94// sqlite-objs custom file-control opcodes.
95// These must match the #define values in sqlite_objs.h.
96
97/// FCNTL opcode: query the number of full blob downloads (int* arg).
98/// ETag cache hits do not increment the counter.
99pub const SQLITE_OBJS_FCNTL_DOWNLOAD_COUNT: c_int = 200;
100
101/// FCNTL opcode: retrieve all VFS activity metrics as a `key=value\n` string.
102/// The returned `char*` is allocated with `sqlite3_malloc`; the caller must
103/// free it with `sqlite3_free`.
104pub const SQLITE_OBJS_FCNTL_STATS: c_int = 201;
105
106/// FCNTL opcode: reset all VFS activity metrics to zero. Pass NULL as arg.
107pub const SQLITE_OBJS_FCNTL_STATS_RESET: c_int = 202;
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_config_size() {
115 // Ensure the struct layout matches C expectations
116 assert!(std::mem::size_of::<sqlite_objs_config_t>() > 0);
117 }
118
119 #[test]
120 fn test_register_uri() {
121 // Test that we can call the FFI function (registration will fail
122 // without Azure config, but linkage should work)
123 unsafe {
124 let result = sqlite_objs_vfs_register_uri(0);
125 // Should return SQLITE_OK since URI mode doesn't require config upfront
126 assert_eq!(result, SQLITE_OK);
127 }
128 }
129
130 #[test]
131 fn test_fcntl_constants_match_header() {
132 // Values must stay in sync with sqlite_objs.h #defines
133 assert_eq!(SQLITE_OBJS_FCNTL_DOWNLOAD_COUNT, 200);
134 assert_eq!(SQLITE_OBJS_FCNTL_STATS, 201);
135 assert_eq!(SQLITE_OBJS_FCNTL_STATS_RESET, 202);
136 }
137}