Skip to content

Commit

Permalink
Implement trait generics on impl-for
Browse files Browse the repository at this point in the history
  • Loading branch information
NightEule5 committed Nov 10, 2023
1 parent f89b2b6 commit 591db72
Showing 1 changed file with 32 additions and 5 deletions.
37 changes: 32 additions & 5 deletions src/generate/impl_for.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct ImplFor<'a, P: Parent> {
type_name: StringOrIdent,
trait_name: Option<StringOrIdent>,
lifetimes: Option<Vec<String>>,
generics: Option<Vec<String>>,
consts: Vec<StreamBuilder>,
custom_generic_constraints: Option<GenericConstraints>,
impl_types: Vec<StreamBuilder>,
Expand All @@ -32,6 +33,7 @@ impl<'a, P: Parent> ImplFor<'a, P> {
trait_name,
type_name,
lifetimes: None,
generics: Some(Vec::new()),
consts: Vec::new(),
custom_generic_constraints: None,
impl_types: Vec::new(),
Expand Down Expand Up @@ -77,6 +79,23 @@ impl<'a, P: Parent> ImplFor<'a, P> {
self
}

/// Add generic parameters to the trait.
///
/// `generator.impl_for("Foo").with_trait_generic(["Bar", "Baz"])` results in code like:
///
/// ```ignore
/// impl Foo<Bar, Baz> for <struct or enum> {
/// }
/// ```
pub fn with_trait_generics<ITER>(mut self, generics: ITER) -> Self
where
ITER: IntoIterator,
ITER::Item: Into<String>,
{
self.generics = Some(generics.into_iter().map(Into::into).collect());
self
}

/// Add a outer attribute to the trait implementation
pub fn impl_outer_attr(&mut self, attr: impl AsRef<str>) -> Result {
let mut builder = StreamBuilder::new();
Expand Down Expand Up @@ -259,16 +278,16 @@ impl<P: Parent> ImplFor<'_, P> {
if let Some(generics) = self.generator.generics() {
builder.append(generics.impl_generics_with_additional_lifetimes(lifetimes));
} else {
append_lifetimes(builder, lifetimes);
append_generics(builder, lifetimes, &[]);
}
} else if let Some(generics) = self.generator.generics() {
builder.append(generics.impl_generics());
}
if let Some(t) = &self.trait_name {
builder.push_parsed(t.to_string()).unwrap();
if let Some(lifetimes) = &self.lifetimes {
append_lifetimes(builder, lifetimes);
}
let lifetimes = self.lifetimes.as_deref().unwrap_or_default();
let generics = self.generics.as_deref().unwrap_or_default();
append_generics(builder, lifetimes, generics);
builder.ident_str("for");
}
builder.push_parsed(self.type_name.to_string()).unwrap();
Expand All @@ -283,10 +302,18 @@ impl<P: Parent> ImplFor<'_, P> {
}
}

fn append_lifetimes(builder: &mut StreamBuilder, lifetimes: &[String]) {
fn append_generics(builder: &mut StreamBuilder, lifetimes: &[String], generics: &[String]) {
for (idx, lt) in lifetimes.iter().enumerate() {
builder.punct(if idx == 0 { '<' } else { ',' });
builder.lifetime_str(lt);
}

for (idx, gen) in generics.iter().enumerate() {
if idx > 0 || !lifetimes.is_empty() {
builder.punct(',');
}
builder.ident_str(gen);
}

builder.punct('>');
}

0 comments on commit 591db72

Please sign in to comment.