mod decode;
mod reader;
mod retainer;
pub use decode::Decode;
#[doc(hidden)]
pub use reader::Reader;
pub(crate) use retainer::Retainer;
use crate::sys;
use o3::base::num::bounded::NonZeroU32;
use std::{ptr, slice};
#[repr(u8)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub(crate) enum Kind {
Integer = 1,
Real = 2,
Text = 3,
Blob = 4,
Null = 5,
}
impl Kind {
pub(crate) const fn into_public(self) -> super::Kind {
match self {
Self::Integer => super::Kind::Integer,
Self::Real => super::Kind::Real,
Self::Text => super::Kind::Text,
Self::Blob => super::Kind::Blob,
Self::Null => super::Kind::Null,
}
}
}
unsafe extern "C" {
fn sqlite3_column_type(
stmt: *mut libsqlite3_sys::sqlite3_stmt,
column: i32,
) -> NonZeroU32<1, 5>;
}
pub(crate) unsafe fn kind(stmt: ptr::NonNull<libsqlite3_sys::sqlite3_stmt>, column: i32) -> Kind {
let raw = unsafe { sqlite3_column_type(stmt.as_ptr(), column) };
match raw.get() {
1 => Kind::Integer,
2 => Kind::Real,
3 => Kind::Text,
4 => Kind::Blob,
_ => Kind::Null,
}
}
pub(crate) unsafe fn text<'row>(
stmt: ptr::NonNull<libsqlite3_sys::sqlite3_stmt>,
column: i32,
) -> Result<&'row [u8], crate::Error> {
let pointer = unsafe { libsqlite3_sys::sqlite3_column_text(stmt.as_ptr(), column) };
let Some(pointer) = ptr::NonNull::new(pointer.cast_mut()) else {
let code = unsafe { error(stmt) };
return Err(crate::Error::Sqlite {
action: sys::Action::ColumnText,
code,
});
};
let length = unsafe { length(stmt, column) };
Ok(unsafe { slice::from_raw_parts(pointer.as_ptr(), length) })
}
pub(super) unsafe fn blob<'row>(
stmt: ptr::NonNull<libsqlite3_sys::sqlite3_stmt>,
column: i32,
) -> Result<&'row [u8], crate::Error> {
let pointer = unsafe { libsqlite3_sys::sqlite3_column_blob(stmt.as_ptr(), column) }
.cast_mut()
.cast::<u8>();
let Some(pointer) = ptr::NonNull::new(pointer) else {
let code = unsafe { error(stmt) };
if code.primary() == libsqlite3_sys::SQLITE_NOMEM {
return Err(sys::Fault::new(sys::Action::ColumnBlob, code).error());
}
return Ok(&[]);
};
let length = unsafe { length(stmt, column) };
Ok(unsafe { slice::from_raw_parts(pointer.as_ptr(), length) })
}
unsafe fn error(stmt: ptr::NonNull<libsqlite3_sys::sqlite3_stmt>) -> sys::Code {
let database = unsafe { libsqlite3_sys::sqlite3_db_handle(stmt.as_ptr()) };
sys::Code::new(unsafe { libsqlite3_sys::sqlite3_extended_errcode(database) })
}
unsafe fn length(stmt: ptr::NonNull<libsqlite3_sys::sqlite3_stmt>, column: i32) -> usize {
let actual = unsafe { libsqlite3_sys::sqlite3_column_bytes(stmt.as_ptr(), column) };
actual as usize
}