sqlite3_ext/extension.rs
1use super::*;
2use std::{
3 ffi::c_void,
4 mem::transmute,
5 ops::Deref,
6 os::raw::{c_char, c_int},
7};
8
9type CEntry = unsafe extern "C" fn(
10 db: *mut ffi::sqlite3,
11 err_msg: *mut *mut c_char,
12 api: *mut ffi::sqlite3_api_routines,
13) -> c_int;
14
15/// Represents an SQLite-compatible extension entry point.
16///
17/// Because the original Rust function is the [Deref] target for Extension, it can be called
18/// from Rust easily.
19///
20/// # Examples
21///
22/// ```no_run
23/// use sqlite3_ext::*;
24///
25/// #[sqlite3_ext_main(persistent)]
26/// fn init(db: &Connection) -> Result<()> {
27/// // Automatically load this extension on future connections.
28/// per_db_init.register_auto()?;
29/// // Load this extension on this connection.
30/// per_db_init(db)?;
31/// // Add extensions to the VFS system
32/// Ok(())
33/// }
34///
35/// #[sqlite3_ext_init]
36/// fn per_db_init(db: &Connection) -> Result<()> {
37/// // Add extensions to this connection.
38/// Ok(())
39/// }
40/// # fn main() {}
41/// ```
42#[repr(C)]
43pub struct Extension {
44 c_entry: unsafe extern "C" fn(),
45 init: fn(&Connection) -> Result<()>,
46}
47
48impl Extension {
49 /// Construct an Extension from parts.
50 ///
51 /// You generally want to use [sqlite3_ext_init] instead of this function.
52 pub const fn new(c_entry: CEntry, init: fn(&Connection) -> Result<()>) -> Self {
53 unsafe {
54 Extension {
55 c_entry: transmute(c_entry as *mut c_void),
56 init,
57 }
58 }
59 }
60
61 /// Register this extension as an automatic extension.
62 ///
63 /// The provided method will be invoked on all database connections opened in the
64 /// future. For more information, consult the SQLite documentation for
65 /// `sqlite3_auto_extension`.
66 ///
67 /// Requires SQLite 3.8.7.
68 pub fn register_auto(&'static self) -> Result<()> {
69 sqlite3_require_version!(3_008_007, unsafe {
70 Error::from_sqlite(ffi::sqlite3_auto_extension(Some(self.c_entry)))
71 })
72 }
73
74 /// Remove all registered automatic extensions.
75 ///
76 /// For more information, consult the SQLite documentation for
77 /// `sqlite3_reset_auto_extension`.
78 ///
79 /// Requires SQLite 3.8.7. On earlier verions this method is a no-op.
80 pub fn reset_auto() {
81 sqlite3_match_version! {
82 3_008_007 => unsafe { ffi::sqlite3_reset_auto_extension() },
83 _ => (),
84 }
85 }
86
87 /// Remove a previously-registered automatic extension.
88 ///
89 /// For more information, consult the SQLite documentation for
90 /// `sqlite3_cancel_auto_extension`.
91 ///
92 /// Requires SQLite 3.8.7.
93 pub fn cancel_auto(&'static self) -> Result<bool> {
94 sqlite3_require_version!(3_008_007, unsafe {
95 Ok(ffi::sqlite3_cancel_auto_extension(Some(self.c_entry)) != 0)
96 })
97 }
98}
99
100impl Deref for Extension {
101 type Target = fn(&Connection) -> Result<()>;
102
103 fn deref(&self) -> &Self::Target {
104 &self.init
105 }
106}