sqlite_tiny/api/
types.rs

1//! Bridge types to help with C and SQLite data types
2
3use crate::{err, error::Error};
4use core::ffi::c_int;
5
6/// An SQLite convertible type
7#[derive(Debug, Clone, PartialEq)]
8pub enum SqliteType {
9    /// NULL
10    Null,
11    /// INTEGER
12    Integer(i64),
13    /// REAL
14    Real(f64),
15    /// TEXT
16    Text(String),
17    /// BLOB
18    Blob(Vec<u8>),
19}
20macro_rules! impl_sqlitetype_conversion {
21    (from: $variant:path => $type:ty) => {
22        impl TryInto<$type> for SqliteType {
23            type Error = Error;
24
25            fn try_into(self) -> Result<$type, Self::Error> {
26                match self {
27                    $variant(value) => <$type>::try_from(value)
28                        .map_err(|e| err!(with: e, "Failed to from SQLite type")),
29                    _ => Err(err!("Failed to convert from SQLite type"))
30                }
31            }
32        }
33        impl TryInto<Option<$type>> for SqliteType {
34            type Error = Error;
35
36            fn try_into(self) -> Result<Option<$type>, Self::Error> {
37                match self {
38                    Self::Null => Ok(None),
39                    $variant(value) => <$type>::try_from(value)
40                        .map(Some).map_err(|e| err!(with: e, "Failed to from SQLite type")),
41                    _ => Err(err!("Failed to convert from SQLite type"))
42                }
43            }
44        }
45    };
46    (into: $type:ty => $intermediate:ty => $variant:path) => {
47        impl TryFrom<$type> for SqliteType {
48            type Error = Error;
49
50            fn try_from(value: $type) -> Result<Self, Self::Error> {
51                <$intermediate>::try_from(value)
52                    .map($variant).map_err(|e| err!(with: e, "Failed to convert into SQLite type"))
53            }
54        }
55        impl TryFrom<Option<$type>> for SqliteType {
56            type Error = Error;
57
58            fn try_from(value: Option<$type>) -> Result<Self, Self::Error> {
59                match value {
60                    None => Ok(Self::Null),
61                    Some(value) => <$intermediate>::try_from(value)
62                        .map($variant).map_err(|e| err!(with: e, "Failed to convert into SQLite type")),
63                }
64            }
65        }
66    };
67    ($type:ty => $intermediate:ty => $variant:path) => {
68        impl_sqlitetype_conversion!(from: $variant => $type);
69        impl_sqlitetype_conversion!(into: $type => $intermediate => $variant);
70    };
71}
72impl_sqlitetype_conversion!(usize => i64 => SqliteType::Integer);
73impl_sqlitetype_conversion!(isize => i64 => SqliteType::Integer);
74impl_sqlitetype_conversion!(u128 => i64 => SqliteType::Integer);
75impl_sqlitetype_conversion!(i128 => i64 => SqliteType::Integer);
76impl_sqlitetype_conversion!(u64 => i64 => SqliteType::Integer);
77impl_sqlitetype_conversion!(i64 => i64 => SqliteType::Integer);
78impl_sqlitetype_conversion!(u32 => i64 => SqliteType::Integer);
79impl_sqlitetype_conversion!(i32 => i64 => SqliteType::Integer);
80impl_sqlitetype_conversion!(u16 => i64 => SqliteType::Integer);
81impl_sqlitetype_conversion!(i16 => i64 => SqliteType::Integer);
82impl_sqlitetype_conversion!(u8 => i64 => SqliteType::Integer);
83impl_sqlitetype_conversion!(i8 => i64 => SqliteType::Integer);
84impl_sqlitetype_conversion!(f64 => f64 => SqliteType::Real);
85impl_sqlitetype_conversion!(into: f32 => f64 => SqliteType::Real);
86impl_sqlitetype_conversion!(String => String => SqliteType::Text);
87impl_sqlitetype_conversion!(into: &str => String => SqliteType::Text);
88impl_sqlitetype_conversion!(Vec<u8> => Vec<u8> => SqliteType::Blob);
89impl_sqlitetype_conversion!(into: &[u8] => Vec<u8> => SqliteType::Blob);
90
91/// An "owned", mutable pointer
92#[derive(Debug)]
93pub struct PointerMut<T> {
94    /// The underlying raw pointer
95    ptr: *mut T,
96    /// An optional callback that is called on drop
97    on_drop: unsafe extern "C" fn(*mut T) -> c_int,
98}
99impl<T> PointerMut<T> {
100    /// Creates a new owned pointer
101    ///
102    /// # Panics
103    /// This function panics if the given pointer is `NULL`.
104    pub fn new(ptr: *mut T, on_drop: unsafe extern "C" fn(*mut T) -> c_int) -> Self {
105        assert!(!ptr.is_null(), "cannot create an owned NULL pointer");
106        Self { ptr, on_drop }
107    }
108
109    /// Returns the underlying pointer
110    pub const fn as_ptr(&self) -> *mut T {
111        self.ptr
112    }
113}
114impl<T> Drop for PointerMut<T> {
115    fn drop(&mut self) {
116        // Call the on-drop callback
117        unsafe { (self.on_drop)(self.ptr) };
118    }
119}
120
121/// A pointer with flexible ownership
122#[derive(Debug)]
123pub enum PointerMutFlex<'a, T> {
124    /// A borrowed pointer
125    Borrowed(&'a mut PointerMut<T>),
126    /// An owned pointer
127    Owned(PointerMut<T>),
128}
129impl<T> PointerMutFlex<'_, T> {
130    /// Returns the underlying pointer
131    pub const fn as_ptr(&self) -> *mut T {
132        match self {
133            PointerMutFlex::Borrowed(pointer_ref) => pointer_ref.as_ptr(),
134            PointerMutFlex::Owned(pointer_mut) => pointer_mut.as_ptr(),
135        }
136    }
137}