use core::{borrow::Borrow, fmt, marker::PhantomData, mem, ptr};
use sqlite::{sqlite3_value, sqlite3_value_dup, sqlite3_value_free};
use super::fetch::Fetch;
#[cfg_attr(docsrs, doc(cfg(any(feature = "functions", feature = "value"))))]
#[repr(transparent)]
pub struct Value {
handle: ptr::NonNull<sqlite3_value>,
}
#[cfg(any(feature = "multi-thread", feature = "serialized"))]
#[cfg_attr(
docsrs,
doc(cfg(any(feature = "multi-thread", feature = "serialized")))
)]
unsafe impl Send for Value {}
#[cfg(feature = "serialized")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialized")))]
unsafe impl Sync for Value {}
impl Value {
#[inline]
#[must_use]
pub(crate) const fn new(handle: *mut sqlite3_value) -> Option<Self> {
match ptr::NonNull::new(handle) {
Some(handle) => Some(Self { handle }),
None => None,
}
}
pub(crate) fn duplicate(handle: *const sqlite3_value) -> Option<Self> {
let handle = unsafe { sqlite3_value_dup(handle) };
Self::new(handle)
}
pub fn fetch<'r, T: Fetch<'r>>(&'r self) -> T {
unsafe { T::fetch_value(self.reference()) }
}
#[inline]
pub fn free(mut self) {
unsafe { self.destroy() }
}
#[inline]
#[must_use]
const fn reference<'c>(&self) -> &ValueRef<'c> {
unsafe { mem::transmute(self) }
}
#[inline]
pub(crate) unsafe fn destroy(&mut self) {
unsafe { sqlite3_value_free(self.as_ptr()) }
}
#[inline]
pub const fn as_ptr(&self) -> *mut sqlite3_value {
self.handle.as_ptr()
}
}
impl<'a> AsRef<ValueRef<'a>> for Value {
fn as_ref(&self) -> &ValueRef<'a> {
unsafe { mem::transmute(self) }
}
}
impl<'a> Borrow<ValueRef<'a>> for Value {
fn borrow(&self) -> &ValueRef<'a> {
unsafe { mem::transmute(self) }
}
}
impl<'a> AsRef<OpaqueValueRef<'a>> for Value {
fn as_ref(&self) -> &OpaqueValueRef<'a> {
unsafe { mem::transmute(self) }
}
}
impl<'a> Borrow<OpaqueValueRef<'a>> for Value {
fn borrow(&self) -> &OpaqueValueRef<'a> {
unsafe { mem::transmute(self) }
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Value({:p})", self.handle)
}
}
#[cfg_attr(docsrs, doc(cfg(any(feature = "functions", feature = "value"))))]
#[repr(transparent)]
pub struct ValueRef<'a> {
handle: ptr::NonNull<sqlite3_value>,
_value: PhantomData<fn() -> &'a sqlite3_value>,
}
#[cfg(any(feature = "multi-thread", feature = "serialized"))]
#[cfg_attr(
docsrs,
doc(cfg(any(feature = "multi-thread", feature = "serialized")))
)]
unsafe impl<'c> Send for ValueRef<'c> {}
#[cfg(feature = "serialized")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialized")))]
unsafe impl<'c> Sync for ValueRef<'c> {}
impl<'a> ValueRef<'a> {
#[inline]
#[must_use]
pub const fn new(handle: *mut sqlite3_value) -> Option<Self> {
match ptr::NonNull::new(handle) {
Some(handle) => Some(Self {
handle,
_value: PhantomData,
}),
None => None,
}
}
pub unsafe fn fetch<'r, T: Fetch<'r>>(&'r self) -> T {
unsafe { T::fetch_value(self) }
}
pub(super) fn as_opaque(&self) -> OpaqueValueRef<'a> {
OpaqueValueRef {
handle: self.handle,
_value: PhantomData,
}
}
#[inline]
pub const fn as_ptr(&self) -> *mut sqlite3_value {
self.handle.as_ptr()
}
}
impl<'a> ToOwned for ValueRef<'a> {
type Owned = Value;
fn to_owned(&self) -> Self::Owned {
Value::duplicate(self.as_ptr()).expect("duplicated sqlite3_value")
}
}
impl fmt::Debug for ValueRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ValueRef({:p})", self.handle)
}
}
#[cfg_attr(docsrs, doc(cfg(any(feature = "functions", feature = "value"))))]
#[repr(transparent)]
pub struct OpaqueValueRef<'a> {
handle: ptr::NonNull<sqlite3_value>,
_value: PhantomData<fn() -> &'a sqlite3_value>,
}
impl<'a> OpaqueValueRef<'a> {
#[inline]
#[must_use]
pub(crate) const fn new(handle: *mut sqlite3_value) -> Option<Self> {
match ptr::NonNull::new(handle) {
Some(handle) => Some(Self {
handle,
_value: PhantomData,
}),
None => None,
}
}
#[inline]
pub const fn as_ptr(&self) -> *mut sqlite3_value {
self.handle.as_ptr()
}
}
impl<'a> ToOwned for OpaqueValueRef<'a> {
type Owned = Value;
fn to_owned(&self) -> Self::Owned {
Value::duplicate(self.as_ptr()).expect("duplicated sqlite3_value")
}
}
impl fmt::Debug for OpaqueValueRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "OpaqueValueRef({:p})", self.handle)
}
}