valkyrie_wit/imports/
mod.rs1use crate::helpers::{FunctionContext, TypeContext, WriteDefine, WriteReference};
2use convert_case::{Case, Casing};
3use std::{fmt::Write, path::Path};
4use std::io::Write as _;
5use wit_parser::{Function, FunctionKind, Handle, Interface, Package, Resolve, Results, Type, TypeDef, TypeDefKind, TypeId};
6
7mod visit_types;
8
9pub struct ValkyrieFFI {
10 cache: Resolve,
11}
12
13impl ValkyrieFFI {
14 pub fn new<P: AsRef<Path>>(directory: P) -> anyhow::Result<Self> {
15 let mut resolved = Resolve::new();
16 resolved.push_dir(directory.as_ref())?;
17 Ok(Self { cache: resolved })
18 }
19 pub fn generate<P: AsRef<Path>>(&self, output: P) -> std::io::Result<()> {
20 let output = output.as_ref();
21 if !output.is_dir() {
22 panic!("")
23 }
24 if !output.exists() {}
25 for (_, item) in self.cache.packages.iter() {
26 self.export_packages(item, output)?;
27 }
28 Ok(())
29 }
30 fn export_packages(&self, package: &Package, root: &Path) -> std::io::Result<()> {
31 let org = package.name.namespace.as_str();
32 let pkg = package.name.name.as_str();
33 tracing::info!("exporting interface: {}/{}", org, pkg);
34 let file = root.join(format!("{}/{}.vk", org, pkg));
35 if let Some(dir) = file.parent() {
36 std::fs::create_dir_all(dir)?;
37 }
38 let mut file = std::fs::File::create(file)?;
39 for (name, ty) in package.interfaces.iter() {
40 match self.cache.interfaces.get(*ty) {
41 Some(s) => {
42 let mut buffer = String::new();
43 self.export_interface(s, package, &mut buffer).unwrap();
44 file.write_all(buffer.as_bytes())?;
45 }
46 None => tracing::error!("interface not found: {:?}", name),
47 }
48 }
49 Ok(())
50 }
51 fn export_interface<W: Write>(&self, interface: &Interface, package: &Package, file: &mut W) -> std::fmt::Result {
52 let name = match interface.name.as_ref() {
53 Some(s) => s,
54 None => panic!("missing name"),
55 };
56 let org = package.name.namespace.as_str();
57 let pkg = package.name.name.as_str();
58 let namespace = format!("{}:{}/{}", org, pkg, name);
59 for (name, item) in interface.types.iter() {
60 match self.cache.types.get(*item) {
61 Some(s) => {
62 if let Err(e) = s.kind.write_define(file, TypeContext {
63 ffi: &self,
64 interface,
65 namespace: &namespace,
66 wasi_name: "",
67 def: &s,
68 }) {
69 tracing::error!("error exporting type: {:?}", e)
70 }
71 }
72 None => tracing::error!("type not found: {:?}", name),
73 }
74 }
75 for (_, item) in interface.functions.iter() {
76 item.write_define(file, FunctionContext { ffi: &self, class_name: "", namespace: &namespace })?
77 }
78 Ok(())
79 }
80}