Skip to main content

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}