use serde::Serialize;
use crate::traits::SrcCode;
use crate::{Function, Generic, Generics, Trait, AssociatedTypeDefinition};
use tera::{Context, Tera};
#[derive(Serialize, Default, Clone)]
pub struct Impl {
generics: Generics,
impl_trait: Option<Trait>,
functions: Vec<Function>,
obj_name: String,
associated_types: Vec<AssociatedTypeDefinition>
}
impl Impl {
pub fn new<S: ToString>(obj_name: S) -> Self {
let mut mpl = Self::default();
mpl.obj_name = obj_name.to_string();
mpl
}
pub fn set_impl_trait(&mut self, impl_trait: Option<Trait>) -> &mut Self {
self.impl_trait = impl_trait;
self
}
pub fn add_function(&mut self, func: Function) -> &mut Self {
self.functions.push(func);
self
}
pub fn add_generic(&mut self, generic: Generic) -> &mut Self {
self.generics.add_generic(generic);
self
}
pub fn add_associated_type(&mut self, associated_type: AssociatedTypeDefinition) -> &mut Self {
self.associated_types.push(associated_type);
self
}
}
impl SrcCode for Impl {
fn generate(&self) -> String {
let template = r#"
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 %}
{% if has_generics %}
where
{% for generic in generics %}{{ generic.generic }}: {{ generic.traits | join(sep=" + ") }},
{% endfor %}
{% endif %}
{
{% for associated_type in associated_types %}{{ associated_type }}{% endfor %}
{% for function in functions %}
{{ function }}
{% endfor %}
}
"#;
let mut context = Context::new();
context.insert("self", &self);
context.insert("has_trait", &self.impl_trait.is_some());
context.insert(
"trait_name",
&self
.impl_trait
.as_ref()
.map(|t| t.name.clone())
.unwrap_or("".to_string()),
);
context.insert("has_generics", &!self.generics.is_empty());
context.insert("generics", &self.generics.generics);
context.insert(
"generic_keys",
&self
.generics
.generics
.iter()
.map(|g| g.generic.clone())
.collect::<Vec<String>>(),
);
context.insert(
"functions",
&self
.functions
.iter()
.map(|f| f.generate())
.collect::<Vec<String>>(),
);
context.insert(
"associated_types",
&self
.associated_types
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &context, false).unwrap()
}
}