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