Skip to content

Commit

Permalink
Allow passing arbitrary attributes to segments
Browse files Browse the repository at this point in the history
  • Loading branch information
Kobzol committed Dec 14, 2023
1 parent e19bbe7 commit 67f59a4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 8 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Dev
- Allow passing arbitrary attributes to delegation segments:
```rust
impl Foo {
delegate! {
#[inline(always)]
to self.0 { ... }
}
}
```

# 0.11.0 (4. 12. 2023)
- Allow delegating an associated function (not just a method).
```rust
Expand Down
32 changes: 24 additions & 8 deletions src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,17 +225,15 @@ pub struct SegmentAttributes {
pub expressions: Vec<ReturnExpression>,
pub generate_await: Option<bool>,
pub target_trait: Option<TypePath>,
pub other_attrs: Vec<Attribute>,
}

pub fn parse_segment_attributes(attrs: &[Attribute]) -> SegmentAttributes {
let mut expressions: Vec<ReturnExpression> = vec![];
let mut generate_await: Option<bool> = None;
let mut target_trait: Option<TraitTarget> = None;

let (parsed, mut other) = parse_attributes(attrs);
if other.next().is_some() {
panic!("Only return expression attributes can be used on a segment (into, try_into, unwrap or await).");
}
let (parsed, other) = parse_attributes(attrs);

for attribute in parsed {
match attribute {
Expand All @@ -261,23 +259,31 @@ pub fn parse_segment_attributes(attrs: &[Attribute]) -> SegmentAttributes {
expressions,
generate_await,
target_trait: target_trait.map(|t| t.type_path),
other_attrs: other.cloned().collect::<Vec<_>>(),
}
}

/// Applies default values from the segment and adds them to the method attributes.
pub fn combine_attributes<'a>(
mut method_attrs: MethodAttributes<'a>,
segment_attrs: &SegmentAttributes,
segment_attrs: &'a SegmentAttributes,
) -> MethodAttributes<'a> {
let SegmentAttributes {
expressions,
generate_await,
target_trait,
other_attrs,
} = segment_attrs;

if method_attrs.generate_await.is_none() {
method_attrs.generate_await = segment_attrs.generate_await;
method_attrs.generate_await = *generate_await;
}

if method_attrs.target_trait.is_none() {
method_attrs.target_trait = segment_attrs.target_trait.clone();
method_attrs.target_trait = target_trait.clone();
}

for expr in &segment_attrs.expressions {
for expr in expressions {
match expr {
ReturnExpression::Into(path) => {
if !method_attrs
Expand All @@ -294,5 +300,15 @@ pub fn combine_attributes<'a>(
}
}

for other_attr in other_attrs {
if !method_attrs
.attributes
.iter()
.any(|attr| attr.path().get_ident() != other_attr.path().get_ident())
{
method_attrs.attributes.push(other_attr);
}
}

method_attrs
}
25 changes: 25 additions & 0 deletions tests/segment_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,28 @@ fn test_segment_through_trait() {
assert_eq!(bar.f(), 0);
assert_eq!(bar.f2(), 1);
}

#[test]
fn test_segment_inline() {
struct Foo;

impl Foo {
fn f(&self) -> u32 {
0
}
}

struct Bar(Foo);

impl Bar {
delegate! {
#[inline(always)]
to self.0 {
fn f(&self) -> u32;
}
}
}

let bar = Bar(Foo);
assert_eq!(bar.f(), 0);
}

0 comments on commit 67f59a4

Please sign in to comment.