use std::ffi::{CStr, CString};
use std::os::raw::c_void;
use libduckdb_sys::{
duckdb_copy_function_bind_get_client_context, duckdb_copy_function_bind_get_column_count,
duckdb_copy_function_bind_get_column_type, duckdb_copy_function_bind_get_extra_info,
duckdb_copy_function_bind_info, duckdb_copy_function_bind_set_bind_data,
duckdb_copy_function_bind_set_error, duckdb_copy_function_finalize_get_bind_data,
duckdb_copy_function_finalize_get_client_context, duckdb_copy_function_finalize_get_extra_info,
duckdb_copy_function_finalize_get_global_state, duckdb_copy_function_finalize_info,
duckdb_copy_function_finalize_set_error, duckdb_copy_function_global_init_get_bind_data,
duckdb_copy_function_global_init_get_client_context,
duckdb_copy_function_global_init_get_extra_info,
duckdb_copy_function_global_init_get_file_path, duckdb_copy_function_global_init_info,
duckdb_copy_function_global_init_set_error, duckdb_copy_function_global_init_set_global_state,
duckdb_copy_function_sink_get_bind_data, duckdb_copy_function_sink_get_client_context,
duckdb_copy_function_sink_get_extra_info, duckdb_copy_function_sink_get_global_state,
duckdb_copy_function_sink_info, duckdb_copy_function_sink_set_error, duckdb_delete_callback_t,
};
use crate::types::LogicalType;
#[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 CopyBindInfo {
info: duckdb_copy_function_bind_info,
}
impl CopyBindInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_copy_function_bind_info) -> Self {
Self { info }
}
#[mutants::skip]
#[must_use]
pub fn column_count(&self) -> u64 {
unsafe { duckdb_copy_function_bind_get_column_count(self.info) }
}
#[must_use]
pub unsafe fn column_type(&self, index: u64) -> LogicalType {
let raw = unsafe { duckdb_copy_function_bind_get_column_type(self.info, index) };
unsafe { LogicalType::from_raw(raw) }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_copy_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_copy_function_bind_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_copy_function_bind_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let ctx = unsafe { duckdb_copy_function_bind_get_client_context(self.info) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[inline]
#[must_use]
pub const fn as_raw(&self) -> duckdb_copy_function_bind_info {
self.info
}
}
pub struct CopyGlobalInitInfo {
info: duckdb_copy_function_global_init_info,
}
impl CopyGlobalInitInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_copy_function_global_init_info) -> Self {
Self { info }
}
#[must_use]
pub unsafe fn get_bind_data(&self) -> *mut c_void {
unsafe { duckdb_copy_function_global_init_get_bind_data(self.info) }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_copy_function_global_init_get_extra_info(self.info) }
}
#[must_use]
pub unsafe fn get_file_path(&self) -> String {
let c_str = unsafe { duckdb_copy_function_global_init_get_file_path(self.info) };
let result = if c_str.is_null() {
String::new()
} else {
unsafe { CStr::from_ptr(c_str) }
.to_str()
.unwrap_or("")
.to_owned()
};
if !c_str.is_null() {
unsafe {
libduckdb_sys::duckdb_free(c_str as *mut c_void);
}
}
result
}
pub unsafe fn set_global_state(&self, state: *mut c_void, destroy: duckdb_delete_callback_t) {
unsafe {
duckdb_copy_function_global_init_set_global_state(self.info, state, destroy);
}
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_copy_function_global_init_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let ctx = unsafe { duckdb_copy_function_global_init_get_client_context(self.info) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[inline]
#[must_use]
pub const fn as_raw(&self) -> duckdb_copy_function_global_init_info {
self.info
}
}
pub struct CopySinkInfo {
info: duckdb_copy_function_sink_info,
}
impl CopySinkInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_copy_function_sink_info) -> Self {
Self { info }
}
#[must_use]
pub unsafe fn get_bind_data(&self) -> *mut c_void {
unsafe { duckdb_copy_function_sink_get_bind_data(self.info) }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_copy_function_sink_get_extra_info(self.info) }
}
#[must_use]
pub unsafe fn get_global_state(&self) -> *mut c_void {
unsafe { duckdb_copy_function_sink_get_global_state(self.info) }
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_copy_function_sink_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let ctx = unsafe { duckdb_copy_function_sink_get_client_context(self.info) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[inline]
#[must_use]
pub const fn as_raw(&self) -> duckdb_copy_function_sink_info {
self.info
}
}
pub struct CopyFinalizeInfo {
info: duckdb_copy_function_finalize_info,
}
impl CopyFinalizeInfo {
#[inline]
#[must_use]
pub const unsafe fn new(info: duckdb_copy_function_finalize_info) -> Self {
Self { info }
}
#[must_use]
pub unsafe fn get_bind_data(&self) -> *mut c_void {
unsafe { duckdb_copy_function_finalize_get_bind_data(self.info) }
}
#[must_use]
pub unsafe fn get_extra_info(&self) -> *mut c_void {
unsafe { duckdb_copy_function_finalize_get_extra_info(self.info) }
}
#[must_use]
pub unsafe fn get_global_state(&self) -> *mut c_void {
unsafe { duckdb_copy_function_finalize_get_global_state(self.info) }
}
#[mutants::skip]
pub fn set_error(&self, message: &str) {
let c_msg = str_to_cstring(message);
unsafe {
duckdb_copy_function_finalize_set_error(self.info, c_msg.as_ptr());
}
}
pub unsafe fn get_client_context(&self) -> crate::client_context::ClientContext {
let ctx = unsafe { duckdb_copy_function_finalize_get_client_context(self.info) };
unsafe { crate::client_context::ClientContext::from_raw(ctx) }
}
#[mutants::skip]
#[inline]
#[must_use]
pub const fn as_raw(&self) -> duckdb_copy_function_finalize_info {
self.info
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn copy_bind_info_wraps_null() {
let _info = unsafe { CopyBindInfo::new(std::ptr::null_mut()) };
}
#[test]
fn copy_global_init_info_wraps_null() {
let _info = unsafe { CopyGlobalInitInfo::new(std::ptr::null_mut()) };
}
#[test]
fn copy_sink_info_wraps_null() {
let _info = unsafe { CopySinkInfo::new(std::ptr::null_mut()) };
}
#[test]
fn copy_finalize_info_wraps_null() {
let _info = unsafe { CopyFinalizeInfo::new(std::ptr::null_mut()) };
}
}