com_scrape/
print.rs

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}