rsbind_core/base/
artifact.rs

1use crate::ast::contract::desc::{StructDesc, TraitDesc};
2use crate::errors::*;
3use crate::AstResult;
4use std::fs;
5use std::path::PathBuf;
6
7pub(crate) struct NativeCodeGen<'a, Extra>
8where
9    Extra: Clone,
10{
11    pub gen_dir: &'a PathBuf,
12    pub file_ext: String,
13    pub ast: &'a AstResult,
14    pub extra: Extra,
15    pub strategy: NativeGenStrategy<'a, Extra>,
16}
17
18pub(crate) struct GenContext<'a, Extra>
19where
20    Extra: Clone,
21{
22    pub ast: &'a AstResult,
23    pub extra: Extra,
24    pub callbacks: Vec<TraitDesc>,
25}
26
27pub(crate) struct NativeGenStrategy<'a, Extra>
28where
29    Extra: Clone,
30{
31    pub gen_bridge_callback: Box<dyn Fn(&GenContext<'a, Extra>, &TraitDesc) -> Result<String>>,
32    pub gen_callback: Box<dyn Fn(&GenContext<'a, Extra>, &TraitDesc) -> Result<String>>,
33    pub gen_bridge_trait: Box<dyn Fn(&GenContext<'a, Extra>, &TraitDesc) -> Result<String>>,
34    pub gen_wrapper_trait: Box<dyn Fn(&GenContext<'a, Extra>, &TraitDesc) -> Result<String>>,
35    pub gen_trait: Box<dyn Fn(&GenContext<'a, Extra>, &TraitDesc) -> Result<String>>,
36    pub gen_struct: Box<dyn Fn(&GenContext<'a, Extra>, &StructDesc) -> Result<String>>,
37    pub gen_manager: Box<dyn Fn(&GenContext<'a, Extra>) -> Result<String>>,
38}
39
40impl<'a, Extra> NativeCodeGen<'a, Extra>
41where
42    Extra: Clone,
43{
44    pub(crate) fn gen_files(&self) -> Result<()> {
45        // collect all the callbacks.
46        let mut callbacks = vec![];
47        for desc in self.ast.traits.iter() {
48            let descs = desc.1;
49            for each in descs.iter() {
50                if each.is_callback {
51                    callbacks.push(each.clone());
52                }
53            }
54        }
55
56        let ctx = GenContext {
57            ast: self.ast,
58            extra: self.extra.clone(),
59            callbacks: callbacks.clone(),
60        };
61
62        // generate all the callbacks.
63        for each in callbacks.clone().iter() {
64            let callback_str = (*self.strategy.gen_callback)(&ctx, each)?;
65            let file_name = format!("{}.{}", &each.name, &self.file_ext);
66            let callback_path = self.gen_dir.clone().join(file_name);
67            fs::write(callback_path, callback_str)?;
68
69            let callback_str = (*self.strategy.gen_bridge_callback)(&ctx, each)?;
70            let file_name = format!("Internal{}.{}", &each.name, &self.file_ext);
71            let callback_path = self.gen_dir.clone().join(file_name);
72            fs::write(callback_path, callback_str)?;
73        }
74
75        // generate all the traits.
76        for desc in self.ast.traits.iter() {
77            let descs = desc.1;
78            for each in descs.iter() {
79                if !each.is_callback {
80                    let str = (*self.strategy.gen_bridge_trait)(&ctx, each)?;
81                    let file_name = format!("Internal{}.{}", &each.name, &self.file_ext);
82                    let path = self.gen_dir.clone().join(file_name);
83                    fs::write(path, str)?;
84
85                    let str = (*self.strategy.gen_wrapper_trait)(&ctx, each)?;
86                    let file_name = format!("Rust{}.{}", &each.name, &self.file_ext);
87                    let path = self.gen_dir.clone().join(file_name);
88                    fs::write(path, str)?;
89
90                    let str = (*self.strategy.gen_trait)(&ctx, each)?;
91                    let file_name = format!("{}.{}", &each.name, &self.file_ext);
92                    let path = self.gen_dir.clone().join(file_name);
93                    fs::write(path, str)?;
94                }
95            }
96        }
97
98        // generate all the structs
99        for (_key, struct_descs) in self.ast.structs.iter() {
100            for struct_desc in struct_descs.iter() {
101                let struct_str = (*self.strategy.gen_struct)(&ctx, struct_desc)?;
102                let file_name = format!("{}.{}", &struct_desc.name, &self.file_ext);
103                let path = self.gen_dir.join(file_name);
104                fs::write(path, struct_str)?
105            }
106        }
107
108        let manager_result = (*self.strategy.gen_manager)(&ctx)?;
109        let path = self.gen_dir.join(format!("RustLib.{}", &self.file_ext));
110        fs::write(path, manager_result)?;
111
112        Ok(())
113    }
114}