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}