use serde::Serialize;
use crate::traits::SrcCode;
use crate::{FunctionSignature, Generic, Generics, AssociatedTypeDeclaration};
use tera::{Context, Tera};
#[derive(Serialize, Default, Clone)]
pub struct Trait {
pub(crate) name: String,
pub(crate) is_pub: bool,
generics: Generics,
signatures: Vec<FunctionSignature>,
associated_types: Vec<AssociatedTypeDeclaration>
}
impl Trait {
pub fn new<S: ToString>(name: S) -> Self {
let mut t = Self::default();
t.name = name.to_string();
t
}
pub fn add_signature(&mut self, signature: FunctionSignature) -> &mut Self {
self.signatures.push(signature);
self
}
pub fn set_is_pub(&mut self, is_pub: bool) -> &mut Self {
self.is_pub = is_pub;
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: AssociatedTypeDeclaration) -> &mut Self {
self.associated_types.push(associated_type);
self
}
}
impl SrcCode for Trait {
fn generate(&self) -> String {
let template = r#"
{% if self.is_pub %}pub {% endif %}trait {{ self.name }}{% if has_generics %}{{ generic_bounds }}{% endif %}
{
{% for associated_type in associated_types %}{{ associated_type }}{% endfor %}
{% for signature in signatures %}{{ signature }};{% endfor %}
}
"#;
let mut context = Context::new();
context.insert("self", &self);
context.insert(
"signatures",
&self
.signatures
.iter()
.map(|s| s.generate())
.collect::<Vec<String>>(),
);
context.insert(
"associated_types",
&self
.associated_types
.iter()
.map(|t| t.generate())
.collect::<Vec<String>>(),
);
context.insert("has_generics", &!self.generics.is_empty());
context.insert("generic_bounds", &self.generics.generate());
Tera::one_off(template, &context, false).unwrap()
}
}