interoptopus_backend_c/
docs.rs

1use crate::CWriter;
2use interoptopus::indented;
3use interoptopus::lang::c::{CType, Function};
4use interoptopus::util::sort_types_by_dependencies;
5use interoptopus::writer::IndentWriter;
6use interoptopus::{Error, Inventory};
7use std::fs::File;
8use std::path::Path;
9
10pub struct DocGenerator<W> {
11    inventory: Inventory,
12    c_writer: W,
13}
14
15impl<W: CWriter> DocGenerator<W> {
16    pub fn new(inventory: Inventory, w: W) -> Self {
17        Self { inventory, c_writer: w }
18    }
19
20    pub fn inventory(&self) -> &Inventory {
21        &self.inventory
22    }
23
24    pub fn write_types(&self, w: &mut IndentWriter) -> Result<(), Error> {
25        indented!(w, r#"# Types "#)?;
26
27        let mut known_function_pointers = vec![];
28
29        for the_type in &sort_types_by_dependencies(self.inventory().ctypes().to_vec()) {
30            self.write_type_definition(w, the_type, &mut known_function_pointers)?;
31        }
32
33        Ok(())
34    }
35
36    pub fn write_type_definition(&self, w: &mut IndentWriter, the_type: &CType, known_function_pointers: &mut Vec<String>) -> Result<(), Error> {
37        let meta = match the_type {
38            CType::Primitive(_) => return Ok(()),
39            CType::Array(_) => return Ok(()),
40            CType::Enum(e) => e.meta(),
41            CType::Opaque(o) => o.meta(),
42            CType::Composite(c) => c.meta(),
43            CType::FnPointer(_) => return Ok(()),
44            CType::ReadPointer(_) => return Ok(()),
45            CType::ReadWritePointer(_) => return Ok(()),
46            CType::Pattern(_) => return Ok(()),
47        };
48
49        w.newline()?;
50        w.newline()?;
51
52        indented!(w, r#"## {} "#, the_type.name_within_lib())?;
53        w.newline()?;
54
55        for line in meta.documentation().lines() {
56            indented!(w, r#"{}"#, line.trim())?;
57            w.newline()?;
58        }
59
60        indented!(w, r#"```"#)?;
61        self.c_writer.write_type_definition(w, the_type, known_function_pointers)?;
62        indented!(w, r#"```"#)?;
63
64        Ok(())
65    }
66
67    pub fn write_functions(&self, w: &mut IndentWriter) -> Result<(), Error> {
68        indented!(w, r#"# Functions "#)?;
69
70        for the_type in self.inventory().functions() {
71            self.write_function(w, the_type)?;
72        }
73
74        Ok(())
75    }
76
77    fn write_function(&self, w: &mut IndentWriter, function: &Function) -> Result<(), Error> {
78        indented!(w, r#"## {} "#, function.name())?;
79
80        for line in function.meta().documentation().lines() {
81            if line.trim().starts_with('#') {
82                write!(w.writer(), "##")?;
83            }
84            indented!(w, r#"{}"#, line.trim())?;
85            w.newline()?;
86        }
87
88        indented!(w, r#"```"#)?;
89        self.c_writer.write_function_declaration(w, function, 80)?;
90        indented!(w, r#"```"#)?;
91
92        w.newline()?;
93
94        Ok(())
95    }
96
97    pub fn write_to(&self, w: &mut IndentWriter) -> Result<(), Error> {
98        self.write_types(w)?;
99        self.write_functions(w)?;
100
101        w.newline()?;
102
103        Ok(())
104    }
105
106    pub fn write_file<P: AsRef<Path>>(&self, file_name: P) -> Result<(), Error> {
107        let mut file = File::create(file_name)?;
108        let mut writer = IndentWriter::new(&mut file);
109
110        self.write_to(&mut writer)
111    }
112}