flarrow_file_ext/
file_ext_default.rs1use crate::prelude::{thirdparty::libloading::Library, *};
2
3#[doc(hidden)]
4#[unsafe(no_mangle)]
5pub static FLARROW_FILE_EXT_PLUGIN: DynamicallyLinkedFileExtPluginInstance =
6 || DefaultFileExtPlugin::new();
7
8static DEFAULT_TOKIO_RUNTIME: std::sync::LazyLock<tokio::runtime::Runtime> =
9 std::sync::LazyLock::new(|| {
10 tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime")
11 });
12
13fn default_runtime<T: Send + 'static>(
14 task: impl Future<Output = T> + Send + 'static,
15) -> tokio::task::JoinHandle<T> {
16 match tokio::runtime::Handle::try_current() {
17 Ok(handle) => handle.spawn(task),
18 Err(_) => DEFAULT_TOKIO_RUNTIME.spawn(task),
19 }
20}
21
22pub struct DefaultFileExtPlugin {}
23
24impl FileExtPlugin for DefaultFileExtPlugin {
25 fn new() -> tokio::task::JoinHandle<Result<Box<dyn FileExtPlugin>>>
26 where
27 Self: Sized,
28 {
29 default_runtime(
30 async move { Ok(Box::new(DefaultFileExtPlugin {}) as Box<dyn FileExtPlugin>) },
31 )
32 }
33
34 fn target(&self) -> Vec<String> {
35 vec!["so".to_string(), "dylib".to_string(), "dll".to_string()]
36 }
37
38 fn load(
39 &self,
40 path: std::path::PathBuf,
41
42 inputs: Inputs,
43 outputs: Outputs,
44 queries: Queries,
45 queryables: Queryables,
46 configuration: serde_yml::Value,
47 ) -> tokio::task::JoinHandle<Result<flarrow_runtime_core::prelude::RuntimeNode>> {
48 default_runtime(async move {
49 match path.extension() {
50 Some(ext) => {
51 if ext == std::env::consts::DLL_EXTENSION {
52 let path_buf = path.clone();
53 let (library, constructor) = tokio::task::spawn_blocking(move || {
54 let library = unsafe {
55 Library::new(path_buf.clone())
56 .wrap_err(format!("Failed to load path {:?}", path_buf))?
57 };
58
59 let constructor = unsafe {
60 library
61 .get::<*mut DynamicallyLinkedNodeInstance>(b"FLARROW_NODE")
62 .wrap_err(format!(
63 "Failed to load symbol 'FLARROW_NODE' from dylib {:?}",
64 path_buf
65 ))?
66 .read()
67 };
68
69 Ok::<_, eyre::Report>((library, constructor))
70 })
71 .await??;
72
73 Ok(RuntimeNode::DynamicallyLinked(DynamicallyLinkedNode {
74 _library: library,
75 handle: (constructor)(
76 inputs,
77 outputs,
78 queries,
79 queryables,
80 configuration,
81 )
82 .await?
83 .wrap_err(format!(
84 "Failed to create dynamically linked node from dylib {:?}",
85 path,
86 ))?,
87 }))
88 } else {
89 Err(eyre::eyre!(
90 "Unsupported file extension '{:?}'. On this platform it must be '{}'",
91 ext,
92 std::env::consts::DLL_EXTENSION
93 ))
94 }
95 }
96 None => Err(eyre::eyre!("No file extension found for path {:?}", path)),
97 }
98 })
99 }
100}