datafusion_ffi/session/
config.rs1use std::ffi::c_void;
19
20use crate::config::FFI_ConfigOptions;
21use abi_stable::StableAbi;
22use datafusion_common::config::ConfigOptions;
23use datafusion_common::error::{DataFusionError, Result};
24use datafusion_execution::config::SessionConfig;
25
26#[repr(C)]
38#[derive(Debug, StableAbi)]
39pub struct FFI_SessionConfig {
40 pub config_options: FFI_ConfigOptions,
42
43 pub clone: unsafe extern "C" fn(plan: &Self) -> Self,
46
47 pub release: unsafe extern "C" fn(arg: &mut Self),
49
50 pub private_data: *mut c_void,
52
53 pub library_marker_id: extern "C" fn() -> usize,
57}
58
59unsafe impl Send for FFI_SessionConfig {}
60unsafe impl Sync for FFI_SessionConfig {}
61
62impl FFI_SessionConfig {
63 fn inner(&self) -> &SessionConfig {
64 let private_data = self.private_data as *mut SessionConfigPrivateData;
65 unsafe { &(*private_data).config }
66 }
67}
68
69unsafe extern "C" fn release_fn_wrapper(config: &mut FFI_SessionConfig) {
70 unsafe {
71 debug_assert!(!config.private_data.is_null());
72 let private_data =
73 Box::from_raw(config.private_data as *mut SessionConfigPrivateData);
74 drop(private_data);
75 config.private_data = std::ptr::null_mut();
76 }
77}
78
79unsafe extern "C" fn clone_fn_wrapper(config: &FFI_SessionConfig) -> FFI_SessionConfig {
80 unsafe {
81 let old_private_data = config.private_data as *mut SessionConfigPrivateData;
82 let old_config = (*old_private_data).config.clone();
83
84 let private_data = Box::new(SessionConfigPrivateData { config: old_config });
85
86 FFI_SessionConfig {
87 config_options: config.config_options.clone(),
88 private_data: Box::into_raw(private_data) as *mut c_void,
89 clone: clone_fn_wrapper,
90 release: release_fn_wrapper,
91 library_marker_id: crate::get_library_marker_id,
92 }
93 }
94}
95
96struct SessionConfigPrivateData {
97 pub config: SessionConfig,
98}
99
100impl From<&SessionConfig> for FFI_SessionConfig {
101 fn from(session: &SessionConfig) -> Self {
102 let private_data = Box::new(SessionConfigPrivateData {
103 config: session.clone(),
104 });
105
106 let config_options = FFI_ConfigOptions::from(session.options().as_ref());
107
108 Self {
109 config_options,
110 private_data: Box::into_raw(private_data) as *mut c_void,
111 clone: clone_fn_wrapper,
112 release: release_fn_wrapper,
113 library_marker_id: crate::get_library_marker_id,
114 }
115 }
116}
117
118impl Clone for FFI_SessionConfig {
119 fn clone(&self) -> Self {
120 unsafe { (self.clone)(self) }
121 }
122}
123
124impl Drop for FFI_SessionConfig {
125 fn drop(&mut self) {
126 unsafe { (self.release)(self) };
127 }
128}
129
130impl TryFrom<&FFI_SessionConfig> for SessionConfig {
131 type Error = DataFusionError;
132
133 fn try_from(config: &FFI_SessionConfig) -> Result<Self, Self::Error> {
134 if (config.library_marker_id)() == crate::get_library_marker_id() {
135 return Ok(config.inner().clone());
136 }
137
138 let config_options = ConfigOptions::try_from(config.config_options.clone())?;
139
140 Ok(SessionConfig::from(config_options))
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_round_trip_ffi_session_config() -> Result<()> {
150 let session_config = SessionConfig::new();
151 let original_options = session_config.options().entries();
152
153 let mut ffi_config: FFI_SessionConfig = (&session_config).into();
154 let _ = ffi_config.clone();
155 ffi_config.library_marker_id = crate::mock_foreign_marker_id;
156
157 let foreign_config: SessionConfig = (&ffi_config).try_into()?;
158
159 let returned_options = foreign_config.options().entries();
160
161 assert_eq!(original_options.len(), returned_options.len());
162
163 Ok(())
164 }
165}