rust_codegen/trait.rs
1use std::fmt::{self, Write};
2
3use crate::associated_type::AssociatedType;
4use crate::bound::Bound;
5use crate::formatter::{fmt_bound_rhs, Formatter};
6use crate::function::Function;
7use crate::type_def::TypeDef;
8
9use crate::r#type::Type;
10
11/// Defines a trait.
12#[allow(dead_code)]
13#[derive(Debug, Clone)]
14pub struct Trait {
15 /// The type definition of the trait.
16 type_def: TypeDef,
17 /// The trait's parent types.
18 parents: Vec<Type>,
19 /// The trait's associated types.
20 associated_tys: Vec<AssociatedType>,
21 /// The trait's functions.
22 fns: Vec<Function>,
23 /// The trait's macros.
24 macros: Vec<String>,
25}
26
27impl Trait {
28 /// Return a trait definition with the provided name.
29 ///
30 /// # Arguments
31 ///
32 /// * `name` - The name of the trait.
33 ///
34 /// # Examples
35 ///
36 /// ```
37 /// use rust_codegen::Trait;
38 ///
39 /// let foo_trait = Trait::new("Foo");
40 /// ```
41 pub fn new(name: &str) -> Self {
42 Trait {
43 type_def: TypeDef::new(name),
44 parents: vec![],
45 associated_tys: vec![],
46 fns: vec![],
47 macros: vec![],
48 }
49 }
50
51 /// Returns a reference to the type.
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use rust_codegen::Trait;
57 ///
58 /// let foo_trait = Trait::new("Foo");
59 /// println!("{:?}", foo_trait.ty());
60 /// ```
61 pub fn ty(&self) -> &Type {
62 &self.type_def.ty
63 }
64
65 /// Set the trait visibility.
66 ///
67 /// # Arguments
68 ///
69 /// * `vis` - The visibility to set for the trait.
70 ///
71 /// # Examples
72 ///
73 /// ```
74 /// use rust_codegen::Trait;
75 ///
76 /// let mut foo_trait = Trait::new("Foo");
77 /// foo_trait.vis("pub");
78 /// ```
79 pub fn vis(&mut self, vis: &str) -> &mut Self {
80 self.type_def.vis(vis);
81 self
82 }
83
84 /// Add a generic to the trait.
85 ///
86 /// # Examples
87 ///
88 /// ```
89 /// use rust_codegen::Trait;
90 ///
91 /// let mut foo_trait = Trait::new("Foo");
92 /// foo_trait.generic("T");
93 /// ```
94 pub fn generic(&mut self, name: &str) -> &mut Self {
95 self.type_def.ty.generic(name);
96 self
97 }
98
99 /// Add a `where` bound to the trait.
100 ///
101 /// # Arguments
102 ///
103 /// * `name` - The name of the bound.
104 /// * `ty` - The type of the bound.
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use rust_codegen::Trait;
110 ///
111 /// let mut foo_trait = Trait::new("Foo");
112 /// foo_trait.bound("A", "String");
113 /// ```
114 pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
115 where
116 T: Into<Type>,
117 {
118 self.type_def.bound(name, ty);
119 self
120 }
121
122 /// Add a macro to the trait def (e.g. `"#[async_trait]"`).
123 ///
124 /// # Arguments
125 ///
126 /// * `r#macro` - The macro to add.
127 ///
128 /// # Examples
129 ///
130 /// ```
131 /// use rust_codegen::Trait;
132 ///
133 /// let mut foo_trait = Trait::new("Foo");
134 /// foo_trait.r#macro("async_trait");
135 /// ```
136 pub fn r#macro(&mut self, r#macro: &str) -> &mut Self {
137 self.type_def.r#macro(r#macro);
138 self
139 }
140
141 /// Add a parent trait.
142 ///
143 /// # Arguments
144 ///
145 /// * `ty` - The type of the parent trait.
146 ///
147 /// # Examples
148 ///
149 /// ```
150 /// use rust_codegen::Trait;
151 ///
152 /// let mut foo_trait = Trait::new("Foo");
153 /// foo_trait.parent("Bar");
154 /// ```
155 pub fn parent<T>(&mut self, ty: T) -> &mut Self
156 where
157 T: Into<Type>,
158 {
159 self.parents.push(ty.into());
160 self
161 }
162
163 /// Set the trait documentation.
164 ///
165 /// # Arguments
166 ///
167 /// * `docs` - The documentation for the trait.
168 ///
169 /// # Examples
170 ///
171 /// ```
172 /// use rust_codegen::Trait;
173 ///
174 /// let mut foo_trait = Trait::new("Foo");
175 /// foo_trait.doc("Sample trait documentation.");
176 /// ```
177 pub fn doc(&mut self, docs: &str) -> &mut Self {
178 self.type_def.doc(docs);
179 self
180 }
181
182 /// Add an associated type. Returns a mutable reference to the new
183 /// associated type for futher configuration.
184 ///
185 /// # Arguments
186 ///
187 /// * `name` - The name of the associated type.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// use rust_codegen::Trait;
193 ///
194 /// let mut foo_trait = Trait::new("Foo");
195 /// foo_trait.associated_type("A");
196 /// ```
197 pub fn associated_type(&mut self, name: &str) -> &mut AssociatedType {
198 self.associated_tys.push(AssociatedType(Bound {
199 name: name.to_string(),
200 bound: vec![],
201 }));
202
203 self.associated_tys.last_mut().unwrap()
204 }
205
206 /// Push a new function definition, returning a mutable reference to it.
207 ///
208 /// # Arguments
209 ///
210 /// * `name` - The name of the function.
211 ///
212 /// # Examples
213 ///
214 /// ```
215 /// use rust_codegen::Trait;
216 ///
217 /// let mut foo_trait = Trait::new("Foo");
218 /// foo_trait.new_fn("bar_fn");
219 /// ```
220 pub fn new_fn(&mut self, name: &str) -> &mut Function {
221 let mut func = Function::new(name);
222 func.body = None;
223
224 self.push_fn(func);
225 self.fns.last_mut().unwrap()
226 }
227
228 /// Push a function definition.
229 ///
230 /// # Arguments
231 ///
232 /// * `item` - The function to add.
233 ///
234 /// # Examples
235 ///
236 /// ```
237 /// use rust_codegen::{Function,Trait};
238 ///
239 /// let mut foo_trait = Trait::new("Foo");
240 /// let mut bar_fn = Function::new("bar_fn");
241 ///
242 /// foo_trait.push_fn(bar_fn);
243 /// ```
244 pub fn push_fn(&mut self, item: Function) -> &mut Self {
245 self.fns.push(item);
246 self
247 }
248
249 /// Formats the scope using the given formatter.
250 ///
251 /// # Arguments
252 ///
253 /// * `fmt` - The formatter to use.
254 ///
255 /// # Examples
256 ///
257 /// ```
258 /// use rust_codegen::{Formatter,Trait};
259 ///
260 /// let mut dest = String::new();
261 /// let mut fmt = Formatter::new(&mut dest);
262 ///
263 /// let mut foo_trait = Trait::new("Foo");
264 /// foo_trait.fmt(&mut fmt);
265 /// ```
266 pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
267 self.type_def.fmt_head("trait", &self.parents, fmt)?;
268
269 fmt.block(|fmt| {
270 let assoc = &self.associated_tys;
271
272 // format associated types
273 if !assoc.is_empty() {
274 for ty in assoc {
275 let ty = &ty.0;
276
277 write!(fmt, "type {}", ty.name)?;
278
279 if !ty.bound.is_empty() {
280 write!(fmt, ": ")?;
281 fmt_bound_rhs(&ty.bound, fmt)?;
282 }
283
284 write!(fmt, ";\n")?;
285 }
286 }
287
288 for (i, func) in self.fns.iter().enumerate() {
289 if i != 0 || !assoc.is_empty() {
290 write!(fmt, "\n")?;
291 }
292
293 func.fmt(true, fmt)?;
294 }
295
296 Ok(())
297 })
298 }
299}