Loading system/gd/rust/linux/client/src/dbus_iface.rs +38 −14 Original line number Original line Diff line number Diff line Loading @@ -184,24 +184,36 @@ impl IBluetoothConnectionCallback for IBluetoothConnectionCallbackDBus { fn on_device_disconnected(&self, remote_device: BluetoothDevice) {} fn on_device_disconnected(&self, remote_device: BluetoothDevice) {} } } // Implements RPC-friendly wrapper methods for calling IBluetooth, generated by // `generate_dbus_interface_client` below. pub(crate) struct BluetoothDBusRPC { client_proxy: ClientDBusProxy, } pub(crate) struct BluetoothDBus { pub(crate) struct BluetoothDBus { client_proxy: ClientDBusProxy, client_proxy: ClientDBusProxy, pub rpc: BluetoothDBusRPC, } } impl BluetoothDBus { impl BluetoothDBus { pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothDBus { fn make_client_proxy(conn: Arc<SyncConnection>, index: i32) -> ClientDBusProxy { BluetoothDBus { ClientDBusProxy::new( client_proxy: ClientDBusProxy::new( conn.clone(), conn.clone(), String::from("org.chromium.bluetooth"), String::from("org.chromium.bluetooth"), make_object_path(index, "adapter"), make_object_path(index, "adapter"), String::from("org.chromium.bluetooth.Bluetooth"), String::from("org.chromium.bluetooth.Bluetooth"), ), ) } pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothDBus { BluetoothDBus { client_proxy: Self::make_client_proxy(conn.clone(), index), rpc: BluetoothDBusRPC { client_proxy: Self::make_client_proxy(conn.clone(), index) }, } } } } } } #[generate_dbus_interface_client] #[generate_dbus_interface_client(BluetoothDBusRPC)] impl IBluetooth for BluetoothDBus { impl IBluetooth for BluetoothDBus { #[dbus_method("RegisterCallback")] #[dbus_method("RegisterCallback")] fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { Loading Loading @@ -413,19 +425,31 @@ pub struct AdapterWithEnabledDbus { enabled: bool, enabled: bool, } } // Implements RPC-friendly wrapper methods for calling IBluetoothManager, generated by // `generate_dbus_interface_client` below. pub(crate) struct BluetoothManagerDBusRPC { client_proxy: ClientDBusProxy, } pub(crate) struct BluetoothManagerDBus { pub(crate) struct BluetoothManagerDBus { client_proxy: ClientDBusProxy, client_proxy: ClientDBusProxy, pub rpc: BluetoothManagerDBusRPC, } } impl BluetoothManagerDBus { impl BluetoothManagerDBus { pub(crate) fn new(conn: Arc<SyncConnection>) -> BluetoothManagerDBus { fn make_client_proxy(conn: Arc<SyncConnection>) -> ClientDBusProxy { BluetoothManagerDBus { ClientDBusProxy::new( client_proxy: ClientDBusProxy::new( conn, conn.clone(), String::from("org.chromium.bluetooth.Manager"), String::from("org.chromium.bluetooth.Manager"), dbus::Path::new("/org/chromium/bluetooth/Manager").unwrap(), dbus::Path::new("/org/chromium/bluetooth/Manager").unwrap(), String::from("org.chromium.bluetooth.Manager"), String::from("org.chromium.bluetooth.Manager"), ), ) } pub(crate) fn new(conn: Arc<SyncConnection>) -> BluetoothManagerDBus { BluetoothManagerDBus { client_proxy: Self::make_client_proxy(conn.clone()), rpc: BluetoothManagerDBusRPC { client_proxy: Self::make_client_proxy(conn.clone()) }, } } } } Loading @@ -435,7 +459,7 @@ impl BluetoothManagerDBus { } } } } #[generate_dbus_interface_client] #[generate_dbus_interface_client(BluetoothManagerDBusRPC)] impl IBluetoothManager for BluetoothManagerDBus { impl IBluetoothManager for BluetoothManagerDBus { #[dbus_method("Start")] #[dbus_method("Start")] fn start(&mut self, hci_interface: i32) { fn start(&mut self, hci_interface: i32) { Loading system/gd/rust/linux/client/src/main.rs +29 −8 Original line number Original line Diff line number Diff line Loading @@ -226,7 +226,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { if !context.lock().unwrap().manager_dbus.is_valid() { if !context.lock().unwrap().manager_dbus.is_valid() { println!("Bluetooth manager doesn't seem to be working correctly."); println!("Bluetooth manager doesn't seem to be working correctly."); println!("Check if service is running."); println!("Check if service is running."); println!("..."); return Ok(()); } } // TODO: Registering the callback should be done when btmanagerd is ready (detect with // TODO: Registering the callback should be done when btmanagerd is ready (detect with Loading @@ -241,8 +241,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // Check if the default adapter is enabled. If yes, we should create the adapter proxy // Check if the default adapter is enabled. If yes, we should create the adapter proxy // right away. // right away. let default_adapter = context.lock().unwrap().default_adapter; let default_adapter = context.lock().unwrap().default_adapter; if context.lock().unwrap().manager_dbus.get_adapter_enabled(default_adapter) { context.lock().unwrap().set_adapter_enabled(default_adapter, true); { let mut context_locked = context.lock().unwrap(); match context_locked.manager_dbus.rpc.get_adapter_enabled(default_adapter).await { Ok(ret) => { if ret { context_locked.set_adapter_enabled(default_adapter, true); } } Err(e) => { panic!("Bluetooth Manager is not available. Exiting. D-Bus error: {}", e); } } } } let mut handler = CommandHandler::new(context.clone()); let mut handler = CommandHandler::new(context.clone()); Loading Loading @@ -325,26 +336,36 @@ async fn start_interactive_shell( let dbus_connection = context.lock().unwrap().dbus_connection.clone(); let dbus_connection = context.lock().unwrap().dbus_connection.clone(); let dbus_crossroads = context.lock().unwrap().dbus_crossroads.clone(); let dbus_crossroads = context.lock().unwrap().dbus_crossroads.clone(); context.lock().unwrap().adapter_dbus.as_mut().unwrap().register_callback(Box::new( context BtCallback::new( .lock() .unwrap() .adapter_dbus .as_mut() .unwrap() .rpc .register_callback(Box::new(BtCallback::new( cb_objpath.clone(), cb_objpath.clone(), context.clone(), context.clone(), dbus_connection.clone(), dbus_connection.clone(), dbus_crossroads.clone(), dbus_crossroads.clone(), ), ))) )); .await .expect("D-Bus error on IBluetooth::RegisterCallback"); context context .lock() .lock() .unwrap() .unwrap() .adapter_dbus .adapter_dbus .as_mut() .as_mut() .unwrap() .unwrap() .rpc .register_connection_callback(Box::new(BtConnectionCallback::new( .register_connection_callback(Box::new(BtConnectionCallback::new( conn_cb_objpath, conn_cb_objpath, context.clone(), context.clone(), dbus_connection.clone(), dbus_connection.clone(), dbus_crossroads.clone(), dbus_crossroads.clone(), ))); ))) .await .expect("D-Bus error on IBluetooth::RegisterConnectionCallback"); // When adapter is ready, Suspend API is also ready. Register as an observer. // When adapter is ready, Suspend API is also ready. Register as an observer. // TODO(b/224606285): Implement suspend debug utils in btclient. // TODO(b/224606285): Implement suspend debug utils in btclient. Loading system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs +83 −2 Original line number Original line Diff line number Diff line Loading @@ -221,11 +221,22 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre /// Generates a client implementation of a D-Bus interface. /// Generates a client implementation of a D-Bus interface. /// /// /// Example: /// Example: /// #[generate_dbus_interface_client()] /// #[generate_dbus_interface_client] /// /// /// The impl containing #[dbus_method()] will contain a generated code to call the method via D-Bus. /// The impl containing #[dbus_method()] will contain a generated code to call the method via D-Bus. /// /// Example: /// #[generate_dbus_interface_client(SomeRPC)] /// /// When the RPC wrapper struct name is specified, it also generates the more RPC-friendly struct: /// * All methods are async, allowing clients to await (yield) without blocking. Even methods that /// are sync at the server side requires clients to "wait" for the return. /// * All method returns are wrapped with `Result`, allowing clients to detect D-Bus level errors in /// addition to API-level errors. #[proc_macro_attribute] #[proc_macro_attribute] pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn generate_dbus_interface_client(attr: TokenStream, item: TokenStream) -> TokenStream { let rpc_struct_name = attr.to_string(); let ast: ItemImpl = syn::parse(item.clone()).unwrap(); let ast: ItemImpl = syn::parse(item.clone()).unwrap(); let trait_path = ast.trait_.unwrap().1; let trait_path = ast.trait_.unwrap().1; let struct_path = match *ast.self_ty { let struct_path = match *ast.self_ty { Loading @@ -233,8 +244,12 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> _ => panic!("Struct path not available"), _ => panic!("Struct path not available"), }; }; // Generated methods let mut methods = quote! {}; let mut methods = quote! {}; // Generated RPC-friendly methods (async and Result-wrapped). let mut rpc_methods = quote! {}; // Iterate on every methods of a trait impl // Iterate on every methods of a trait impl for item in ast.items { for item in ast.items { if let ImplItem::Method(method) = item { if let ImplItem::Method(method) = item { Loading @@ -256,6 +271,22 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> let sig = &method.sig; let sig = &method.sig; // For RPC-friendly method, copy the original signature but add public, async, and wrap // the return with Result. let mut rpc_sig = sig.clone(); rpc_sig.asyncness = Some(<syn::Token![async]>::default()); rpc_sig.output = match rpc_sig.output { syn::ReturnType::Default => { syn::parse(quote! {-> Result<(), dbus::Error>}.into()).unwrap() } syn::ReturnType::Type(_arrow, path) => { syn::parse(quote! {-> Result<#path, dbus::Error>}.into()).unwrap() } }; let rpc_sig = quote! { pub #rpc_sig }; let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() { let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() { Some(meta_list.nested[0].clone()) Some(meta_list.nested[0].clone()) } else { } else { Loading Loading @@ -343,6 +374,26 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> } } } } }; }; let rpc_body = match &method.sig.output { // Build the async method call to `self.client_proxy`. ReturnType::Default => { quote! { self.client_proxy .async_method_noreturn(#dbus_method_name, #input_tuple) .await } } _ => { quote! { self.client_proxy .async_method(#dbus_method_name, #input_tuple) .await .map(|(x,)| { #output_as_dbus_arg::from_dbus(x, None, None, None).unwrap() }) } } }; // Assemble the method body. May have object conversions if there is a param that is // Assemble the method body. May have object conversions if there is a param that is // a proxy object (`Box<dyn>` type). // a proxy object (`Box<dyn>` type). Loading @@ -351,6 +402,11 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #body #body }; }; let rpc_body = quote! { #object_conversions #rpc_body }; // The method definition is its signature and the body. // The method definition is its signature and the body. let generated_method = quote! { let generated_method = quote! { Loading @@ -358,6 +414,11 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #body #body } } }; }; let generated_rpc_method = quote! { #rpc_sig { #rpc_body } }; // Assemble all the method definitions. // Assemble all the method definitions. methods = quote! { methods = quote! { Loading @@ -365,13 +426,33 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #generated_method #generated_method }; }; rpc_methods = quote! { #rpc_methods #generated_rpc_method }; } } // Generated code for the RPC wrapper struct. let rpc_gen = if rpc_struct_name.is_empty() { quote! {} } else { let rpc_struct = format_ident!("{}", rpc_struct_name); quote! { impl #rpc_struct { #rpc_methods } } } } }; // The final generated code. let gen = quote! { let gen = quote! { impl #trait_path for #struct_path { impl #trait_path for #struct_path { #methods #methods } } #rpc_gen }; }; debug_output_to_file( debug_output_to_file( Loading system/gd/rust/linux/dbus_projection/src/lib.rs +23 −0 Original line number Original line Diff line number Diff line Loading @@ -185,6 +185,29 @@ impl ClientDBusProxy { ) ) } } /// Asynchronously calls the method and returns the D-Bus result and lets the caller unwrap. pub async fn async_method< A: AppendAll, T: 'static + dbus::arg::Arg + for<'z> dbus::arg::Get<'z>, >( &self, member: &str, args: A, ) -> Result<(T,), dbus::Error> { let proxy = self.create_proxy(); proxy.method_call(self.interface.clone(), member, args).await } /// Asynchronously calls the method and returns the D-Bus result with empty return data. pub async fn async_method_noreturn<A: AppendAll>( &self, member: &str, args: A, ) -> Result<(), dbus::Error> { let proxy = self.create_proxy(); proxy.method_call(self.interface.clone(), member, args).await } /// Calls the method and returns the D-Bus result and lets the caller unwrap. /// Calls the method and returns the D-Bus result and lets the caller unwrap. pub fn method_withresult< pub fn method_withresult< A: AppendAll, A: AppendAll, Loading Loading
system/gd/rust/linux/client/src/dbus_iface.rs +38 −14 Original line number Original line Diff line number Diff line Loading @@ -184,24 +184,36 @@ impl IBluetoothConnectionCallback for IBluetoothConnectionCallbackDBus { fn on_device_disconnected(&self, remote_device: BluetoothDevice) {} fn on_device_disconnected(&self, remote_device: BluetoothDevice) {} } } // Implements RPC-friendly wrapper methods for calling IBluetooth, generated by // `generate_dbus_interface_client` below. pub(crate) struct BluetoothDBusRPC { client_proxy: ClientDBusProxy, } pub(crate) struct BluetoothDBus { pub(crate) struct BluetoothDBus { client_proxy: ClientDBusProxy, client_proxy: ClientDBusProxy, pub rpc: BluetoothDBusRPC, } } impl BluetoothDBus { impl BluetoothDBus { pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothDBus { fn make_client_proxy(conn: Arc<SyncConnection>, index: i32) -> ClientDBusProxy { BluetoothDBus { ClientDBusProxy::new( client_proxy: ClientDBusProxy::new( conn.clone(), conn.clone(), String::from("org.chromium.bluetooth"), String::from("org.chromium.bluetooth"), make_object_path(index, "adapter"), make_object_path(index, "adapter"), String::from("org.chromium.bluetooth.Bluetooth"), String::from("org.chromium.bluetooth.Bluetooth"), ), ) } pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothDBus { BluetoothDBus { client_proxy: Self::make_client_proxy(conn.clone(), index), rpc: BluetoothDBusRPC { client_proxy: Self::make_client_proxy(conn.clone(), index) }, } } } } } } #[generate_dbus_interface_client] #[generate_dbus_interface_client(BluetoothDBusRPC)] impl IBluetooth for BluetoothDBus { impl IBluetooth for BluetoothDBus { #[dbus_method("RegisterCallback")] #[dbus_method("RegisterCallback")] fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) { Loading Loading @@ -413,19 +425,31 @@ pub struct AdapterWithEnabledDbus { enabled: bool, enabled: bool, } } // Implements RPC-friendly wrapper methods for calling IBluetoothManager, generated by // `generate_dbus_interface_client` below. pub(crate) struct BluetoothManagerDBusRPC { client_proxy: ClientDBusProxy, } pub(crate) struct BluetoothManagerDBus { pub(crate) struct BluetoothManagerDBus { client_proxy: ClientDBusProxy, client_proxy: ClientDBusProxy, pub rpc: BluetoothManagerDBusRPC, } } impl BluetoothManagerDBus { impl BluetoothManagerDBus { pub(crate) fn new(conn: Arc<SyncConnection>) -> BluetoothManagerDBus { fn make_client_proxy(conn: Arc<SyncConnection>) -> ClientDBusProxy { BluetoothManagerDBus { ClientDBusProxy::new( client_proxy: ClientDBusProxy::new( conn, conn.clone(), String::from("org.chromium.bluetooth.Manager"), String::from("org.chromium.bluetooth.Manager"), dbus::Path::new("/org/chromium/bluetooth/Manager").unwrap(), dbus::Path::new("/org/chromium/bluetooth/Manager").unwrap(), String::from("org.chromium.bluetooth.Manager"), String::from("org.chromium.bluetooth.Manager"), ), ) } pub(crate) fn new(conn: Arc<SyncConnection>) -> BluetoothManagerDBus { BluetoothManagerDBus { client_proxy: Self::make_client_proxy(conn.clone()), rpc: BluetoothManagerDBusRPC { client_proxy: Self::make_client_proxy(conn.clone()) }, } } } } Loading @@ -435,7 +459,7 @@ impl BluetoothManagerDBus { } } } } #[generate_dbus_interface_client] #[generate_dbus_interface_client(BluetoothManagerDBusRPC)] impl IBluetoothManager for BluetoothManagerDBus { impl IBluetoothManager for BluetoothManagerDBus { #[dbus_method("Start")] #[dbus_method("Start")] fn start(&mut self, hci_interface: i32) { fn start(&mut self, hci_interface: i32) { Loading
system/gd/rust/linux/client/src/main.rs +29 −8 Original line number Original line Diff line number Diff line Loading @@ -226,7 +226,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { if !context.lock().unwrap().manager_dbus.is_valid() { if !context.lock().unwrap().manager_dbus.is_valid() { println!("Bluetooth manager doesn't seem to be working correctly."); println!("Bluetooth manager doesn't seem to be working correctly."); println!("Check if service is running."); println!("Check if service is running."); println!("..."); return Ok(()); } } // TODO: Registering the callback should be done when btmanagerd is ready (detect with // TODO: Registering the callback should be done when btmanagerd is ready (detect with Loading @@ -241,8 +241,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // Check if the default adapter is enabled. If yes, we should create the adapter proxy // Check if the default adapter is enabled. If yes, we should create the adapter proxy // right away. // right away. let default_adapter = context.lock().unwrap().default_adapter; let default_adapter = context.lock().unwrap().default_adapter; if context.lock().unwrap().manager_dbus.get_adapter_enabled(default_adapter) { context.lock().unwrap().set_adapter_enabled(default_adapter, true); { let mut context_locked = context.lock().unwrap(); match context_locked.manager_dbus.rpc.get_adapter_enabled(default_adapter).await { Ok(ret) => { if ret { context_locked.set_adapter_enabled(default_adapter, true); } } Err(e) => { panic!("Bluetooth Manager is not available. Exiting. D-Bus error: {}", e); } } } } let mut handler = CommandHandler::new(context.clone()); let mut handler = CommandHandler::new(context.clone()); Loading Loading @@ -325,26 +336,36 @@ async fn start_interactive_shell( let dbus_connection = context.lock().unwrap().dbus_connection.clone(); let dbus_connection = context.lock().unwrap().dbus_connection.clone(); let dbus_crossroads = context.lock().unwrap().dbus_crossroads.clone(); let dbus_crossroads = context.lock().unwrap().dbus_crossroads.clone(); context.lock().unwrap().adapter_dbus.as_mut().unwrap().register_callback(Box::new( context BtCallback::new( .lock() .unwrap() .adapter_dbus .as_mut() .unwrap() .rpc .register_callback(Box::new(BtCallback::new( cb_objpath.clone(), cb_objpath.clone(), context.clone(), context.clone(), dbus_connection.clone(), dbus_connection.clone(), dbus_crossroads.clone(), dbus_crossroads.clone(), ), ))) )); .await .expect("D-Bus error on IBluetooth::RegisterCallback"); context context .lock() .lock() .unwrap() .unwrap() .adapter_dbus .adapter_dbus .as_mut() .as_mut() .unwrap() .unwrap() .rpc .register_connection_callback(Box::new(BtConnectionCallback::new( .register_connection_callback(Box::new(BtConnectionCallback::new( conn_cb_objpath, conn_cb_objpath, context.clone(), context.clone(), dbus_connection.clone(), dbus_connection.clone(), dbus_crossroads.clone(), dbus_crossroads.clone(), ))); ))) .await .expect("D-Bus error on IBluetooth::RegisterConnectionCallback"); // When adapter is ready, Suspend API is also ready. Register as an observer. // When adapter is ready, Suspend API is also ready. Register as an observer. // TODO(b/224606285): Implement suspend debug utils in btclient. // TODO(b/224606285): Implement suspend debug utils in btclient. Loading
system/gd/rust/linux/dbus_projection/dbus_macros/src/lib.rs +83 −2 Original line number Original line Diff line number Diff line Loading @@ -221,11 +221,22 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre /// Generates a client implementation of a D-Bus interface. /// Generates a client implementation of a D-Bus interface. /// /// /// Example: /// Example: /// #[generate_dbus_interface_client()] /// #[generate_dbus_interface_client] /// /// /// The impl containing #[dbus_method()] will contain a generated code to call the method via D-Bus. /// The impl containing #[dbus_method()] will contain a generated code to call the method via D-Bus. /// /// Example: /// #[generate_dbus_interface_client(SomeRPC)] /// /// When the RPC wrapper struct name is specified, it also generates the more RPC-friendly struct: /// * All methods are async, allowing clients to await (yield) without blocking. Even methods that /// are sync at the server side requires clients to "wait" for the return. /// * All method returns are wrapped with `Result`, allowing clients to detect D-Bus level errors in /// addition to API-level errors. #[proc_macro_attribute] #[proc_macro_attribute] pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn generate_dbus_interface_client(attr: TokenStream, item: TokenStream) -> TokenStream { let rpc_struct_name = attr.to_string(); let ast: ItemImpl = syn::parse(item.clone()).unwrap(); let ast: ItemImpl = syn::parse(item.clone()).unwrap(); let trait_path = ast.trait_.unwrap().1; let trait_path = ast.trait_.unwrap().1; let struct_path = match *ast.self_ty { let struct_path = match *ast.self_ty { Loading @@ -233,8 +244,12 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> _ => panic!("Struct path not available"), _ => panic!("Struct path not available"), }; }; // Generated methods let mut methods = quote! {}; let mut methods = quote! {}; // Generated RPC-friendly methods (async and Result-wrapped). let mut rpc_methods = quote! {}; // Iterate on every methods of a trait impl // Iterate on every methods of a trait impl for item in ast.items { for item in ast.items { if let ImplItem::Method(method) = item { if let ImplItem::Method(method) = item { Loading @@ -256,6 +271,22 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> let sig = &method.sig; let sig = &method.sig; // For RPC-friendly method, copy the original signature but add public, async, and wrap // the return with Result. let mut rpc_sig = sig.clone(); rpc_sig.asyncness = Some(<syn::Token![async]>::default()); rpc_sig.output = match rpc_sig.output { syn::ReturnType::Default => { syn::parse(quote! {-> Result<(), dbus::Error>}.into()).unwrap() } syn::ReturnType::Type(_arrow, path) => { syn::parse(quote! {-> Result<#path, dbus::Error>}.into()).unwrap() } }; let rpc_sig = quote! { pub #rpc_sig }; let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() { let dbus_method_name = if let Meta::List(meta_list) = attr.parse_meta().unwrap() { Some(meta_list.nested[0].clone()) Some(meta_list.nested[0].clone()) } else { } else { Loading Loading @@ -343,6 +374,26 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> } } } } }; }; let rpc_body = match &method.sig.output { // Build the async method call to `self.client_proxy`. ReturnType::Default => { quote! { self.client_proxy .async_method_noreturn(#dbus_method_name, #input_tuple) .await } } _ => { quote! { self.client_proxy .async_method(#dbus_method_name, #input_tuple) .await .map(|(x,)| { #output_as_dbus_arg::from_dbus(x, None, None, None).unwrap() }) } } }; // Assemble the method body. May have object conversions if there is a param that is // Assemble the method body. May have object conversions if there is a param that is // a proxy object (`Box<dyn>` type). // a proxy object (`Box<dyn>` type). Loading @@ -351,6 +402,11 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #body #body }; }; let rpc_body = quote! { #object_conversions #rpc_body }; // The method definition is its signature and the body. // The method definition is its signature and the body. let generated_method = quote! { let generated_method = quote! { Loading @@ -358,6 +414,11 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #body #body } } }; }; let generated_rpc_method = quote! { #rpc_sig { #rpc_body } }; // Assemble all the method definitions. // Assemble all the method definitions. methods = quote! { methods = quote! { Loading @@ -365,13 +426,33 @@ pub fn generate_dbus_interface_client(_attr: TokenStream, item: TokenStream) -> #generated_method #generated_method }; }; rpc_methods = quote! { #rpc_methods #generated_rpc_method }; } } // Generated code for the RPC wrapper struct. let rpc_gen = if rpc_struct_name.is_empty() { quote! {} } else { let rpc_struct = format_ident!("{}", rpc_struct_name); quote! { impl #rpc_struct { #rpc_methods } } } } }; // The final generated code. let gen = quote! { let gen = quote! { impl #trait_path for #struct_path { impl #trait_path for #struct_path { #methods #methods } } #rpc_gen }; }; debug_output_to_file( debug_output_to_file( Loading
system/gd/rust/linux/dbus_projection/src/lib.rs +23 −0 Original line number Original line Diff line number Diff line Loading @@ -185,6 +185,29 @@ impl ClientDBusProxy { ) ) } } /// Asynchronously calls the method and returns the D-Bus result and lets the caller unwrap. pub async fn async_method< A: AppendAll, T: 'static + dbus::arg::Arg + for<'z> dbus::arg::Get<'z>, >( &self, member: &str, args: A, ) -> Result<(T,), dbus::Error> { let proxy = self.create_proxy(); proxy.method_call(self.interface.clone(), member, args).await } /// Asynchronously calls the method and returns the D-Bus result with empty return data. pub async fn async_method_noreturn<A: AppendAll>( &self, member: &str, args: A, ) -> Result<(), dbus::Error> { let proxy = self.create_proxy(); proxy.method_call(self.interface.clone(), member, args).await } /// Calls the method and returns the D-Bus result and lets the caller unwrap. /// Calls the method and returns the D-Bus result and lets the caller unwrap. pub fn method_withresult< pub fn method_withresult< A: AppendAll, A: AppendAll, Loading