trans_gen/gens/markdown/
mod.rs

1use super::*;
2
3fn conv(name: &str) -> String {
4    name.to_owned()
5}
6
7fn type_name(schema: &Schema) -> String {
8    match schema {
9        Schema::Bool => "boolean".to_owned(),
10        Schema::Int32 => "int32".to_owned(),
11        Schema::Int64 => "int64".to_owned(),
12        Schema::Float32 => "float32".to_owned(),
13        Schema::Float64 => "float64".to_owned(),
14        Schema::String => "string".to_owned(),
15        Schema::Option(inner) => format!("Option<{}>", type_name(inner)),
16        Schema::Struct(Struct { name, .. }) => name.camel_case(conv),
17        Schema::OneOf { base_name, .. } => base_name.camel_case(conv),
18        Schema::Vec(inner) => format!("[{}]", type_name(inner)),
19        Schema::Map(key_type, value_type) => {
20            format!("Map<{} -> {}>", type_name(key_type), type_name(value_type))
21        }
22        Schema::Enum { base_name, .. } => base_name.camel_case(conv),
23    }
24}
25
26#[derive(Debug, Serialize, Deserialize, Clone)]
27pub struct Options {
28    pub language: String,
29    pub require_docs: bool,
30}
31
32impl Options {
33    fn get_doc<'a>(&self, documentation: &'a Documentation, error_msg: &str) -> &'a str {
34        if let Some(text) = documentation.get(&self.language) {
35            text
36        } else if self.require_docs {
37            panic!("{}", error_msg);
38        } else {
39            "TODO: document"
40        }
41    }
42}
43
44impl Default for Options {
45    fn default() -> Self {
46        Self {
47            language: "en".to_owned(),
48            require_docs: false,
49        }
50    }
51}
52
53pub struct Generator {
54    parts: Vec<String>,
55    options: Options,
56}
57impl crate::Generator for Generator {
58    type Options = Options;
59    fn new(_name: &str, _version: &str, options: Options) -> Self {
60        Self {
61            parts: Vec::new(),
62            options,
63        }
64    }
65    fn result(self) -> GenResult {
66        GenResult {
67            files: vec![File {
68                path: "doc.md".to_owned(),
69                content: self.parts.join("\n"),
70            }],
71        }
72    }
73    fn add_only(&mut self, schema: &Schema) {
74        let language = &self.options.language;
75        match schema {
76            Schema::Struct(Struct {
77                documentation,
78                name,
79                fields,
80                magic: _,
81            }) => {
82                let mut content = Writer::new();
83                {
84                    let content = &mut content;
85                    writeln!(content, "## `{}`", name.camel_case(conv)).unwrap();
86                    writeln!(content).unwrap();
87                    writeln!(
88                        content,
89                        "{}",
90                        self.options.get_doc(
91                            documentation,
92                            &format!("{:?} not documented in {:?}", name, language)
93                        )
94                    )
95                    .unwrap();
96                    writeln!(content).unwrap();
97                    writeln!(
98                        content,
99                        "{}",
100                        match language.as_str() {
101                            "ru" => "Поля:",
102                            "en" | _ => "Fields:",
103                        }
104                    )
105                    .unwrap();
106                    writeln!(content).unwrap();
107                    for field in fields {
108                        writeln!(
109                            content,
110                            "- `{}`: `{}` - {}",
111                            field.name.snake_case(conv),
112                            type_name(&field.schema),
113                            self.options.get_doc(
114                                &field.documentation,
115                                &format!(
116                                    "{:?}::{:?} not documented in {:?}",
117                                    name, field.name, language
118                                )
119                            ),
120                        )
121                        .unwrap();
122                    }
123                }
124                self.parts.push(content.get());
125            }
126            Schema::OneOf {
127                documentation,
128                base_name,
129                variants,
130            } => {
131                let mut content = Writer::new();
132                {
133                    let content = &mut content;
134                    writeln!(content, "## `{}`", base_name.camel_case(conv)).unwrap();
135                    writeln!(content).unwrap();
136                    writeln!(
137                        content,
138                        "{}",
139                        self.options.get_doc(
140                            documentation,
141                            &format!("{:?} not documented in {:?}", base_name, language)
142                        )
143                    )
144                    .unwrap();
145                    writeln!(content).unwrap();
146                    writeln!(
147                        content,
148                        "{}",
149                        match language.as_str() {
150                            "ru" => "Варианты:",
151                            "en" | _ => "One of:",
152                        }
153                    )
154                    .unwrap();
155                    writeln!(content).unwrap();
156                    for variant in variants {
157                        writeln!(
158                            content,
159                            "- `{}` - {}",
160                            variant.name.camel_case(conv),
161                            self.options.get_doc(
162                                &variant.documentation,
163                                &format!(
164                                    "{:?}::{:?} not documented in {:?}",
165                                    base_name, variant.name, language
166                                )
167                            ),
168                        )
169                        .unwrap();
170                        writeln!(content).unwrap();
171                        content.inc_ident();
172                        if variant.fields.is_empty() {
173                            writeln!(
174                                content,
175                                "{}",
176                                match language.as_str() {
177                                    "ru" => "Нет полей",
178                                    "en" | _ => "No fields",
179                                }
180                            )
181                            .unwrap();
182                        } else {
183                            writeln!(
184                                content,
185                                "{}",
186                                match language.as_str() {
187                                    "ru" => "Поля:",
188                                    "en" | _ => "Fields:",
189                                }
190                            )
191                            .unwrap();
192                        }
193                        writeln!(content).unwrap();
194                        for field in &variant.fields {
195                            writeln!(
196                                content,
197                                "- `{}`: `{}` - {}",
198                                field.name.snake_case(conv),
199                                type_name(&field.schema),
200                                self.options.get_doc(
201                                    &field.documentation,
202                                    &format!(
203                                        "{:?}::{:?}::{:?} not documented in {:?}",
204                                        base_name, variant.name, field.name, language
205                                    )
206                                ),
207                            )
208                            .unwrap();
209                        }
210                        content.dec_ident();
211                    }
212                }
213                self.parts.push(content.get());
214            }
215            Schema::Enum {
216                documentation,
217                base_name,
218                variants,
219            } => {
220                let mut content = Writer::new();
221                {
222                    let content = &mut content;
223                    writeln!(content, "## `{}`", base_name.camel_case(conv)).unwrap();
224                    writeln!(content).unwrap();
225                    writeln!(
226                        content,
227                        "{}",
228                        self.options.get_doc(
229                            documentation,
230                            &format!("{:?} not documented in {:?}", base_name, language)
231                        ),
232                    )
233                    .unwrap();
234                    writeln!(content).unwrap();
235                    writeln!(
236                        content,
237                        "{}",
238                        match language.as_str() {
239                            "ru" => "Варианты:",
240                            "en" | _ => "Variants:",
241                        }
242                    )
243                    .unwrap();
244                    writeln!(content).unwrap();
245                    for variant in variants {
246                        writeln!(
247                            content,
248                            "- `{}` - {}",
249                            variant.name.camel_case(conv),
250                            self.options.get_doc(
251                                &variant.documentation,
252                                &format!(
253                                    "{:?}::{:?} not documented in {:?}",
254                                    base_name, variant.name, language
255                                )
256                            ),
257                        )
258                        .unwrap();
259                    }
260                }
261                self.parts.push(content.get());
262            }
263            Schema::Bool
264            | Schema::Int32
265            | Schema::Int64
266            | Schema::Float32
267            | Schema::Float64
268            | Schema::String
269            | Schema::Option(_)
270            | Schema::Vec(_)
271            | Schema::Map(_, _) => {}
272        }
273    }
274}