use std::ffi::CString;
use std::os::raw::c_void;
#[cfg(feature = "duckdb-1-5")]
use libduckdb_sys::{
duckdb_bind_info, duckdb_client_context, duckdb_delete_callback_t, duckdb_expression,
duckdb_init_info, duckdb_scalar_function_bind_get_argument,
duckdb_scalar_function_bind_get_argument_count, duckdb_scalar_function_bind_get_extra_info,
duckdb_scalar_function_bind_set_error, duckdb_scalar_function_get_bind_data,
duckdb_scalar_function_get_client_context, duckdb_scalar_function_get_state,
duckdb_scalar_function_init_get_bind_data, duckdb_scalar_function_init_get_client_context,
duckdb_scalar_function_init_get_extra_info, duckdb_scalar_function_init_set_error,
duckdb_scalar_function_init_set_state, duckdb_scalar_function_set_bind_data,
};
use libduckdb_sys::{
duckdb_function_info, duckdb_scalar_function_get_extra_info, duckdb_scalar_function_set_error,
};
#[mutants::skip] fn str_to_cstring(s: &str) -> CString {
CString::new(s).unwrap_or_else(|_| {
let pos = s.bytes().position(|b| b == 0).unwrap_or(s.len());
CString::new(&s.as_bytes()[..pos]).unwrap_or_default()
})
}
pub struct ScalarFunctionInfo {
info: duckdb_function_info,
}
impl ScalarFunctionInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_function_info) -> Self {
Self { info }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_get_extra_info(self.info) }
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_scalar_function_set_error(self.info, c_msg.as_ptr());
}
}
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_function_info {
self.info
}
#[cfg(feature = "duckdb-1-5")]
#[must_use]
pub unsafe fn get_bind_data(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_get_bind_data(self.info) }
}
#[cfg(feature = "duckdb-1-5")]
#[must_use]
pub unsafe fn get_state(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_get_state(self.info) }
}
}
#[cfg(feature = "duckdb-1-5")]
pub struct ScalarBindInfo {
info: duckdb_bind_info,
}
#[cfg(feature = "duckdb-1-5")]
impl ScalarBindInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_bind_info) -> Self {
Self { info }
}
#[mutants::skip]
#[must_use]
pub fn argument_count(&self) -> u64 {
unsafe { duckdb_scalar_function_bind_get_argument_count(self.info) }
}
#[must_use]
pub unsafe fn get_argument(&self, index: u64) -> duckdb_expression {
unsafe { duckdb_scalar_function_bind_get_argument(self.info, index) }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_bind_get_extra_info(self.info) }
}
pub unsafe fn set_bind_data(&self, data: *mut c_void, destroy: duckdb_delete_callback_t) {
unsafe {
duckdb_scalar_function_set_bind_data(self.info, data, destroy);
}
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_scalar_function_bind_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let mut ctx: duckdb_client_context = core::ptr::null_mut();
unsafe { duckdb_scalar_function_get_client_context(self.info, &raw mut ctx) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_bind_info {
self.info
}
}
#[cfg(feature = "duckdb-1-5")]
pub struct ScalarInitInfo {
info: duckdb_init_info,
}
#[cfg(feature = "duckdb-1-5")]
impl ScalarInitInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_init_info) -> Self {
Self { info }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_init_get_extra_info(self.info) }
}
#[must_use]
pub unsafe fn get_bind_data(&self) -> *mut c_void {
unsafe { duckdb_scalar_function_init_get_bind_data(self.info) }
}
pub unsafe fn set_state(&self, state: *mut c_void, destroy: duckdb_delete_callback_t) {
unsafe {
duckdb_scalar_function_init_set_state(self.info, state, destroy);
}
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_scalar_function_init_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let mut ctx: duckdb_client_context = core::ptr::null_mut();
unsafe { duckdb_scalar_function_init_get_client_context(self.info, &raw mut ctx) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[must_use]
#[inline]
pub const fn as_raw(&self) -> duckdb_init_info {
self.info
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scalar_function_info_as_raw_roundtrip() {
let raw = std::ptr::null_mut();
let info = unsafe { ScalarFunctionInfo::new(raw) };
assert_eq!(info.as_raw(), raw);
}
#[cfg(feature = "duckdb-1-5")]
#[test]
fn scalar_bind_info_as_raw_roundtrip() {
let raw = std::ptr::null_mut();
let info = unsafe { ScalarBindInfo::new(raw) };
assert_eq!(info.as_raw(), raw);
}
#[cfg(feature = "duckdb-1-5")]
#[test]
fn scalar_init_info_as_raw_roundtrip() {
let raw = std::ptr::null_mut();
let info = unsafe { ScalarInitInfo::new(raw) };
assert_eq!(info.as_raw(), raw);
}
}