proffer/
impl_gen.rs

1//!
2//! Create `impl` blocks for functions, traits, and other objects.
3//!
4
5use serde::Serialize;
6
7use crate::traits::SrcCode;
8use crate::{Function, Generic, Generics, Trait, AssociatedTypeDefinition};
9use tera::{Context, Tera};
10
11/// Represents an `impl` block
12#[derive(Serialize, Default, Clone)]
13pub struct Impl {
14    generics: Generics,
15    impl_trait: Option<Trait>,
16    functions: Vec<Function>,
17    obj_name: String,
18    associated_types: Vec<AssociatedTypeDefinition>
19}
20
21impl Impl {
22    /// Create a new impl block
23    pub fn new<S: ToString>(obj_name: S) -> Self {
24        let mut mpl = Self::default();
25        mpl.obj_name = obj_name.to_string();
26        mpl
27    }
28
29    /// Set if this `impl` is implementing a `Trait` for an object.
30    pub fn set_impl_trait(&mut self, impl_trait: Option<Trait>) -> &mut Self {
31        self.impl_trait = impl_trait;
32        self
33    }
34
35    /// Add a function to this `Impl` block
36    pub fn add_function(&mut self, func: Function) -> &mut Self {
37        self.functions.push(func);
38        self
39    }
40
41    /// Add a generic to this `Impl` block
42    pub fn add_generic(&mut self, generic: Generic) -> &mut Self {
43        self.generics.add_generic(generic);
44        self
45    }
46
47    /// Add a associated type to this `Impl` block
48    pub fn add_associated_type(&mut self, associated_type: AssociatedTypeDefinition) -> &mut Self {
49        self.associated_types.push(associated_type);
50        self
51    }
52}
53
54impl SrcCode for Impl {
55    fn generate(&self) -> String {
56        let template = r#"
57            impl{% if has_generics %}<{{ generic_keys | join(sep=", ") }}>{% endif %} {% if has_trait %}{{ trait_name }} for {% endif %}{{ self.obj_name }}{% if has_generics %}<{{ generic_keys | join(sep=", ") }}>{% endif %}
58                {% if has_generics %}
59                where
60                    {% for generic in generics %}{{ generic.generic }}: {{ generic.traits | join(sep=" + ") }},
61                    {% endfor %}
62                {% endif %}
63            {
64                {% for associated_type in associated_types %}{{ associated_type }}{% endfor %}
65                {% for function in functions %}
66                    {{ function }}
67                {% endfor %}
68            }
69        "#;
70        let mut context = Context::new();
71        context.insert("self", &self);
72        context.insert("has_trait", &self.impl_trait.is_some());
73        context.insert(
74            "trait_name",
75            &self
76                .impl_trait
77                .as_ref()
78                .map(|t| t.name.clone())
79                .unwrap_or("".to_string()),
80        );
81        context.insert("has_generics", &!self.generics.is_empty());
82        context.insert("generics", &self.generics.generics);
83        context.insert(
84            "generic_keys",
85            &self
86                .generics
87                .generics
88                .iter()
89                .map(|g| g.generic.clone())
90                .collect::<Vec<String>>(),
91        );
92        context.insert(
93            "functions",
94            &self
95                .functions
96                .iter()
97                .map(|f| f.generate())
98                .collect::<Vec<String>>(),
99        );
100        context.insert(
101            "associated_types",
102            &self
103                .associated_types
104                .iter()
105                .map(|a| a.generate())
106                .collect::<Vec<String>>(),
107        );
108        Tera::one_off(template, &context, false).unwrap()
109    }
110}