1use super::*;
2
3// TODO: should we use rustfmt in the short term (with pre/post)
4
5#[derive(Default)]
6pub struct Writer {
7 out: String,
8 indent: usize,
9 newline: bool,
10}
11
12impl Writer {
13 pub fn new(file: &rdl::File) -> Self {
14 let mut writer = Self::default();
15 writer.rdl_file(file);
16 writer
17 }
18
19 pub fn into_string(mut self) -> String {
20 self.out.push('\n');
21 self.out
22 }
23
24 fn word(&mut self, value: &str) {
25 if self.newline {
26 self.newline = false;
27 self.out.push('\n');
28 for _ in 0..self.indent {
29 self.out.push_str(" ");
30 }
31 }
32
33 self.out.push_str(value);
34 }
35
36 fn newline(&mut self) {
37 self.newline = true;
38 }
39
40 fn rdl_file(&mut self, file: &rdl::File) {
41 if file.winrt {
42 self.word("#![winrt]\n");
43 } else {
44 self.word("#![win32]\n");
45 }
46
47 self.newline();
48
49 for reference in &file.references {
50 self.item_use(reference);
51 }
52
53 for module in &file.modules {
54 self.rdl_module(module);
55 }
56 }
57
58 fn rdl_module(&mut self, module: &rdl::Module) {
59 self.word("mod ");
60 self.word(module.name());
61 self.word(" {");
62 self.newline();
63 self.indent += 1;
64
65 for member in &module.members {
66 self.rdl_module_member(member);
67 self.newline();
68 }
69
70 self.indent -= 1;
71 self.newline();
72 self.word("}");
73 self.newline();
74 }
75
76 fn rdl_module_member(&mut self, member: &rdl::ModuleMember) {
77 match member {
78 rdl::ModuleMember::Module(member) => self.rdl_module(member),
79 rdl::ModuleMember::Interface(member) => self.rdl_interface(member),
80 rdl::ModuleMember::Struct(member) => self.rdl_struct(member),
81 rdl::ModuleMember::Enum(member) => self.rdl_enum(member),
82 rdl::ModuleMember::Class(member) => self.rdl_class(member),
83 rdl::ModuleMember::Constant(member) => self.rdl_constant(member),
84 rdl::ModuleMember::Function(member) => self.rdl_function(member),
85 }
86 }
87
88 fn rdl_class(&mut self, member: &rdl::Class) {
89 self.attrs(&member.attributes);
90 self.word("class ");
91 self.word(&member.name);
92
93 if !member.extends.is_empty() || member.base.is_some() {
94 self.word(" : ");
95
96 if let Some(path) = &member.base {
97 self.word("class ");
98 self.type_path(path);
99
100 if !member.extends.is_empty() {
101 self.word(", ");
102 }
103 }
104
105 let mut first = true;
106 for path in &member.extends {
107 if first {
108 first = false;
109 } else {
110 self.word(", ");
111 }
112 self.type_path(path);
113 }
114 }
115
116 self.word(";");
117 self.newline();
118 }
119
120 fn rdl_interface(&mut self, member: &rdl::Interface) {
121 self.attrs(&member.attributes);
122 self.word("interface ");
123 self.word(&member.name);
124
125 if !member.generics.is_empty() {
126 self.word("<");
127
128 let mut first = true;
129 for generic in &member.generics {
130 if first {
131 first = false;
132 } else {
133 self.word(", ");
134 }
135 self.word(generic);
136 }
137
138 self.word(">");
139 }
140
141 if !member.extends.is_empty() {
142 self.word(" : ");
143
144 let mut first = true;
145 for path in &member.extends {
146 if first {
147 first = false;
148 } else {
149 self.word(", ");
150 }
151 self.type_path(path);
152 }
153 }
154
155 self.word(" {");
156 self.newline();
157 self.indent += 1;
158
159 for method in &member.methods {
160 self.trait_item_fn(method);
161 self.word(";");
162 self.newline();
163 }
164
165 self.indent -= 1;
166 self.newline();
167 self.word("}");
168 }
169
170 fn rdl_constant(&mut self, member: &rdl::Constant) {
171 self.item_const(&member.item);
172 }
173
174 fn rdl_function(&mut self, member: &rdl::Function) {
175 self.trait_item_fn(&member.item);
176 self.word(";");
177 self.newline();
178 }
179
180 fn item_const(&mut self, item: &syn::ItemConst) {
181 self.word("const ");
182 self.ident(&item.ident);
183 self.word(": ");
184 self.ty(&item.ty);
185 self.word(" = ");
186 self.expr(&item.expr);
187 self.word(";");
188 self.newline();
189 }
190
191 fn attrs(&mut self, attrs: &[syn::Attribute]) {
192 for attr in attrs {
193 self.attr(attr);
194 }
195 }
196
197 fn attr(&mut self, attr: &syn::Attribute) {
198 self.word("#[");
199 self.meta(&attr.meta);
200 self.word("]");
201 self.newline();
202 }
203
204 fn meta(&mut self, meta: &syn::Meta) {
205 match meta {
206 syn::Meta::Path(path) => self.path(path),
207 syn::Meta::List(list) => self.meta_list(list),
208 syn::Meta::NameValue(meta) => self.meta_name_value(meta),
209 }
210 }
211
212 fn meta_list(&mut self, meta_list: &syn::MetaList) {
213 self.path(&meta_list.path);
214 self.word("(");
215 self.word(&meta_list.tokens.to_string());
216 self.word(")");
217 }
218
219 fn meta_name_value(&mut self, meta: &syn::MetaNameValue) {
220 self.path(&meta.path);
221 self.word(" = ");
222 self.expr(&meta.value);
223 }
224
225 fn rdl_struct(&mut self, member: &rdl::Struct) {
226 self.attrs(&member.attributes);
227
228 self.word("struct ");
229 self.word(&member.name);
230 self.word(" {");
231 self.newline();
232 self.indent += 1;
233
234 for field in &member.fields {
235 self.word(&field.name);
236 self.word(": ");
237 self.ty(&field.ty);
238 self.word(",");
239 self.newline();
240 }
241
242 self.indent -= 1;
243 self.newline();
244 self.word("}");
245 }
246
247 fn rdl_enum(&mut self, member: &rdl::Enum) {
248 self.attrs(&member.item.attrs);
249
250 self.word("enum ");
251 self.ident(&member.item.ident);
252 self.word(" {");
253 self.newline();
254 self.indent += 1;
255
256 for variant in &member.item.variants {
257 self.ident(&variant.ident);
258 if let Some((_, expr)) = &variant.discriminant {
259 self.word(" = ");
260 self.expr(expr);
261 }
262 self.word(",");
263 self.newline();
264 }
265
266 self.indent -= 1;
267 self.newline();
268 self.word("}");
269 }
270
271 fn trait_item_fn(&mut self, method: &syn::TraitItemFn) {
272 self.attrs(&method.attrs);
273 self.signature(&method.sig);
274 }
275
276 fn signature(&mut self, signature: &syn::Signature) {
277 self.word("fn ");
278 self.ident(&signature.ident);
279 self.word("(");
280
281 let mut first = true;
282 for input in &signature.inputs {
283 if first {
284 first = false;
285 } else {
286 self.word(", ");
287 }
288 self.fn_arg(input);
289 }
290
291 self.word(")");
292
293 if let syn::ReturnType::Type(_, ty) = &signature.output {
294 self.word(" -> ");
295 self.ty(ty);
296 }
297 }
298
299 fn fn_arg(&mut self, fn_arg: &syn::FnArg) {
300 if let syn::FnArg::Typed(pat_type) = fn_arg {
301 self.pat_type(pat_type);
302 }
303 }
304
305 fn pat_type(&mut self, pat_type: &syn::PatType) {
306 self.pat(&pat_type.pat);
307 self.word(": ");
308 self.ty(&pat_type.ty);
309 }
310
311 fn pat(&mut self, pat: &syn::Pat) {
312 match pat {
313 syn::Pat::Ident(pat_ident) => self.pat_ident(pat_ident),
314 rest => unimplemented!("{rest:?}"),
315 }
316 }
317
318 fn pat_ident(&mut self, pat_ident: &syn::PatIdent) {
319 self.ident(&pat_ident.ident);
320 }
321
322 fn ty(&mut self, ty: &syn::Type) {
323 match ty {
324 syn::Type::Path(ty) => self.type_path(ty),
325 syn::Type::Ptr(ptr) => self.type_ptr(ptr),
326 syn::Type::Array(array) => self.type_array(array),
327 rest => unimplemented!("{rest:?}"),
328 }
329 }
330
331 fn type_array(&mut self, array: &syn::TypeArray) {
332 self.word("[");
333 self.ty(&array.elem);
334 self.word("; ");
335 self.expr(&array.len);
336 self.word("]");
337 }
338
339 fn expr(&mut self, expr: &syn::Expr) {
340 match expr {
341 syn::Expr::Lit(lit) => self.expr_lit(lit),
342 syn::Expr::Unary(unary) => self.expr_unary(unary),
343 rest => unimplemented!("{rest:?}"),
344 }
345 }
346
347 fn expr_unary(&mut self, unary: &syn::ExprUnary) {
348 self.word("-");
349 self.expr(&unary.expr);
350 }
351
352 fn expr_lit(&mut self, expr: &syn::ExprLit) {
353 self.lit(&expr.lit);
354 }
355
356 fn lit(&mut self, lit: &syn::Lit) {
357 match lit {
358 syn::Lit::Int(lit) => self.lit_int(lit),
359 syn::Lit::Str(lit) => self.lit_str(lit),
360 _ => _ = dbg!(lit),
361 }
362 }
363
364 fn lit_str(&mut self, lit: &syn::LitStr) {
365 self.word("\"");
366 self.word(&lit.value());
367 self.word("\"");
368 }
369
370 fn lit_int(&mut self, lit: &syn::LitInt) {
371 self.word(&lit.token().to_string());
372 }
373
374 fn type_ptr(&mut self, ptr: &syn::TypePtr) {
375 if ptr.mutability.is_some() {
376 self.word("*mut ");
377 } else {
378 self.word("*const ");
379 }
380 self.ty(&ptr.elem);
381 }
382
383 fn type_path(&mut self, ty: &syn::TypePath) {
384 self.path(&ty.path);
385 }
386
387 fn path(&mut self, path: &syn::Path) {
388 let mut first = true;
389 for segment in &path.segments {
390 if first {
391 first = false;
392 } else {
393 self.word("::");
394 }
395 self.path_segment(segment);
396 }
397 }
398
399 pub fn path_segment(&mut self, segment: &syn::PathSegment) {
400 self.ident(&segment.ident);
401
402 if let syn::PathArguments::AngleBracketed(args) = &segment.arguments {
403 self.word("<");
404
405 let mut first = true;
406 for arg in &args.args {
407 if first {
408 first = false;
409 } else {
410 self.word(", ");
411 }
412 self.generic_argument(arg);
413 }
414
415 self.word(">");
416 }
417 }
418
419 fn generic_argument(&mut self, arg: &syn::GenericArgument) {
420 match arg {
421 syn::GenericArgument::Type(ty) => self.ty(ty),
422 rest => unimplemented!("{rest:?}"),
423 }
424 }
425
426 fn item_use(&mut self, item: &syn::ItemUse) {
427 self.word("use ");
428 self.use_tree(&item.tree);
429 self.word(";");
430 self.newline();
431 }
432
433 fn use_tree(&mut self, use_tree: &syn::UseTree) {
434 match use_tree {
435 syn::UseTree::Path(use_path) => self.use_path(use_path),
436 syn::UseTree::Name(use_name) => self.use_name(use_name),
437 _ => {}
438 }
439 }
440
441 fn use_path(&mut self, use_path: &syn::UsePath) {
442 self.ident(&use_path.ident);
443 self.word("::");
444 self.use_tree(&use_path.tree);
445 }
446
447 fn use_name(&mut self, use_name: &syn::UseName) {
448 self.ident(&use_name.ident);
449 }
450
451 pub fn ident(&mut self, ident: &syn::Ident) {
452 self.word(&ident.to_string());
453 }
454}
455