marine/
marine_interface.rs

1/*
2 * Copyright 2020 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use super::IRecordType;
18use super::itype_text_view;
19use crate::MarineModuleInterface;
20
21use itertools::Itertools;
22use serde::Serialize;
23
24use std::fmt;
25use std::collections::HashMap;
26
27#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
28pub struct MarineInterface<'a> {
29    pub modules: HashMap<&'a str, MarineModuleInterface<'a>>,
30}
31
32impl<'a> fmt::Display for MarineInterface<'a> {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        print_record_types(self.modules.values(), f)?;
35        print_functions_sign(self.modules.iter(), f)
36    }
37}
38
39fn print_record_types<'r>(
40    modules: impl Iterator<Item = &'r MarineModuleInterface<'r>>,
41    f: &mut fmt::Formatter<'_>,
42) -> fmt::Result {
43    use std::collections::HashSet;
44    writeln!(f, "exported data types (combined from all modules):")?;
45    let mut printed_record_types: HashSet<&IRecordType> = HashSet::new();
46
47    for module in modules {
48        for (_, record_type) in module.record_types.iter() {
49            if !printed_record_types.insert(record_type) {
50                // do not print record if it has been already printed
51                continue;
52            }
53
54            writeln!(f, "data {}:", record_type.name)?;
55
56            for field in record_type.fields.iter() {
57                writeln!(
58                    f,
59                    "  {}: {}",
60                    field.name,
61                    itype_text_view(&field.ty, module.record_types)
62                )?;
63            }
64        }
65    }
66
67    if printed_record_types.is_empty() {
68        writeln!(f, "<no exported data types>")?;
69    }
70
71    writeln!(f)
72}
73
74fn print_functions_sign<'r>(
75    modules: impl Iterator<Item = (&'r &'r str, &'r MarineModuleInterface<'r>)>,
76    f: &mut fmt::Formatter<'_>,
77) -> fmt::Result {
78    let modules = modules.sorted_by(|lhs, rhs| lhs.0.cmp(rhs.0));
79    writeln!(f, "exported functions:")?;
80    for (name, module_interface) in modules {
81        writeln!(f, "{}:", *name)?;
82        if module_interface.function_signatures.is_empty() {
83            writeln!(f, "<no exported functions>")?;
84            continue;
85        }
86
87        for function_signature in module_interface.function_signatures.iter() {
88            write!(f, "  func {}(", function_signature.name)?;
89
90            let args = function_signature
91                .arguments
92                .iter()
93                .map(|arg| {
94                    format!(
95                        "{}: {}",
96                        arg.name,
97                        itype_text_view(&arg.ty, module_interface.record_types)
98                    )
99                })
100                .join(", ");
101
102            let outputs = &function_signature.outputs;
103            if outputs.is_empty() {
104                writeln!(f, "{})", args)?;
105            } else if outputs.len() == 1 {
106                writeln!(
107                    f,
108                    "{}) -> {}",
109                    args,
110                    itype_text_view(&outputs[0], module_interface.record_types)
111                )?;
112            } else {
113                // At now, multi values aren't supported - only one output type is possible
114                unimplemented!()
115            }
116        }
117    }
118
119    Ok(())
120}