diff --git a/wayland-client/src/conn.rs b/wayland-client/src/conn.rs index d3ef75df585..cec2eee2a3d 100644 --- a/wayland-client/src/conn.rs +++ b/wayland-client/src/conn.rs @@ -199,10 +199,11 @@ impl Connection { pub fn send_request( &self, proxy: &I, - request: I::Request, + request: I::Request<'_>, data: Option>, ) -> Result { let (msg, child_spec) = proxy.write_request(self, request)?; + let msg = msg.map_fd(|fd| fd.as_raw_fd()); self.backend.send_request(msg, data, child_spec) } diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index 00320d2c0b6..e40737b5ddf 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -169,12 +169,11 @@ use std::{ fmt, hash::{Hash, Hasher}, - os::unix::io::RawFd, sync::Arc, }; use wayland_backend::{ client::{InvalidId, ObjectData, ObjectId, WaylandError, WeakBackend}, - io_lifetimes::OwnedFd, + io_lifetimes::{BorrowedFd, OwnedFd}, protocol::{Interface, Message}, }; @@ -227,7 +226,7 @@ pub trait Proxy: Clone + std::fmt::Debug + Sized { /// The event enum for this interface type Event; /// The request enum for this interface - type Request; + type Request<'a>; /// The interface description fn interface() -> &'static Interface; @@ -278,7 +277,7 @@ pub trait Proxy: Clone + std::fmt::Debug + Sized { /// /// It is an error to use this function on requests that create objects; use /// [Proxy::send_constructor] for such requests. - fn send_request(&self, req: Self::Request) -> Result<(), InvalidId>; + fn send_request(&self, req: Self::Request<'_>) -> Result<(), InvalidId>; /// Send a request for this object that creates another object. /// @@ -286,7 +285,7 @@ pub trait Proxy: Clone + std::fmt::Debug + Sized { /// [Proxy::send_request] for such requests. fn send_constructor( &self, - req: Self::Request, + req: Self::Request<'_>, data: Arc, ) -> Result; @@ -304,11 +303,11 @@ pub trait Proxy: Clone + std::fmt::Debug + Sized { /// **Note:** This method is mostly meant as an implementation detail to be /// used by code generated by wayland-scanner. #[allow(clippy::type_complexity)] - fn write_request( + fn write_request<'a>( &self, conn: &Connection, - req: Self::Request, - ) -> Result<(Message, Option<(&'static Interface, u32)>), InvalidId>; + req: Self::Request<'a>, + ) -> Result<(Message>, Option<(&'static Interface, u32)>), InvalidId>; /// Creates a weak handle to this object /// diff --git a/wayland-scanner/src/client_gen.rs b/wayland-scanner/src/client_gen.rs index f02518c3831..0b591cfabc3 100644 --- a/wayland-scanner/src/client_gen.rs +++ b/wayland-scanner/src/client_gen.rs @@ -21,13 +21,13 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { let enums = crate::common::generate_enums_for(interface); let sinces = crate::common::gen_msg_constants(&interface.requests, &interface.events); - let requests = crate::common::gen_message_enum( + let (requests, requests_is_generic) = crate::common::gen_message_enum( &format_ident!("Request"), Side::Client, false, &interface.requests, ); - let events = crate::common::gen_message_enum( + let (events, events_is_generic) = crate::common::gen_message_enum( &format_ident!("Event"), Side::Client, true, @@ -49,6 +49,12 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { }; let doc_attr = to_doc_attr(&docs); + let request_generic = if requests_is_generic { + quote! { 'request } + } else { + quote! {} + }; + quote! { #mod_doc pub mod #mod_name { @@ -103,7 +109,7 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { } impl super::wayland_client::Proxy for #iface_name { - type Request = Request; + type Request<'request> = Request<#request_generic>; type Event = Event; #[inline] @@ -134,14 +140,14 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { &self.backend } - fn send_request(&self, req: Self::Request) -> Result<(), InvalidId> { + fn send_request(&self, req: Self::Request<'_>) -> Result<(), InvalidId> { let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?); let id = conn.send_request(self, req, None)?; debug_assert!(id.is_null()); Ok(()) } - fn send_constructor(&self, req: Self::Request, data: Arc) -> Result { + fn send_constructor(&self, req: Self::Request<'_>, data: Arc) -> Result { let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?); let id = conn.send_request(self, req, Some(data))?; Proxy::from_id(&conn, id) @@ -167,7 +173,7 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { #parse_body } - fn write_request(&self, conn: &Connection, msg: Self::Request) -> Result<(Message, Option<(&'static Interface, u32)>), InvalidId> { + fn write_request<'a>(&self, conn: &Connection, msg: Self::Request<'a>) -> Result<(Message>, Option<(&'static Interface, u32)>), InvalidId> { #write_body } } @@ -211,7 +217,7 @@ fn gen_methods(interface: &Interface) -> TokenStream { Type::Fixed => quote! { f64 }, Type::String => if arg.allow_null { quote!{ Option } } else { quote!{ String } }, Type::Array => if arg.allow_null { quote!{ Option> } } else { quote!{ Vec } }, - Type::Fd => quote! { ::std::os::unix::io::RawFd }, + Type::Fd => quote! { ::std::os::unix::io::BorrowedFd<'_> }, Type::Object => { let iface = arg.interface.as_ref().unwrap(); let iface_mod = Ident::new(iface, Span::call_site()); diff --git a/wayland-scanner/src/common.rs b/wayland-scanner/src/common.rs index 3844f6dc85e..e02202633a8 100644 --- a/wayland-scanner/src/common.rs +++ b/wayland-scanner/src/common.rs @@ -159,7 +159,9 @@ pub(crate) fn gen_message_enum( side: Side, receiver: bool, messages: &[Message], -) -> TokenStream { +) -> (TokenStream, bool) { + let mut needs_generic = false; + let variants = messages.iter().map(|msg| { let mut docs = String::new(); if let Some((ref short, ref long)) = msg.description { @@ -199,7 +201,8 @@ pub(crate) fn gen_message_enum( if receiver { quote! { io_lifetimes::OwnedFd } } else { - quote! { std::os::unix::io::RawFd } + needs_generic = true; + quote! { io_lifetimes::BorrowedFd<'request> } } } Type::Object => { @@ -275,7 +278,7 @@ pub(crate) fn gen_message_enum( #doc_attr #msg_variant_decl } - }); + }).collect::>(); let opcodes = messages.iter().enumerate().map(|(opcode, msg)| { let msg_name = Ident::new(&snake_to_camel(&msg.name), Span::call_site()); @@ -291,14 +294,20 @@ pub(crate) fn gen_message_enum( } }); - quote! { + let generic = if needs_generic { + quote! { 'request } + } else { + quote! {} + }; + + (quote! { #[derive(Debug)] #[non_exhaustive] - pub enum #name { + pub enum #name<#generic> { #(#variants,)* } - impl #name { + impl<#generic> #name<#generic> { #[doc="Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { @@ -306,7 +315,7 @@ pub(crate) fn gen_message_enum( } } } - } + }, needs_generic) } pub(crate) fn gen_parse_body(interface: &Interface, side: Side) -> TokenStream { diff --git a/wayland-scanner/src/server_gen.rs b/wayland-scanner/src/server_gen.rs index cde8db6de83..d101c7de624 100644 --- a/wayland-scanner/src/server_gen.rs +++ b/wayland-scanner/src/server_gen.rs @@ -26,13 +26,13 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { let enums = crate::common::generate_enums_for(interface); let msg_constants = crate::common::gen_msg_constants(&interface.requests, &interface.events); - let requests = crate::common::gen_message_enum( + let (requests, requests_is_generic) = crate::common::gen_message_enum( &format_ident!("Request"), Side::Server, true, &interface.requests, ); - let events = crate::common::gen_message_enum( + let (events, events_is_generic) = crate::common::gen_message_enum( &format_ident!("Event"), Side::Server, false,