cargo_wiki/generators/
struct_gen.rs

1use crate::generators::generic_gen::GenericGenerator;
2use crate::generators::type_gen::TypeGenerator;
3use crate::generators::visibility_gen::VisibilityGenerator;
4use crate::generators::{ExternalCrates, Generator, Index, Paths};
5use anyhow::Result;
6use rustdoc_types::{Item, ItemEnum, StructKind};
7
8pub struct StructGenerator;
9
10impl Generator for StructGenerator {
11    /// Generate Code Syntax for `Struct`. See [Template.html](https://github.com/AS1100K/cargo-wiki/blob/main/Template.md#struct-syntax-block)
12    /// for more info.
13    fn generate_syntax(
14        item: &Item,
15        index: &Index,
16        paths: &Paths,
17        external_crates: &ExternalCrates,
18    ) -> Result<String> {
19        if let ItemEnum::Struct(rustdoc_types::Struct {
20            kind,
21            generics,
22            impls,
23        }) = &item.inner
24        {
25            let mut syntax = String::from("```rust\n");
26            syntax.push_str(&VisibilityGenerator::generate_visibility(&item.visibility));
27            syntax.push_str("struct ");
28
29            if let Some(struct_name) = &item.name {
30                let (generic_params, where_predicates) =
31                    GenericGenerator::generate_generics(&generics)?;
32                syntax.push_str(struct_name);
33                syntax.push_str(&generic_params);
34                syntax.push_str(&where_predicates);
35
36                match kind {
37                    StructKind::Unit => {
38                        syntax.push_str(";");
39                    }
40                    StructKind::Tuple(unnamed_fields) => {
41                        syntax.push_str("(");
42                        for (i, unnamed_field) in unnamed_fields.iter().enumerate() {
43                            if i != 0 {
44                                syntax.push_str(", ");
45                            }
46
47                            if let Some(field_id) = unnamed_field {
48                                let Some(field_item) = index.get(field_id) else {
49                                    return Err(anyhow::Error::msg(format!(
50                                        "Failed to find item with id: {} in index",
51                                        field_id.0
52                                    )));
53                                };
54                                let ItemEnum::StructField(type_) = &field_item.inner else {
55                                    return Err(anyhow::Error::msg(format!("inner can't be anything other than `StructField in index id: {}", field_id.0)));
56                                };
57                                syntax.push_str(&TypeGenerator::type_to_string(type_));
58                            } else {
59                                syntax.push_str("/* private field */");
60                            }
61                        }
62                        syntax.push_str(")");
63                    }
64                    StructKind::Plain {
65                        fields,
66                        has_stripped_fields,
67                    } => {
68                        if where_predicates.is_empty() {
69                            syntax.push_str(" {\n");
70                        } else {
71                            syntax.push_str("\n{")
72                        }
73
74                        for field_id in fields {
75                            let Some(field_item) = index.get(field_id) else {
76                                return Err(anyhow::Error::msg(format!(
77                                    "Failed to find item with id: {} in index",
78                                    field_id.0
79                                )));
80                            };
81                            let Some(field_name) = &field_item.name else {
82                                return Err(anyhow::Error::msg(format!(
83                                    "Failed to find name of struct field with id: {} in index",
84                                    field_id.0
85                                )));
86                            };
87                            let ItemEnum::StructField(type_) = &field_item.inner else {
88                                return Err(anyhow::Error::msg(format!("inner can't be anything other than `StructField in index id: {}", field_id.0)));
89                            };
90
91                            syntax.push_str("\t");
92                            syntax.push_str(&VisibilityGenerator::generate_visibility(
93                                &field_item.visibility,
94                            ));
95                            syntax.push_str(field_name);
96                            syntax.push_str(": ");
97                            syntax.push_str(&TypeGenerator::type_to_string(type_));
98                            syntax.push_str(",\n");
99                        }
100
101                        if *has_stripped_fields {
102                            syntax.push_str("\t/* private fields */\n");
103                        }
104                        syntax.push_str("}");
105                    }
106                }
107                syntax.push_str("\n```\n");
108                return Ok(syntax);
109            }
110            return Err(anyhow::Error::msg("Can't document a struct with no name"));
111        }
112        Err(anyhow::Error::msg(
113            "Umm... Only Item with inner ItemEnum::Struct to be used here",
114        ))
115    }
116}