1use std::collections::HashSet;
2use std::io::{self, ErrorKind, Write};
3
4use crate::parse::{Method, Namespace, Record, RecordKind, Type, Value};
5use crate::Generator;
6
7struct UnnamedRecordScope {
8 prefix: String,
9 records: Vec<Record>,
10}
11
12impl UnnamedRecordScope {
13 fn next_name(&self) -> String {
14 format!("{}__type{}", self.prefix, self.records.len())
15 }
16
17 fn add_record(&mut self, record: Record) {
18 self.records.push(record);
19 }
20}
21
22pub struct RustPrinter<'a, W> {
23 sink: W,
24 options: &'a Generator,
25 reserved: HashSet<&'static str>,
26 indent_level: usize,
27 unnamed_records: Vec<UnnamedRecordScope>,
28}
29
30impl<'a, W: Write> RustPrinter<'a, W> {
31 pub fn new(sink: W, options: &'a Generator) -> RustPrinter<'a, W> {
32 RustPrinter {
33 sink,
34 options: options,
35 reserved: HashSet::from(["type"]),
36 indent_level: 0,
37 unnamed_records: Vec::new(),
38 }
39 }
40
41 fn indent(&self) -> String {
42 " ".repeat(self.indent_level)
43 }
44
45 #[rustfmt::skip]
46 pub fn print_namespace(&mut self, namespace: &Namespace) -> io::Result<()> {
47 self.push_unnamed_records("");
48
49 let indent = self.indent();
50
51 for typedef in &namespace.typedefs {
52 let name = &typedef.name;
53
54 write!(self.sink, "{indent}pub type {name} = ")?;
55 self.print_type(&typedef.type_)?;
56 writeln!(self.sink, ";")?;
57
58 if !typedef.inner.is_empty() {
59 writeln!(self.sink, "{indent}pub mod {name}_ {{")?;
60 writeln!(self.sink, "{indent} #[allow(unused_imports)]")?;
61 writeln!(self.sink, "{indent} use super::*;")?;
62
63 self.indent_level += 1;
64 self.print_namespace(&typedef.inner)?;
65 self.indent_level -= 1;
66
67 writeln!(self.sink, "{indent}}}")?;
68 }
69 }
70
71 for record in &namespace.records {
72 self.print_record(&record)?;
73 }
74
75 for constant in &namespace.constants {
76 let name = &constant.name;
77 write!(self.sink, "{indent}pub const {name}: ")?;
78 self.print_type(&constant.type_)?;
79 match &constant.value {
80 Value::Signed(value) => writeln!(self.sink, " = {value:?};")?,
81 Value::Unsigned(value) => writeln!(self.sink, " = {value:?};")?,
82 Value::Float(value) => writeln!(self.sink, " = {value:?};")?,
83 Value::Str(value) => writeln!(self.sink, " = b\"{value}\\0\".as_ptr() as *const ::std::ffi::c_char;")?,
84 }
85 }
86
87 for constant in &namespace.unparsed_constants {
88 let indent = self.indent();
89 writeln!(self.sink, "{indent}{constant}")?;
90 }
91
92 for (name, child) in &namespace.children {
93 if !child.is_empty() {
94 writeln!(self.sink, "{indent}pub mod {name} {{")?;
95 writeln!(self.sink, "{indent} #[allow(unused_imports)]")?;
96 writeln!(self.sink, "{indent} use super::*;")?;
97
98 self.indent_level += 1;
99 self.print_namespace(child)?;
100 self.indent_level -= 1;
101
102 writeln!(self.sink, "{indent}}}")?;
103 }
104 }
105
106 self.pop_unnamed_records()?;
107
108 Ok(())
109 }
110
111 #[rustfmt::skip]
112 fn print_record(&mut self, record: &Record) -> io::Result<()> {
113 self.push_unnamed_records(&record.name);
114
115 let needs_module = !record.inner.is_empty();
116
117 let name = &record.name;
118
119 if needs_module {
120 let indent = self.indent();
121
122 writeln!(self.sink, "{indent}mod __{name}_wrapper {{")?;
123 writeln!(self.sink, "{indent} #[allow(unused_imports)]")?;
124 writeln!(self.sink, "{indent} use super::*;")?;
125 writeln!(self.sink, "{indent} #[allow(unused_imports)]")?;
126 writeln!(self.sink, "{indent} use super::{name}_::*;")?;
127
128 self.indent_level += 1;
129 self.print_record_body(record)?;
130 self.print_interface(record)?;
131 self.indent_level -= 1;
132
133 writeln!(self.sink, "{indent}}}")?;
134 writeln!(self.sink, "{indent}pub use __{name}_wrapper::*;")?;
135
136 writeln!(self.sink, "{indent}pub mod {name}_ {{")?;
137 writeln!(self.sink, "{indent} #[allow(unused_imports)]")?;
138 writeln!(self.sink, "{indent} use super::*;")?;
139
140 self.indent_level += 1;
141 self.print_namespace(&record.inner)?;
142 self.indent_level -= 1;
143
144 writeln!(self.sink, "{indent}}}")?;
145 } else {
146 self.print_record_body(record)?;
147 self.print_interface(record)?;
148 }
149
150 self.pop_unnamed_records()?;
151
152 Ok(())
153 }
154
155 #[rustfmt::skip]
156 fn print_record_body(&mut self, record: &Record) -> io::Result<()> {
157 let indent = self.indent();
158 let name = &record.name;
159 let record_kind = match record.kind {
160 RecordKind::Struct => "struct",
161 RecordKind::Union => "union",
162 };
163
164 writeln!(self.sink, "{indent}#[repr(C)]")?;
165 writeln!(self.sink, "{indent}#[derive(Copy, Clone)]")?;
166 writeln!(self.sink, "{indent}pub {record_kind} {name} {{")?;
167
168 if !record.virtual_methods.is_empty() {
169 writeln!(self.sink, "{indent} pub vtbl: *const {name}Vtbl,")?;
170 }
171
172 let mut anon_counter = 0;
173 for field in &record.fields {
174 if let Some(field_name) = &field.name {
175 if self.reserved.contains(&**field_name) {
176 write!(self.sink, "{indent} pub r#{field_name}: ")?;
177 } else {
178 write!(self.sink, "{indent} pub {field_name}: ")?;
179 }
180 } else {
181 write!(self.sink, "{indent} pub __field{anon_counter}: ")?;
182 anon_counter += 1;
183 }
184 self.print_type(&field.type_)?;
185 writeln!(self.sink, ",")?;
186 }
187
188 writeln!(self.sink, "{indent}}}")?;
189 writeln!(self.sink, "{indent}unsafe impl Send for {name} {{}}")?;
190 writeln!(self.sink, "{indent}unsafe impl Sync for {name} {{}}")?;
191
192 Ok(())
193 }
194
195 #[rustfmt::skip]
196 fn print_interface(&mut self, record: &Record) -> io::Result<()> {
197 if !record.virtual_methods.is_empty() {
198 let indent = self.indent();
199 let name = &record.name;
200
201 if record.bases.len() > 1 {
202 return Err(io::Error::new(
203 ErrorKind::Other,
204 format!("type {name} has more than one base class"),
205 ));
206 }
207
208 {
209 let mut bases = &record.bases;
210 while let Some(base) = bases.first() {
211 let base_name = &base.name;
212 writeln!(self.sink, "{indent}unsafe impl ::com_scrape_types::Inherits<{base_name}> for {name} {{}}")?;
213 bases = &base.bases;
214 }
215 }
216
217 let iid_generator = self.options.iid_generator.as_ref().ok_or_else(|| {
218 io::Error::new(ErrorKind::Other, "no value provided for iid_generator")
219 })?;
220 let iid_string = iid_generator(name);
221 let query_interface_fn = self.options.query_interface_fn.as_ref().ok_or_else(|| {
222 io::Error::new(ErrorKind::Other, "no value provided for query_interface_fn")
223 })?;
224 let add_ref_fn = self.options.add_ref_fn.as_ref().ok_or_else(|| {
225 io::Error::new(ErrorKind::Other, "no value provided for add_ref_fn")
226 })?;
227 let release_fn = self.options.release_fn.as_ref().ok_or_else(|| {
228 io::Error::new(ErrorKind::Other, "no value provided for release_fn")
229 })?;
230
231 writeln!(self.sink, "{indent}impl ::com_scrape_types::Unknown for {name} {{")?;
232 writeln!(self.sink, "{indent} #[inline]")?;
233 writeln!(self.sink, "{indent} unsafe fn query_interface(this: *mut Self, iid: &::com_scrape_types::Guid) -> Option<*mut c_void> {{")?;
234 writeln!(self.sink, "{indent} {query_interface_fn}(this as *mut c_void, iid)")?;
235 writeln!(self.sink, "{indent} }}")?;
236 writeln!(self.sink, "{indent} #[inline]")?;
237 writeln!(self.sink, "{indent} unsafe fn add_ref(this: *mut Self) -> usize {{")?;
238 writeln!(self.sink, "{indent} {add_ref_fn}(this as *mut c_void)")?;
239 writeln!(self.sink, "{indent} }}")?;
240 writeln!(self.sink, "{indent} #[inline]")?;
241 writeln!(self.sink, "{indent} unsafe fn release(this: *mut Self) -> usize {{")?;
242 writeln!(self.sink, "{indent} {release_fn}(this as *mut c_void)")?;
243 writeln!(self.sink, "{indent} }}")?;
244 writeln!(self.sink, "{indent}}}")?;
245
246 writeln!(self.sink, "{indent}unsafe impl ::com_scrape_types::Interface for {name} {{")?;
247 writeln!(self.sink, "{indent} type Vtbl = {name}Vtbl;")?;
248 writeln!(self.sink, "{indent} const IID: ::com_scrape_types::Guid = {iid_string};")?;
249 writeln!(self.sink, "{indent} #[inline]")?;
250 writeln!(self.sink, "{indent} fn inherits(iid: &::com_scrape_types::Guid) -> bool {{")?;
251 write!(self.sink, "{indent} iid == &Self::IID")?;
252 if let Some(base) = record.bases.first() {
253 let base_name = &base.name;
254 write!(self.sink, " || {base_name}::inherits(iid)")?;
255 }
256 writeln!(self.sink, "")?;
257 writeln!(self.sink, "{indent} }}")?;
258 writeln!(self.sink, "{indent}}}")?;
259
260 writeln!(self.sink, "{indent}#[repr(C)]")?;
261 writeln!(self.sink, "{indent}#[derive(Copy, Clone)]")?;
262 writeln!(self.sink, "{indent}pub struct {name}Vtbl {{")?;
263
264 if let Some(base) = record.bases.first() {
265 let base_name = &base.name;
266 writeln!(self.sink, "{indent} pub base: {base_name}Vtbl,")?;
267 }
268
269 for method in &record.virtual_methods {
270 let method_name = &method.name;
271 writeln!(
272 self.sink,
273 "{indent} pub {method_name}: unsafe extern \"system\" fn("
274 )?;
275
276 writeln!(self.sink, "{indent} this: *mut {name},")?;
277
278 self.indent_level += 2;
279 self.print_args(method)?;
280 self.indent_level -= 2;
281
282 write!(self.sink, "{indent} )")?;
283 if let Type::Void = method.result_type {
284 } else {
285 write!(self.sink, " -> ")?;
286 self.print_type(&method.result_type)?;
287 }
288 writeln!(self.sink, ",")?;
289 }
290
291 writeln!(self.sink, "{indent}}}")?;
292
293 if !self.options.skip_interface_traits.contains(&record.name) {
294 write!(self.sink, "{indent}pub trait {name}Trait")?;
295 {
296 let mut bases = &record.bases;
297 while let Some(base) = bases.first() {
298 if !self.options.skip_interface_traits.contains(&base.name) {
299 let base_name = &base.name;
300 write!(self.sink, ": {base_name}Trait")?;
301 break;
302 }
303 bases = &base.bases;
304 }
305 }
306 writeln!(self.sink, " {{")?;
307
308 for method in &record.virtual_methods {
309 let method_name = &method.name;
310
311 writeln!(self.sink, "{indent} unsafe fn {method_name}(")?;
312 writeln!(self.sink, "{indent} &self,")?;
313
314 self.indent_level += 2;
315 self.print_args(method)?;
316 self.indent_level -= 2;
317
318 write!(self.sink, "{indent} )")?;
319 if let Type::Void = method.result_type {
320 } else {
321 write!(self.sink, " -> ")?;
322 self.print_type(&method.result_type)?;
323 }
324 writeln!(self.sink, ";")?;
325 }
326
327 writeln!(self.sink, "{indent}}}")?;
328
329 writeln!(self.sink, "{indent}impl<P> {name}Trait for P")?;
330 writeln!(self.sink, "{indent}where")?;
331 writeln!(self.sink, "{indent} P: ::com_scrape_types::SmartPtr,")?;
332 writeln!(self.sink, "{indent} P::Target: ::com_scrape_types::Inherits<{name}>,")?;
333 {
334 let mut bases = &record.bases;
335 while let Some(base) = bases.first() {
336 if !self.options.skip_interface_traits.contains(&base.name) {
337 let base_name = &base.name;
338 writeln!(self.sink, "{indent} P::Target: ::com_scrape_types::Inherits<{base_name}>,")?;
339 }
340 bases = &base.bases;
341 }
342 }
343 writeln!(self.sink, "{indent}{{")?;
344
345 for method in &record.virtual_methods {
346 let method_name = &method.name;
347
348 writeln!(self.sink, "{indent} #[inline]")?;
349 writeln!(self.sink, "{indent} unsafe fn {method_name}(")?;
350 writeln!(self.sink, "{indent} &self,")?;
351
352 self.indent_level += 2;
353 self.print_args(method)?;
354 self.indent_level -= 2;
355
356 write!(self.sink, "{indent} )")?;
357 if let Type::Void = method.result_type {
358 } else {
359 write!(self.sink, " -> ")?;
360 self.print_type(&method.result_type)?;
361 }
362 writeln!(self.sink, " {{")?;
363 writeln!(self.sink, "{indent} let ptr = self.ptr() as *mut {name};")?;
364 writeln!(self.sink, "{indent} ((*(*ptr).vtbl).{method_name})(")?;
365 writeln!(self.sink, "{indent} ptr,")?;
366
367 self.indent_level += 3;
368 self.print_arg_names(&method)?;
369 self.indent_level -= 3;
370
371 writeln!(self.sink, "{indent} )")?;
372 writeln!(self.sink, "{indent} }}")?;
373 }
374
375 writeln!(self.sink, "{indent}}}")?;
376
377 writeln!(self.sink, "{indent}impl {name} {{")?;
378 writeln!(self.sink, "{indent} const fn make_vtbl<C, W, const OFFSET: isize>() -> {name}Vtbl")?;
379 writeln!(self.sink, "{indent} where")?;
380 writeln!(self.sink, "{indent} C: {name}Trait + ::com_scrape_types::Class,")?;
381 writeln!(self.sink, "{indent} W: ::com_scrape_types::Wrapper<C>,")?;
382 writeln!(self.sink, "{indent} {{")?;
383
384 #[rustfmt::skip]
385 for method in &record.virtual_methods {
386 let method_name = &method.name;
387
388 writeln!(self.sink, "{indent} unsafe extern \"system\" fn {method_name}<C, W, const OFFSET: isize>(")?;
389 writeln!(self.sink, "{indent} this: *mut {name},")?;
390
391 self.indent_level += 3;
392 self.print_args(method)?;
393 self.indent_level -= 3;
394
395 write!(self.sink, "{indent} )")?;
396 if let Type::Void = method.result_type {
397 } else {
398 write!(self.sink, " -> ")?;
399 self.print_type(&method.result_type)?;
400 }
401 writeln!(self.sink, "")?;
402 writeln!(self.sink, "{indent} where")?;
403 writeln!(self.sink, "{indent} C: {name}Trait + ::com_scrape_types::Class,")?;
404 writeln!(self.sink, "{indent} W: ::com_scrape_types::Wrapper<C>,")?;
405 writeln!(self.sink, "{indent} {{")?;
406 writeln!(self.sink, "{indent} let header_ptr = (this as *mut u8).offset(-OFFSET) as *mut Header<C>;")?;
407 writeln!(self.sink, "{indent} let ptr = <W as ::com_scrape_types::Wrapper<C>>::data_from_header(header_ptr);")?;
408 writeln!(self.sink, "{indent} (*ptr).{method_name}(")?;
409
410 self.indent_level += 4;
411 self.print_arg_names(method)?;
412 self.indent_level -= 4;
413
414 writeln!(self.sink, "{indent} )")?;
415 writeln!(self.sink, "{indent} }}")?;
416 };
417
418 writeln!(self.sink, "{indent} {name}Vtbl {{")?;
419 if let Some(base) = record.bases.first() {
420 let base_name = &base.name;
421 writeln!(self.sink, "{indent} base: {base_name}::make_vtbl::<C, W, OFFSET>(),")?;
422 }
423
424 for method in &record.virtual_methods {
425 let method_name = &method.name;
426 writeln!(
427 self.sink,
428 "{indent} {method_name}: {method_name}::<C, W, OFFSET>,"
429 )?;
430 }
431
432 writeln!(self.sink, "{indent} }}")?;
433
434 writeln!(self.sink, "{indent} }}")?;
435 writeln!(self.sink, "{indent}}}")?;
436
437 writeln!(self.sink, "{indent}unsafe impl<C, W, const OFFSET: isize> ::com_scrape_types::Construct<C, W, OFFSET> for {name}")?;
438 writeln!(self.sink, "{indent}where")?;
439 writeln!(
440 self.sink,
441 "{indent} C: {name}Trait + ::com_scrape_types::Class,"
442 )?;
443 writeln!(self.sink, "{indent} W: ::com_scrape_types::Wrapper<C>,")?;
444 writeln!(self.sink, "{indent}{{")?;
445 writeln!(self.sink, "{indent} const OBJ: Self = {name} {{")?;
446 writeln!(
447 self.sink,
448 "{indent} vtbl: &Self::make_vtbl::<C, W, OFFSET>(),"
449 )?;
450 writeln!(self.sink, "{indent} }};")?;
451 writeln!(self.sink, "{indent}}}")?;
452 }
453 }
454
455 Ok(())
456 }
457
458 fn print_args(&mut self, method: &Method) -> io::Result<()> {
459 let mut unnamed_counter = 0;
460
461 let indent = self.indent();
462
463 for arg in &method.arguments {
464 let arg_name = &arg.name;
465 if arg.name.is_empty() {
466 write!(self.sink, "{indent}_{unnamed_counter}: ")?;
467 unnamed_counter += 1;
468 } else if self.reserved.contains(&*arg.name) {
469 write!(self.sink, "{indent}r#{arg_name}: ")?;
470 } else {
471 write!(self.sink, "{indent}{arg_name}: ")?;
472 }
473 self.print_type(&arg.type_)?;
474 writeln!(self.sink, ",")?;
475 }
476
477 Ok(())
478 }
479
480 fn print_arg_names(&mut self, method: &Method) -> io::Result<()> {
481 let mut unnamed_counter = 0;
482
483 let indent = self.indent();
484
485 for arg in &method.arguments {
486 let arg_name = &arg.name;
487 if arg.name.is_empty() {
488 writeln!(self.sink, "{indent}_{unnamed_counter},")?;
489 unnamed_counter += 1;
490 } else if self.reserved.contains(&*arg.name) {
491 writeln!(self.sink, "{indent}r#{arg_name},")?;
492 } else {
493 writeln!(self.sink, "{indent}{arg_name},")?;
494 }
495 }
496
497 Ok(())
498 }
499
500 fn print_type(&mut self, type_: &Type) -> io::Result<()> {
501 match type_ {
502 Type::Void => write!(self.sink, "::std::ffi::c_void")?,
503 Type::Bool => write!(self.sink, "bool")?,
504 Type::Char => write!(self.sink, "::std::ffi::c_char")?,
505 Type::UChar => write!(self.sink, "::std::ffi::c_uchar")?,
506 Type::UShort => write!(self.sink, "::std::ffi::c_ushort")?,
507 Type::UInt => write!(self.sink, "::std::ffi::c_uint")?,
508 Type::ULong => write!(self.sink, "::std::ffi::c_ulong")?,
509 Type::ULongLong => write!(self.sink, "::std::ffi::c_ulonglong")?,
510 Type::SChar => write!(self.sink, "::std::ffi::c_schar")?,
511 Type::Short => write!(self.sink, "::std::ffi::c_short")?,
512 Type::Int => write!(self.sink, "::std::ffi::c_int")?,
513 Type::Long => write!(self.sink, "::std::ffi::c_long")?,
514 Type::LongLong => write!(self.sink, "::std::ffi::c_longlong")?,
515 Type::Unsigned(size) => match size {
516 1 => write!(self.sink, "u8")?,
517 2 => write!(self.sink, "u16")?,
518 4 => write!(self.sink, "u32")?,
519 8 => write!(self.sink, "u64")?,
520 _ => {
521 return Err(io::Error::new(
522 ErrorKind::Other,
523 format!("unexpected size {size} for unsigned integer"),
524 ))
525 }
526 },
527 Type::Signed(size) => match size {
528 1 => write!(self.sink, "i8")?,
529 2 => write!(self.sink, "i16")?,
530 4 => write!(self.sink, "i32")?,
531 8 => write!(self.sink, "i64")?,
532 _ => {
533 return Err(io::Error::new(
534 ErrorKind::Other,
535 format!("unexpected size {size} for signed integer"),
536 ))
537 }
538 },
539 Type::Float => write!(self.sink, "f32")?,
540 Type::Double => write!(self.sink, "f64")?,
541 Type::Pointer { is_const, pointee } | Type::Reference { is_const, pointee } => {
542 if *is_const {
543 write!(self.sink, "*const ")?;
544 } else {
545 write!(self.sink, "*mut ")?;
546 }
547 self.print_type(pointee)?;
548 }
549 Type::Record(name) => write!(self.sink, "{name}")?,
550 Type::UnnamedRecord(record) => {
551 let scope = self.unnamed_record_scope_mut();
552 let name = scope.next_name();
553 let mut record = record.clone();
554 record.name = name.clone();
555 scope.add_record(record);
556
557 write!(self.sink, "{name}")?;
558 }
559 Type::Typedef(name) => write!(self.sink, "{name}")?,
560 Type::Array(size, elem) => {
561 write!(self.sink, "[")?;
562 self.print_type(elem)?;
563 write!(self.sink, "; {size}]")?
564 }
565 }
566
567 Ok(())
568 }
569
570 fn push_unnamed_records(&mut self, prefix: &str) {
571 self.unnamed_records.push(UnnamedRecordScope {
572 prefix: prefix.to_string(),
573 records: Vec::new(),
574 });
575 }
576
577 fn unnamed_record_scope_mut(&mut self) -> &mut UnnamedRecordScope {
578 self.unnamed_records.last_mut().unwrap()
579 }
580
581 fn pop_unnamed_records(&mut self) -> io::Result<()> {
582 let unnamed_records = self.unnamed_records.pop().unwrap();
583
584 for record in unnamed_records.records {
585 self.print_record(&record)?;
586 }
587
588 Ok(())
589 }
590}