datagen_rs/plugins/
plugin.rs

1use crate::generate::current_schema::CurrentSchemaRef;
2use crate::generate::generated_schema::GeneratedSchema;
3use crate::util::types::Result;
4use serde_json::Value;
5use std::fmt::Debug;
6use std::sync::Arc;
7
8#[repr(C)]
9pub enum PluginInitResult {
10    Ok(*mut dyn Plugin),
11    Err(*mut std::ffi::c_char),
12}
13
14impl<T: Plugin + 'static> From<Result<T>> for PluginInitResult {
15    fn from(result: Result<T>) -> Self {
16        match result {
17            Ok(value) => PluginInitResult::Ok(Box::into_raw(Box::new(value))),
18            Err(err) => {
19                PluginInitResult::Err(std::ffi::CString::new(err.to_string()).unwrap().into_raw())
20            }
21        }
22    }
23}
24
25pub trait Plugin: Debug {
26    fn name(&self) -> String;
27
28    #[allow(unused_variables)]
29    fn generate(&self, schema: CurrentSchemaRef, args: Value) -> Result<Arc<GeneratedSchema>> {
30        Err("Operation 'generate' is not supported".into())
31    }
32
33    #[allow(unused_variables)]
34    fn transform(
35        &self,
36        schema: CurrentSchemaRef,
37        value: Arc<GeneratedSchema>,
38        args: Value,
39    ) -> Result<Arc<GeneratedSchema>> {
40        Err("Operation 'transform' is not supported".into())
41    }
42
43    #[allow(unused_variables)]
44    fn serialize(&self, value: &Arc<GeneratedSchema>, args: Value) -> Result<String> {
45        Err("Operation 'serialize' is not supported".into())
46    }
47}
48
49pub trait PluginConstructor: Plugin + Sized {
50    fn new(args: Value) -> Result<Self>;
51}
52
53#[macro_export]
54macro_rules! declare_plugin {
55    ($plugin_type:ty, $constructor: path) => {
56        impl PluginConstructor for $plugin_type {
57            fn new(args: Value) -> Result<Self> {
58                Ok($constructor())
59            }
60        }
61
62        declare_plugin!($plugin_type);
63    };
64    ($plugin_type:ty) => {
65        #[no_mangle]
66        pub unsafe extern "C" fn _plugin_create(
67            args: *mut Value,
68        ) -> datagen_rs::plugins::plugin::PluginInitResult {
69            // make sure the constructor is the correct type.
70            let constructor: fn(args: Value) -> Result<$plugin_type> = <$plugin_type>::new;
71
72            let args = Box::from_raw(args);
73            constructor(*args).into()
74        }
75
76        #[no_mangle]
77        pub extern "C" fn _plugin_version() -> *mut std::ffi::c_char {
78            std::ffi::CString::new("1.0.0").unwrap().into_raw()
79        }
80    };
81}