Skip to content

Commit

Permalink
Merge pull request #59 from dewert99/single_field_target
Browse files Browse the repository at this point in the history
Allow specifying a target for single field structs
  • Loading branch information
dewert99 authored Jun 19, 2024
2 parents 6164831 + 3915bcd commit d537cfe
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
6 changes: 3 additions & 3 deletions ambassador/src/delegate_shared.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::util::{error, process_results};
use crate::util::error;
use itertools::Itertools;
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::ToTokens;
Expand Down Expand Up @@ -101,8 +101,8 @@ pub(super) fn delegate_macro<I>(
}

let iter = delegate_attributes.map(|attr| delegate_single(input, attr));
let res = process_results(iter, |iter| iter.flatten().collect());
res.unwrap_or_else(|x| x.to_compile_error())
iter.flat_map(|x| x.unwrap_or_else(|err| err.to_compile_error()))
.collect()
}

pub(super) fn trait_info(trait_path_full: &syn::Path) -> Result<(&Ident, impl ToTokens + '_)> {
Expand Down
26 changes: 16 additions & 10 deletions ambassador/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,22 @@ impl delegate_shared::DelegateTarget for DelegateTarget {

type DelegateArgs = delegate_shared::DelegateArgs<DelegateTarget>;

fn unknown_field<X>(target: &syn::Member) -> Result<X> {
error!(
target.span(),
"Unknown field specified as \"target\" value in #[delegate] attribute"
)
}

/// Select the correct field_ident based on the `target`.
pub fn get_field<'a>(
fn get_field<'a>(
target: &syn::Member,
field_idents: &'a [(syn::Member, syn::Type)],
) -> Result<&'a (syn::Member, syn::Type)> {
let field = field_idents.iter().find(|n| n.0 == *target);
match field {
Some(field) => Ok(field),
None => error!(
target.span(),
"Unknown field specified as \"target\" value in #[delegate] attribute"
),
None => unknown_field(target),
}
}

Expand Down Expand Up @@ -207,11 +211,13 @@ fn delegate_single_attr(
}
}
}
(Field(field), SingleFieldStruct {..}) => return error!(
field.span(),
"\"target\" value on #[delegate] attribute can not be specified for structs with a single field"
),
(TrgNone, SingleFieldStruct {field_ident, field_type}) => {
(trg, SingleFieldStruct {field_ident, field_type}) => {
match trg {
Field(f) if f != field_ident => {
unknown_field(f)?;
}
_ => {}
}
if !args.inhibit_automatic_where_clause {
add_auto_where_clause(&mut where_clause, &trait_path_full, field_type);
}
Expand Down
5 changes: 1 addition & 4 deletions ambassador/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,5 @@ pub fn delegatable_trait_remote(_attr: TokenStream, item: TokenStream) -> TokenS
let original_item: syn::ItemTrait = syn::parse(item).unwrap();
let register_trait = build_register_trait(&original_item);

let expanded = quote! {
#register_trait
};
TokenStream::from(expanded)
TokenStream::from(register_trait)
}
27 changes: 27 additions & 0 deletions ambassador/tests/run-pass/struct_single_field_target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
extern crate ambassador;

use ambassador::{delegatable_trait, Delegate};

#[delegatable_trait]
pub trait Shout {
fn shout(&self, input: &str) -> String;
}

pub struct Cat;

impl Shout for Cat {
fn shout(&self, input: &str) -> String {
format!("{} - meow!", input)
}
}

#[derive(Delegate)]
#[delegate(Shout, target = "inner")]
pub struct WrappedCat {
inner: Cat,
}

pub fn main() {
let foo_animal = WrappedCat { inner: Cat };
println!("{}", foo_animal.shout("BAR"));
}

0 comments on commit d537cfe

Please sign in to comment.