#[cfg(feature = "plugin")]
use sqlite_loadable::prelude::{c_char, c_uint, sqlite3, sqlite3_api_routines};
mod base32;
pub mod julid;
#[cfg(feature = "serde")]
pub mod serde;
#[cfg(feature = "sqlx")]
pub mod sqlx;
#[doc(inline)]
pub use base32::DecodeError;
#[doc(inline)]
pub use julid::Julid;
#[cfg(feature = "plugin")]
#[no_mangle]
pub unsafe extern "C" fn sqlite3_julid_init(
db: *mut sqlite3,
_pz_err_msg: *mut *mut c_char,
p_api: *mut sqlite3_api_routines,
) -> c_uint {
unsafe { sqlite_loadable::ext::faux_sqlite_extension_init2(p_api) }
match sqlite_plugin::init_rs(db) {
Ok(()) => 256, Err(err) => err.code_extended(),
}
}
#[cfg(feature = "plugin")]
pub mod sqlite_plugin {
use sqlite_loadable::{
api, define_scalar_function,
prelude::{sqlite3, sqlite3_context, sqlite3_value, FunctionFlags},
Result,
};
use super::*;
pub(super) fn init_rs(db: *mut sqlite3) -> Result<()> {
let flags = FunctionFlags::UTF8 | FunctionFlags::DETERMINISTIC;
define_scalar_function(db, "julid_new", 0, julid_new, FunctionFlags::INNOCUOUS)?;
define_scalar_function(db, "julid_seconds", 1, julid_seconds, flags)?;
define_scalar_function(db, "julid_counter", 1, julid_counter, flags)?;
define_scalar_function(db, "julid_sortable", 1, julid_sortable, flags)?;
define_scalar_function(db, "julid_string", 1, julid_string, flags)?;
Ok(())
}
pub fn julid_new(context: *mut sqlite3_context, _vals: &[*mut sqlite3_value]) -> Result<()> {
api::result_blob(context, Julid::new().as_bytes().as_slice());
Ok(())
}
pub fn julid_seconds(context: *mut sqlite3_context, id: &[*mut sqlite3_value]) -> Result<()> {
if let Some(value) = id.get(0) {
let id = api::value_blob(value);
let bytes: [u8; 16] = id.try_into().map_err(|_| {
sqlite_loadable::Error::new_message("Could not convert given value to Julid")
})?;
let id: Julid = bytes.into();
let ts = id.timestamp() as f64 / 1000.0;
api::result_double(context, ts);
} else {
return Err(sqlite_loadable::Error::new_message(
"Could not get timestamp for empty Julid",
));
}
Ok(())
}
pub fn julid_counter(context: *mut sqlite3_context, id: &[*mut sqlite3_value]) -> Result<()> {
if let Some(value) = id.get(0) {
let id = api::value_blob(value);
let bytes: [u8; 16] = id.try_into().map_err(|_| {
sqlite_loadable::Error::new_message("Could not convert given value to Julid")
})?;
let id: Julid = bytes.into();
api::result_int64(context, id.counter() as i64);
} else {
return Err(sqlite_loadable::Error::new_message(
"Could not get counter value for empty Julid",
));
}
Ok(())
}
pub fn julid_sortable(context: *mut sqlite3_context, id: &[*mut sqlite3_value]) -> Result<()> {
if let Some(value) = id.get(0) {
let id = api::value_blob(value);
let bytes: [u8; 16] = id.try_into().map_err(|_| {
sqlite_loadable::Error::new_message("Could not convert given value to Julid")
})?;
let id: Julid = bytes.into();
api::result_int64(context, id.sortable() as i64);
} else {
return Err(sqlite_loadable::Error::new_message(
"Could not get sortable bits for empty Julid",
));
}
Ok(())
}
pub fn julid_string(context: *mut sqlite3_context, id: &[*mut sqlite3_value]) -> Result<()> {
if let Some(value) = id.get(0) {
let id = api::value_blob(value);
let bytes: [u8; 16] = id.try_into().map_err(|_| {
sqlite_loadable::Error::new_message("Could not convert given value to Julid")
})?;
let id: Julid = bytes.into();
api::result_text(context, id.as_string())?;
} else {
return Err(sqlite_loadable::Error::new_message(
"Could not convert empty Julid to string",
));
}
Ok(())
}
}