use crate::utils::error::Result;
use serde_json::json;
use super::{PartManifest, PartSpec};
#[derive(Clone, Debug)]
pub struct AdapterGenerator {
}
impl AdapterGenerator {
pub fn new() -> Self {
Self {}
}
pub async fn generate(&self, spec: &PartSpec, manifest: &PartManifest) -> Result<String> {
match spec.target_language.as_str() {
"rust" => self.generate_rust_adapter(spec, manifest),
"erlang" => self.generate_erlang_adapter(spec, manifest),
_ => Err(crate::utils::error::ggen_error!(
"Unsupported target language: {}",
spec.target_language
)),
}
}
fn generate_rust_adapter(&self, _spec: &PartSpec, manifest: &PartManifest) -> Result<String> {
let mut code = String::new();
code.push_str("//! Generated Genesis membrane adapter\n");
code.push_str("//! Auto-generated by PartFoundry\n\n");
code.push_str("use std::ffi::{c_void, CStr};\n\n");
code.push_str("/// Genesis part interface\n");
code.push_str("pub mod genesis_part {\n");
code.push_str(" use super::*;\n\n");
for iface in &manifest.interfaces {
code.push_str(&format!(" /// Interface: {}\n", iface.name));
code.push_str(&format!(
" pub extern \"C\" fn {}(input: *const c_void) -> *const c_void {{\n",
iface.name.to_lowercase()
));
code.push_str(" // TODO: Implement interface\n");
code.push_str(" std::ptr::null()\n");
code.push_str(" }\n\n");
}
code.push_str("}\n\n");
code.push_str("#[no_mangle]\n");
code.push_str("pub extern \"C\" fn part_init() {\n");
code.push_str(" // Part initialization\n");
code.push_str("}\n\n");
code.push_str("#[no_mangle]\n");
code.push_str("pub extern \"C\" fn part_fini() {\n");
code.push_str(" // Part finalization\n");
code.push_str("}\n");
Ok(code)
}
fn generate_erlang_adapter(&self, spec: &PartSpec, manifest: &PartManifest) -> Result<String> {
let mut code = String::new();
code.push_str("%% Generated Genesis membrane adapter\n");
code.push_str("%% Auto-generated by PartFoundry\n\n");
code.push_str(&format!(
"-module(genesis_{}).\n",
spec.id.replace('-', "_")
));
code.push_str("-export([init/0, fini/0]).\n\n");
for iface in &manifest.interfaces {
code.push_str(&format!("-export([{}/1]).\n", iface.name.to_lowercase()));
}
code.push('\n');
code.push_str("init() ->\n");
code.push_str(" ok.\n\n");
code.push_str("fini() ->\n");
code.push_str(" ok.\n\n");
for iface in &manifest.interfaces {
code.push_str(&format!("{}(Input) ->\n", iface.name.to_lowercase()));
code.push_str(" {ok, Input}.\n\n");
}
Ok(code)
}
}
impl Default for AdapterGenerator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_rust_adapter_generation() {
let gen = AdapterGenerator::new();
let spec = PartSpec {
id: "test-part".to_string(),
version: "1.0.0".to_string(),
part_type: "wasm32".to_string(),
rdf_source: "(RDF)".to_string(),
target_language: "rust".to_string(),
};
let manifest = PartManifest {
interfaces: vec![crate::parts_foundry::InterfaceSpec {
name: "Process".to_string(),
params: json!({"input": "bytes"}),
returns: json!({"output": "bytes"}),
}],
dependencies: Default::default(),
config: json!({}),
};
let code = gen.generate(&spec, &manifest).await.unwrap();
assert!(code.contains("Generated Genesis membrane adapter"));
assert!(code.contains("pub extern"));
assert!(code.contains("process"));
}
#[tokio::test]
async fn test_erlang_adapter_generation() {
let gen = AdapterGenerator::new();
let spec = PartSpec {
id: "test-part".to_string(),
version: "1.0.0".to_string(),
part_type: "beam".to_string(),
rdf_source: "(RDF)".to_string(),
target_language: "erlang".to_string(),
};
let manifest = PartManifest {
interfaces: vec![crate::parts_foundry::InterfaceSpec {
name: "Process".to_string(),
params: json!({"input": "bytes"}),
returns: json!({"output": "bytes"}),
}],
dependencies: Default::default(),
config: json!({}),
};
let code = gen.generate(&spec, &manifest).await.unwrap();
assert!(code.contains("Generated Genesis membrane adapter"));
assert!(code.contains("-module("));
assert!(code.contains("process/1"));
}
#[tokio::test]
async fn test_unsupported_language() {
let gen = AdapterGenerator::new();
let spec = PartSpec {
id: "test-part".to_string(),
version: "1.0.0".to_string(),
part_type: "wasm32".to_string(),
rdf_source: "(RDF)".to_string(),
target_language: "python".to_string(),
};
let manifest = PartManifest {
interfaces: vec![],
dependencies: Default::default(),
config: json!({}),
};
let result = gen.generate(&spec, &manifest).await;
assert!(result.is_err());
}
}