1mod common;
2mod function;
3mod r#struct;
4mod tuple;
5mod union;
6
7use std::io::Write;
8
9use common::*;
10
11use super::*;
12use crate::astype::*;
13use crate::error::*;
14use crate::pretty_writer::PrettyWriter;
15
16pub struct OverviewGenerator {
17 module_name: Option<String>,
18}
19
20impl OverviewGenerator {
21 pub fn new(module_name: Option<String>) -> Self {
22 OverviewGenerator { module_name }
23 }
24}
25
26impl<T: Write> Generator<T> for OverviewGenerator {
27 fn generate(
28 &self,
29 writer: &mut T,
30 module_witx: witx::Module,
31 options: &Options,
32 ) -> Result<(), Error> {
33 let mut w = PrettyWriter::new(writer, " ");
34 let module_name = match &self.module_name {
35 None => module_witx.name().as_str().to_string(),
36 Some(module_name) => module_name.to_string(),
37 };
38 let module_id = module_witx.module_id();
39 let skip_imports = options.skip_imports;
40
41 if !options.skip_header {
42 Self::header(&mut w)?;
43 }
44
45 let module_title_doc = format!(
46 "---------------------- Module: [{}] ----------------------",
47 module_name
48 );
49 w.eob()?;
50 w.write_line(module_title_doc)?;
51 w.eob()?;
52
53 for type_ in module_witx.typenames() {
54 if skip_imports && &type_.module != module_id {
55 continue;
56 }
57 let constants_for_type: Vec<_> = module_witx
58 .constants()
59 .filter_map(|x| {
60 if x.ty == type_.name {
61 Some(ASConstant {
62 name: x.name.as_str().to_string(),
63 value: x.value,
64 })
65 } else {
66 None
67 }
68 })
69 .collect();
70 Self::define_type(&mut w, type_.as_ref(), &constants_for_type)?;
71 }
72
73 for func in module_witx.funcs() {
74 Self::define_func(&mut w, &module_name, func.as_ref())?;
75 }
76
77 Ok(())
78 }
79}
80
81impl OverviewGenerator {
82 fn header<T: Write>(w: &mut PrettyWriter<T>) -> Result<(), Error> {
83 w.write_line("* API overview *")?;
84 w.eob()?;
85 Ok(())
86 }
87
88 fn define_as_alias<T: Write>(
89 w: &mut PrettyWriter<T>,
90 name: &str,
91 other_type: &ASType,
92 ) -> Result<(), Error> {
93 w.write_line(format!(
94 "alias {} = {}",
95 name.as_type(),
96 other_type.as_lang()
97 ))?;
98 Ok(())
99 }
100
101 fn define_as_atom<T: Write>(
102 w: &mut PrettyWriter<T>,
103 name: &str,
104 type_: &ASType,
105 ) -> Result<(), Error> {
106 w.write_line(format!("alias {} = {}", name.as_type(), type_.as_lang()))?;
107 Ok(())
108 }
109
110 fn define_as_enum<T: Write>(
111 w: &mut PrettyWriter<T>,
112 name: &str,
113 enum_: &ASEnum,
114 ) -> Result<(), Error> {
115 let repr = enum_.repr.as_ref();
116 w.write_line(format!(
117 "enum {}: (tag: {})",
118 name.as_type(),
119 repr.as_lang()
120 ))?;
121 {
122 let mut w = w.new_block();
123 for choice in &enum_.choices {
124 w.write_line(format!("- {}: {}", choice.name.as_const(), choice.value))?;
125 }
126 }
127 Ok(())
128 }
129
130 fn define_as_constants<T: Write>(
131 w: &mut PrettyWriter<T>,
132 name: &str,
133 constants: &ASConstants,
134 ) -> Result<(), Error> {
135 let repr = constants.repr.as_ref();
136 w.write_line(format!(
137 "constants {}: (type: {})",
138 name.as_type(),
139 repr.as_lang()
140 ))?;
141 Self::define_constants_for_type(w, name, &constants.constants)?;
142 Ok(())
143 }
144
145 fn define_as_type<T: Write>(
146 w: &mut PrettyWriter<T>,
147 name: &str,
148 type_: &ASType,
149 ) -> Result<(), Error> {
150 match type_ {
151 ASType::Alias(_)
152 | ASType::Bool
153 | ASType::Char8
154 | ASType::Char32
155 | ASType::F32
156 | ASType::F64
157 | ASType::U8
158 | ASType::U16
159 | ASType::U32
160 | ASType::U64
161 | ASType::S8
162 | ASType::S16
163 | ASType::S32
164 | ASType::S64
165 | ASType::USize
166 | ASType::Handle(_)
167 | ASType::Slice(_)
168 | ASType::String(_)
169 | ASType::ReadBuffer(_)
170 | ASType::WriteBuffer(_) => Self::define_as_atom(w, name, type_)?,
171 ASType::Enum(enum_) => Self::define_as_enum(w, name, enum_)?,
172 ASType::Union(union_) => Self::define_as_union(w, name, union_)?,
173 ASType::Constants(constants) => Self::define_as_constants(w, name, constants)?,
174 ASType::Tuple(members) => Self::define_as_tuple(w, name, members)?,
175 ASType::Struct(members) => Self::define_as_struct(w, name, members)?,
176 _ => {
177 dbg!(type_);
178 unimplemented!();
179 }
180 }
181 Ok(())
182 }
183
184 fn define_constants_for_type<T: Write>(
185 w: &mut PrettyWriter<T>,
186 type_name: &str,
187 constants: &[ASConstant],
188 ) -> Result<(), Error> {
189 if constants.is_empty() {
190 return Ok(());
191 }
192 w.write_line(format!("predefined constants for {}:", type_name.as_type()))?;
193 {
194 let mut w = w.new_block();
195 let mut hex = false;
196 let mut single_bits: usize = 0;
197 for constant in constants {
198 if constant.value > 0xffff {
199 hex = true;
200 }
201 if constant.value.count_ones() == 1 {
202 single_bits += 1;
203 }
204 }
205 if constants.len() > 2 && single_bits == constants.len() {
206 hex = true;
207 }
208 for constant in constants {
209 let value_s = if hex {
210 format!("0x{:x}", constant.value)
211 } else {
212 format!("{}", constant.value)
213 };
214 w.write_line(format!("- {} = {}", constant.name.as_const(), value_s))?;
215 }
216 }
217 Ok(())
218 }
219
220 fn define_type<T: Write>(
221 w: &mut PrettyWriter<T>,
222 type_witx: &witx::NamedType,
223 constants: &[ASConstant],
224 ) -> Result<(), Error> {
225 let type_name = type_witx.name.as_str();
226 let tref = &type_witx.tref;
227 match tref {
228 witx::TypeRef::Name(other_type) => {
229 Self::define_as_alias(w, type_name, &ASType::from(&other_type.tref))?
230 }
231 witx::TypeRef::Value(type_witx) => {
232 let t = ASType::from(type_witx.as_ref());
233 Self::define_as_type(w, type_name, &t)?
234 }
235 }
236 Self::define_constants_for_type(w, type_name, constants)?;
237 w.eob()?;
238 Ok(())
239 }
240}