sqlite_tiny/api/
ffiext.rs

1//! FFI types and helpers
2
3use crate::ffi;
4use std::ffi::c_int;
5
6/// Gets the last error from the database as [`crate::error::Error`]
7///
8/// # Safety
9/// This function operates on a raw SQLite handle. If `database` is not `NULL` but invalid or points to an invalid
10/// handle, the behaviour is undefined.
11#[doc(hidden)]
12pub unsafe fn sqlite3_last_error(retval: i32, database: *mut ffi::sqlite3) -> crate::error::Error {
13    use std::borrow::Cow;
14    use std::ffi::CStr;
15
16    // Get the error string
17    let error = ffi::sqlite3_errstr(retval);
18    let mut message = match error.is_null() {
19        true => Cow::Borrowed("Unknown"),
20        false => CStr::from_ptr(error).to_string_lossy(),
21    };
22
23    // Append database specific error
24    if !database.is_null() {
25        // Get error from database
26        let error = ffi::sqlite3_errmsg(database);
27        let message_ = CStr::from_ptr(error).to_string_lossy();
28        message = Cow::Owned(format!("{message} ({message_})"));
29    }
30    crate::err!("SQLite error: {message}")
31}
32
33/// Helper to translate a result code into a `Result`
34///
35/// # Safety
36/// This function operates on a raw SQLite handle. If `database` is not `NULL` but invalid or points to an invalid
37/// handle, the behaviour is undefined.
38#[doc(hidden)]
39#[inline]
40pub unsafe fn sqlite3_check_result(retval: i32, database: *mut ffi::sqlite3) -> Result<(), crate::error::Error> {
41    match retval {
42        ffi::SQLITE_OK => Ok(()),
43        _ => Err(sqlite3_last_error(retval, database)),
44    }
45}
46
47/// An "owned", mutable pointer
48#[derive(Debug)]
49pub struct PointerMut<T> {
50    /// The underlying raw pointer
51    ptr: *mut T,
52    /// An optional callback that is called on drop
53    on_drop: unsafe extern "C" fn(*mut T) -> c_int,
54}
55impl<T> PointerMut<T> {
56    /// Creates a new owned pointer
57    ///
58    /// # Panics
59    /// This function panics if the given pointer is `NULL`.
60    pub fn new(ptr: *mut T, on_drop: unsafe extern "C" fn(*mut T) -> c_int) -> Self {
61        assert!(!ptr.is_null(), "cannot create an owned NULL pointer");
62        Self { ptr, on_drop }
63    }
64
65    /// Returns the underlying pointer
66    pub const fn as_ptr(&self) -> *mut T {
67        self.ptr
68    }
69}
70impl<T> Drop for PointerMut<T> {
71    fn drop(&mut self) {
72        // Call the on-drop callback
73        unsafe { (self.on_drop)(self.ptr) };
74    }
75}
76
77/// A pointer with flexible ownership
78#[derive(Debug)]
79pub enum PointerMutFlex<'a, T> {
80    /// A borrowed pointer
81    Borrowed(&'a mut PointerMut<T>),
82    /// An owned pointer
83    Owned(PointerMut<T>),
84}
85impl<T> PointerMutFlex<'_, T> {
86    /// Returns the underlying pointer
87    pub const fn as_ptr(&self) -> *mut T {
88        match self {
89            PointerMutFlex::Borrowed(pointer_ref) => pointer_ref.as_ptr(),
90            PointerMutFlex::Owned(pointer_mut) => pointer_mut.as_ptr(),
91        }
92    }
93}