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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#![deny(missing_docs)]
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")]
#[doc(hidden)]
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();
}
}
}
}
}