use serde::Deserialize;
pub use typewriter_core::ir::*;
pub use typewriter_core::mapper::TypeMapper;
pub use typewriter_core::naming::{FileStyle, to_file_style};
pub const PLUGIN_API_VERSION: u32 = 1;
#[derive(Debug, Clone, Default, Deserialize)]
pub struct PluginConfig {
pub output_dir: Option<String>,
pub file_style: Option<String>,
#[serde(flatten)]
pub extra: toml::Table,
}
pub trait EmitterPlugin: Send + Sync {
fn language_id(&self) -> &str;
fn language_name(&self) -> &str;
fn version(&self) -> &str;
fn default_output_dir(&self) -> &str;
fn mapper(&self, config: &PluginConfig) -> Box<dyn TypeMapper>;
fn config_key(&self) -> &str {
self.language_id()
}
fn file_extension(&self) -> &str;
fn api_version(&self) -> u32 {
PLUGIN_API_VERSION
}
}
#[macro_export]
macro_rules! declare_plugin {
($plugin_type:ty) => {
#[unsafe(no_mangle)]
pub extern "C" fn _tw_plugin_create() -> *mut dyn $crate::EmitterPlugin {
let plugin: Box<dyn $crate::EmitterPlugin> = Box::new(<$plugin_type>::new());
Box::into_raw(plugin)
}
#[unsafe(no_mangle)]
pub extern "C" fn _tw_plugin_api_version() -> u32 {
$crate::PLUGIN_API_VERSION
}
};
}
pub mod prelude {
pub use super::{
EmitterPlugin, PLUGIN_API_VERSION, PluginConfig,
};
pub use typewriter_core::ir::*;
pub use typewriter_core::mapper::TypeMapper;
pub use typewriter_core::naming::{FileStyle, to_file_style};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_api_version() {
assert_eq!(PLUGIN_API_VERSION, 1);
}
#[test]
fn test_plugin_config_default() {
let config = PluginConfig::default();
assert!(config.output_dir.is_none());
assert!(config.file_style.is_none());
assert!(config.extra.is_empty());
}
#[test]
fn test_plugin_config_deserialization() {
let toml_str = r#"
output_dir = "./generated/ruby"
file_style = "snake_case"
gem_version = "3.2"
"#;
let config: PluginConfig = toml::from_str(toml_str).unwrap();
assert_eq!(config.output_dir.as_deref(), Some("./generated/ruby"));
assert_eq!(config.file_style.as_deref(), Some("snake_case"));
assert_eq!(
config.extra.get("gem_version").and_then(|v| v.as_str()),
Some("3.2")
);
}
}