datafusion_ffi/config/
mod.rs1pub mod extension_options;
19
20use abi_stable::StableAbi;
21use abi_stable::std_types::{RHashMap, RString};
22use datafusion_common::config::{
23 ConfigExtension, ConfigOptions, ExtensionOptions, TableOptions,
24};
25use datafusion_common::{DataFusionError, Result};
26
27use crate::config::extension_options::FFI_ExtensionOptions;
28
29#[repr(C)]
35#[derive(Debug, Clone, StableAbi)]
36pub struct FFI_ConfigOptions {
37 base_options: RHashMap<RString, RString>,
38
39 extensions: FFI_ExtensionOptions,
40}
41
42impl From<&ConfigOptions> for FFI_ConfigOptions {
43 fn from(options: &ConfigOptions) -> Self {
44 let base_options: RHashMap<RString, RString> = options
45 .entries()
46 .into_iter()
47 .filter_map(|entry| entry.value.map(|value| (entry.key, value)))
48 .map(|(key, value)| (key.into(), value.into()))
49 .collect();
50
51 let mut extensions = FFI_ExtensionOptions::default();
52 for (extension_name, extension) in options.extensions.iter() {
53 for entry in extension.entries().iter() {
54 if let Some(value) = entry.value.as_ref() {
55 extensions
56 .set(format!("{extension_name}.{}", entry.key).as_str(), value)
57 .expect("FFI_ExtensionOptions set should always return Ok");
58 }
59 }
60 }
61
62 Self {
63 base_options,
64 extensions,
65 }
66 }
67}
68
69impl TryFrom<FFI_ConfigOptions> for ConfigOptions {
70 type Error = DataFusionError;
71 fn try_from(ffi_options: FFI_ConfigOptions) -> Result<Self, Self::Error> {
72 let mut options = ConfigOptions::default();
73 options.extensions.insert(ffi_options.extensions);
74
75 for kv_tuple in ffi_options.base_options.iter() {
76 options.set(kv_tuple.0.as_str(), kv_tuple.1.as_str())?;
77 }
78
79 Ok(options)
80 }
81}
82
83pub trait ExtensionOptionsFFIProvider {
84 fn local_or_ffi_extension<C: ConfigExtension + Clone + Default>(&self) -> Option<C>;
89}
90
91impl ExtensionOptionsFFIProvider for ConfigOptions {
92 fn local_or_ffi_extension<C: ConfigExtension + Clone + Default>(&self) -> Option<C> {
93 self.extensions
94 .get::<C>()
95 .map(|v| v.to_owned())
96 .or_else(|| {
97 self.extensions
98 .get::<FFI_ExtensionOptions>()
99 .and_then(|ffi_ext| ffi_ext.to_extension().ok())
100 })
101 }
102}
103
104impl ExtensionOptionsFFIProvider for TableOptions {
105 fn local_or_ffi_extension<C: ConfigExtension + Clone + Default>(&self) -> Option<C> {
106 self.extensions
107 .get::<C>()
108 .map(|v| v.to_owned())
109 .or_else(|| {
110 self.extensions
111 .get::<FFI_ExtensionOptions>()
112 .and_then(|ffi_ext| ffi_ext.to_extension().ok())
113 })
114 }
115}
116
117#[repr(C)]
123#[derive(Debug, Clone, StableAbi)]
124pub struct FFI_TableOptions {
125 base_options: RHashMap<RString, RString>,
126
127 extensions: FFI_ExtensionOptions,
128}
129
130impl From<&TableOptions> for FFI_TableOptions {
131 fn from(options: &TableOptions) -> Self {
132 let base_options: RHashMap<RString, RString> = options
133 .entries()
134 .into_iter()
135 .filter_map(|entry| entry.value.map(|value| (entry.key, value)))
136 .map(|(key, value)| (key.into(), value.into()))
137 .collect();
138
139 let mut extensions = FFI_ExtensionOptions::default();
140 for (extension_name, extension) in options.extensions.iter() {
141 for entry in extension.entries().iter() {
142 if let Some(value) = entry.value.as_ref() {
143 extensions
144 .set(format!("{extension_name}.{}", entry.key).as_str(), value)
145 .expect("FFI_ExtensionOptions set should always return Ok");
146 }
147 }
148 }
149
150 Self {
151 base_options,
152 extensions,
153 }
154 }
155}
156
157impl TryFrom<FFI_TableOptions> for TableOptions {
158 type Error = DataFusionError;
159 fn try_from(ffi_options: FFI_TableOptions) -> Result<Self, Self::Error> {
160 let mut options = TableOptions::default();
161 options.extensions.insert(ffi_options.extensions);
162
163 for kv_tuple in ffi_options.base_options.iter() {
164 options.set(kv_tuple.0.as_str(), kv_tuple.1.as_str())?;
165 }
166
167 Ok(options)
168 }
169}