valkyrie_wit/imports/
mod.rs

1use 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}