1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
mod abi;
mod dart;
mod js;
mod parser;
mod rust;
use crate::abi::{
export, import, AbiFunction, AbiFuture, AbiIter, AbiObject, AbiStream, AbiType, FunctionType,
NumType, Return, Var,
};
use crate::dart::DartGenerator;
use crate::js::{JsGenerator, TsGenerator, WasmMultiValueShim};
use crate::parser::Interface;
use crate::rust::RustGenerator;
use anyhow::Result;
use std::path::Path;
use std::process::Command;
pub use crate::abi::Abi;
pub struct FfiGen {
iface: Interface,
}
impl FfiGen {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
let s = std::fs::read_to_string(path)?;
let iface = Interface::parse(&s)?;
Ok(Self { iface })
}
pub fn generate_rust(&self, abi: Abi) -> Result<String> {
let rust = RustGenerator::new(abi);
let rust = rust.generate(self.iface.clone()).to_file_string()?;
Ok(rust)
}
pub fn wasm_multi_value_shim<P: AsRef<Path>>(&self, path: P) -> Result<()> {
WasmMultiValueShim::new().run(path, self.iface.clone())
}
pub fn generate_dart<P: AsRef<Path>>(
&self,
path: P,
library: &str,
cdylib: &str,
) -> Result<()> {
let dart = DartGenerator::new(library.to_string(), cdylib.to_string());
let dart = dart.generate(self.iface.clone()).to_file_string()?;
std::fs::write(path.as_ref(), &dart)?;
let status = Command::new("dart")
.arg("format")
.arg(path.as_ref())
.status()?;
if !status.success() {
anyhow::bail!("dart format failed");
}
Ok(())
}
pub fn generate_js<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let js = JsGenerator::default();
let js = js.generate(self.iface.clone()).to_file_string()?;
std::fs::write(path.as_ref(), &js)?;
let status = Command::new("prettier")
.arg("--write")
.arg(path.as_ref())
.status()?;
if !status.success() {
anyhow::bail!("prettier failed");
}
Ok(())
}
pub fn generate_ts<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let ts = TsGenerator::default();
let ts = ts.generate(self.iface.clone()).to_file_string()?;
std::fs::write(path.as_ref(), &ts)?;
let status = Command::new("prettier")
.arg("--write")
.arg(path.as_ref())
.status()?;
if !status.success() {
anyhow::bail!("prettier failed");
}
Ok(())
}
}
#[cfg(feature = "test_runner")]
pub mod test_runner {
pub use crate::dart::test_runner::compile_pass as compile_pass_dart;
pub use crate::js::test_runner::compile_pass as compile_pass_js;
pub use crate::js::test_runner::compile_pass_ts;
pub use crate::rust::test_runner::compile_pass as compile_pass_rust;
#[macro_export]
macro_rules! compile_pass {
($ident:ident, $iface:expr, ($($api:tt)*), ($($rust:tt)*), ($($dart:tt)*), ($($js:tt)*), ($($ts:tt)*)) => {
mod $ident {
#[test]
fn rust() {
$crate::test_runner::compile_pass_rust($iface, genco::quote!($($api)*), genco::quote!($($rust)*)).unwrap();
}
#[test]
fn dart() {
$crate::test_runner::compile_pass_dart($iface, genco::quote!($($api)*), genco::quote!($($dart)*)).unwrap();
}
#[test]
fn js() {
$crate::test_runner::compile_pass_js($iface, genco::quote!($($api)*), genco::quote!($($js)*)).unwrap();
}
#[test]
fn ts() {
$crate::test_runner::compile_pass_ts($iface, genco::quote!($($ts)*)).unwrap();
}
}
}
}
}