codegen/
type_def.rs

1use std::fmt::{self, Write};
2
3use crate::bound::Bound;
4use crate::docs::Docs;
5use crate::formatter::{fmt_bounds, Formatter};
6
7use crate::r#type::Type;
8
9/// Defines a type definition.
10#[derive(Debug, Clone)]
11pub struct TypeDef {
12    pub ty: Type,
13    vis: Option<String>,
14    docs: Option<Docs>,
15    derive: Vec<String>,
16    allow: Vec<String>,
17    attributes: Vec<String>,
18    repr: Option<String>,
19    bounds: Vec<Bound>,
20    macros: Vec<String>,
21}
22
23impl TypeDef {
24    /// Return a structure definition with the provided name
25    pub fn new(name: impl Into<String>) -> Self {
26        TypeDef {
27            ty: Type::new(name),
28            vis: None,
29            docs: None,
30            derive: vec![],
31            allow: vec![],
32            attributes: vec![],
33            repr: None,
34            bounds: vec![],
35            macros: vec![],
36        }
37    }
38
39    pub fn vis(&mut self, vis: impl Into<String>) {
40        self.vis = Some(vis.into());
41    }
42
43    pub fn bound<T>(&mut self, name: impl Into<String>, ty: T)
44    where
45        T: Into<Type>,
46    {
47        self.bounds.push(Bound {
48            name: name.into(),
49            bound: vec![ty.into()],
50        });
51    }
52
53    pub fn r#macro(&mut self, r#macro: impl Into<String>) {
54        self.macros.push(r#macro.into());
55    }
56
57    pub fn attr(&mut self, attr: impl Into<String>) {
58        self.attributes.push(attr.into());
59    }
60
61    pub fn doc(&mut self, docs: impl Into<String>) {
62        self.docs = Some(Docs::new(docs.into()));
63    }
64
65    pub fn derive(&mut self, name: impl Into<String>) {
66        self.derive.push(name.into());
67    }
68
69    pub fn allow(&mut self, allow: impl Into<String>) {
70        self.allow.push(allow.into());
71    }
72
73    pub fn repr(&mut self, repr: impl Into<String>) {
74        self.repr = Some(repr.into());
75    }
76
77    pub fn fmt_head(
78        &self,
79        keyword: &str,
80        parents: &[Type],
81        fmt: &mut Formatter<'_>,
82    ) -> fmt::Result {
83        if let Some(ref docs) = self.docs {
84            docs.fmt(fmt)?;
85        }
86
87        self.fmt_allow(fmt)?;
88        self.fmt_derive(fmt)?;
89        self.fmt_repr(fmt)?;
90        self.fmt_attributes(fmt)?;
91        self.fmt_macros(fmt)?;
92
93        if let Some(ref vis) = self.vis {
94            write!(fmt, "{} ", vis)?;
95        }
96
97        write!(fmt, "{} ", keyword)?;
98        self.ty.fmt(fmt)?;
99
100        if !parents.is_empty() {
101            for (i, ty) in parents.iter().enumerate() {
102                if i == 0 {
103                    write!(fmt, ": ")?;
104                } else {
105                    write!(fmt, " + ")?;
106                }
107
108                ty.fmt(fmt)?;
109            }
110        }
111
112        fmt_bounds(&self.bounds, fmt)?;
113
114        Ok(())
115    }
116
117    fn fmt_attributes(&self, fmt: &mut Formatter) -> fmt::Result {
118        for attr in &self.attributes {
119            write!(fmt, "#[{}]\n", attr)?;
120        }
121
122        Ok(())
123    }
124
125    fn fmt_allow(&self, fmt: &mut Formatter) -> fmt::Result {
126        for allow in &self.allow {
127            write!(fmt, "#[allow({})]\n", allow)?;
128        }
129
130        Ok(())
131    }
132
133    fn fmt_repr(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
134        if let Some(ref repr) = self.repr {
135            write!(fmt, "#[repr({})]\n", repr)?;
136        }
137
138        Ok(())
139    }
140
141    fn fmt_derive(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
142        if !self.derive.is_empty() {
143            write!(fmt, "#[derive(")?;
144
145            for (i, name) in self.derive.iter().enumerate() {
146                if i != 0 {
147                    write!(fmt, ", ")?
148                }
149                write!(fmt, "{}", name)?;
150            }
151
152            write!(fmt, ")]\n")?;
153        }
154
155        Ok(())
156    }
157
158    fn fmt_macros(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
159        for m in self.macros.iter() {
160            write!(fmt, "{}\n", m)?;
161        }
162        Ok(())
163    }
164}