diff --git a/zbus/src/fdo/properties.rs b/zbus/src/fdo/properties.rs index 258e06ae4..d493d7b78 100644 --- a/zbus/src/fdo/properties.rs +++ b/zbus/src/fdo/properties.rs @@ -62,7 +62,7 @@ impl Properties { &self, interface_name: InterfaceName<'_>, property_name: &str, - value: Value<'_>, + value: &Value<'_>, #[zbus(object_server)] server: &ObjectServer, #[zbus(connection)] connection: &Connection, #[zbus(header)] header: Header<'_>, @@ -79,7 +79,7 @@ impl Properties { match iface.instance.read().await.set( property_name, - &value, + value, server, connection, Some(&header), diff --git a/zbus/src/proxy/mod.rs b/zbus/src/proxy/mod.rs index ca458de17..7a12a41dc 100644 --- a/zbus/src/proxy/mod.rs +++ b/zbus/src/proxy/mod.rs @@ -810,7 +810,7 @@ impl<'a> Proxy<'a> { T: 't + Into>, { self.properties_proxy() - .set(self.inner.interface.as_ref(), property_name, value.into()) + .set(self.inner.interface.as_ref(), property_name, &value.into()) .await } diff --git a/zbus_macros/src/iface.rs b/zbus_macros/src/iface.rs index d29def692..ca9e1f265 100644 --- a/zbus_macros/src/iface.rs +++ b/zbus_macros/src/iface.rs @@ -11,7 +11,7 @@ use syn::{ ImplItem, ImplItemFn, ItemImpl, Lit::Str, Meta, MetaNameValue, PatType, PathArguments, ReturnType, Signature, Token, Type, TypePath, - Visibility, + TypeReference, Visibility, }; use zvariant_utils::{case, def_attrs}; @@ -983,6 +983,18 @@ pub fn expand(args: Punctuated, mut input: ItemImpl) -> syn::Re }) } +fn maybe_unref_ty(ty: &Type) -> Option<&Type> { + fn should_unref(v: &TypeReference) -> bool { + // &str is special and we can deserialize to it, unlike other reference types. + !matches!(*v.elem, Type::Path(ref p) if p.path.is_ident("str")) + } + + match *ty { + Type::Reference(ref v) if should_unref(v) => Some(&v.elem), + _ => None, + } +} + fn get_args_from_inputs( inputs: &[PatType], method_type: MethodType, @@ -1071,7 +1083,7 @@ fn get_args_from_inputs( }; } else { args_names.push(pat_ident(input).unwrap()); - tys.push(&input.ty); + tys.push(&*input.ty); } } @@ -1085,15 +1097,36 @@ fn get_args_from_inputs( _ => ( quote! { let hdr = message.header(); }, quote! { let msg_body = message.body(); }, - quote! { - let (#(#args_names),*): (#(#tys),*) = - match msg_body.deserialize() { - ::std::result::Result::Ok(r) => r, - ::std::result::Result::Err(e) => { - let err = <#zbus::fdo::Error as ::std::convert::From<_>>::from(e); - return connection.reply_dbus_error(&hdr, err).await; + { + let mut unrefed_indices = vec![]; + let owned_tys = tys + .iter() + .enumerate() + .map(|(i, ty)| { + let owned = maybe_unref_ty(ty); + if owned.is_some() { + unrefed_indices.push(i); } - }; + owned.unwrap_or(ty) + }) + .collect::>(); + let mut q = quote! { + let (#(#args_names),*): (#(#owned_tys),*) = + match msg_body.deserialize() { + ::std::result::Result::Ok(r) => r, + ::std::result::Result::Err(e) => { + let err = <#zbus::fdo::Error as ::std::convert::From<_>>::from(e); + return connection.reply_dbus_error(&hdr, err).await; + } + }; + }; + for index in unrefed_indices { + let arg_name = &args_names[index]; + q.extend(quote! { + let #arg_name = &#arg_name; + }); + } + q }, ), };