| //! Automatic extension loading |
| use super::ffi; |
| use crate::error::{check, to_sqlite_error}; |
| use crate::{Connection, Error, Result}; |
| use std::os::raw::{c_char, c_int}; |
| use std::panic::catch_unwind; |
| |
| /// Automatic extension initialization routine |
| pub type AutoExtension = fn(Connection) -> Result<()>; |
| |
| /// Raw automatic extension initialization routine |
| pub type RawAutoExtension = unsafe extern "C" fn( |
| db: *mut ffi::sqlite3, |
| pz_err_msg: *mut *mut c_char, |
| _: *const ffi::sqlite3_api_routines, |
| ) -> c_int; |
| |
| /// Bridge between `RawAutoExtension` and `AutoExtension` |
| /// |
| /// # Safety |
| /// * Opening a database from an auto-extension handler will lead to |
| /// an endless recursion of the auto-handler triggering itself |
| /// indirectly for each newly-opened database. |
| /// * Results are undefined if the given db is closed by an auto-extension. |
| /// * The list of auto-extensions should not be manipulated from an auto-extension. |
| pub unsafe fn init_auto_extension( |
| db: *mut ffi::sqlite3, |
| pz_err_msg: *mut *mut c_char, |
| ax: AutoExtension, |
| ) -> c_int { |
| let r = catch_unwind(|| { |
| let c = Connection::from_handle(db); |
| c.and_then(ax) |
| }) |
| .unwrap_or_else(|_| Err(Error::UnwindingPanic)); |
| match r { |
| Err(e) => to_sqlite_error(&e, pz_err_msg), |
| _ => ffi::SQLITE_OK, |
| } |
| } |
| |
| /// Register au auto-extension |
| /// |
| /// # Safety |
| /// * Opening a database from an auto-extension handler will lead to |
| /// an endless recursion of the auto-handler triggering itself |
| /// indirectly for each newly-opened database. |
| /// * Results are undefined if the given db is closed by an auto-extension. |
| /// * The list of auto-extensions should not be manipulated from an auto-extension. |
| pub unsafe fn register_auto_extension(ax: RawAutoExtension) -> Result<()> { |
| check(ffi::sqlite3_auto_extension(Some(ax))) |
| } |
| |
| /// Unregister the initialization routine |
| pub fn cancel_auto_extension(ax: RawAutoExtension) -> bool { |
| unsafe { ffi::sqlite3_cancel_auto_extension(Some(ax)) == 1 } |
| } |
| |
| /// Disable all automatic extensions previously registered |
| pub fn reset_auto_extension() { |
| unsafe { ffi::sqlite3_reset_auto_extension() } |
| } |