witx_codegen/cpp/
function.rs

1use super::*;
2use std::io::Write;
3
4impl CppGenerator {
5    pub fn define_func<T: Write>(
6        w: &mut PrettyWriter<T>,
7        // module_name: &str,
8        func_witx: &witx::Function,
9    ) -> Result<(), Error> {
10        assert_eq!(func_witx.abi, witx::Abi::Preview1);
11        let name = func_witx.name.as_str().to_string();
12        let params_witx = &func_witx.params;
13        let mut params = vec![];
14        for param_witx in params_witx {
15            let param_name = param_witx.name.as_str();
16            let param_type = ASType::from(&param_witx.tref);
17            params.push((param_name.to_string(), param_type));
18        }
19
20        let results_witx = &func_witx.results;
21        assert_eq!(results_witx.len(), 1);
22        let result_witx = &results_witx[0];
23        let result = ASType::from(&result_witx.tref);
24        let result = match result {
25            ASType::Result(result) => result,
26            _ => unreachable!(),
27        };
28
29        let ok_type = result.ok_type.clone();
30
31        let docs = &func_witx.docs;
32        if !docs.is_empty() {
33            Self::write_docs(w, docs)?;
34        }
35
36        let mut params_decomposed = vec![];
37
38        for param in &params {
39            let mut decomposed = param.1.decompose(&param.0, false);
40            params_decomposed.append(&mut decomposed);
41        }
42
43        let mut results = vec![];
44        // A tuple in a result is expanded into additional parameters, transformed to pointers
45        if let ASType::Tuple(tuple_members) = ok_type.as_ref().leaf() {
46            for (i, tuple_member) in tuple_members.iter().enumerate() {
47                let name = format!("result{}_ptr", i);
48                results.push((name, tuple_member.type_.clone()));
49            }
50        } else {
51            let name = "result_ptr";
52            results.push((name.to_string(), ok_type));
53        }
54
55        let mut results_decomposed = vec![];
56        for result in &results {
57            let mut decomposed = result.1.decompose(&result.0, true);
58            results_decomposed.append(&mut decomposed);
59        }
60
61        let results_decomposed_deref = results_decomposed
62            .iter()
63            .map(|result_ptr_type| match result_ptr_type.type_.as_ref() {
64                ASType::MutPtr(result_type) => ASTypeDecomposed {
65                    name: result_ptr_type.name.clone(),
66                    type_: result_type.clone(),
67                },
68                _ => panic!("Result type is not a pointer"),
69            })
70            .collect::<Vec<_>>();
71        let results_set = results_decomposed_deref
72            .iter()
73            .map(|result| result.type_.as_lang())
74            .collect::<Vec<_>>();
75        let rust_fn_result_str = match results_set.len() {
76            0 => "std::monostate".to_string(),
77            1 => results_set[0].clone(),
78            _ => format!("std::tuple<{}>", results_set.join(", ")),
79        };
80
81        w.indent()?.write(format!(
82            "Expected<{}, {}> {}(",
83            rust_fn_result_str,
84            result.error_type.as_lang(),
85            name.as_fn()
86        ))?;
87
88        if !params_decomposed.is_empty() || !results.is_empty() {
89            w.eol()?;
90        }
91        for (i, param) in params_decomposed.iter().enumerate() {
92            let eol = if i + 1 == params_decomposed.len() {
93                ""
94            } else {
95                ","
96            };
97            w.write_line_continued(format!(
98                "{} {}{}",
99                param.type_.as_lang(),
100                param.name.as_var(),
101                eol
102            ))?;
103        }
104
105        w.write_line(");")?;
106        w.eob()?;
107
108        let signature_witx = func_witx.wasm_signature(witx::CallMode::DefinedImport);
109        let params_count_witx = signature_witx.params.len() + signature_witx.results.len();
110        assert_eq!(
111            params_count_witx,
112            params_decomposed.len() + results_decomposed.len() + 1
113        );
114
115        Ok(())
116    }
117}