From b933030a82f77e04e914d14dc200d991c305c0e7 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Wed, 11 Sep 2019 17:55:01 +0200 Subject: [PATCH] commons: use smallvec to store message arguments Any message with 4 argument or less will have these arguments stored inline rather than in an heap-allocated vec. The number 4 was chose because almost all messages have 4 arguments or less, and some potentially very spammy messages (wl_touch.move) have exactly 4 arguments. Avoiding allocations in these cases should generally be a gain. Moreother, to avoid bloating the size of Message due to this, String and Array arguments are further boxed, reducing the size of Argument from 4*usize to 2*usize. These kind of arguments are generally pretty rare, so the double allocation should overall not counter the size gain. Closes #268, #249 --- CHANGELOG.md | 2 ++ tests/protocol_errors.rs | 7 ++-- tests/scanner_assets/client_code.rs | 34 ++++++++++-------- tests/scanner_assets/server_code.rs | 16 ++++----- wayland-client/src/lib.rs | 1 + wayland-client/src/rust_imp/mod.rs | 1 + wayland-client/src/rust_imp/queues.rs | 2 +- wayland-commons/Cargo.toml | 1 + .../examples/manual_global_list.rs | 3 +- wayland-commons/src/lib.rs | 2 ++ wayland-commons/src/socket.rs | 22 ++++++------ wayland-commons/src/wire.rs | 36 ++++++++++++++----- wayland-protocols/src/protocol_macro.rs | 2 ++ wayland-scanner/src/c_code_gen.rs | 4 +-- wayland-scanner/src/common_gen.rs | 22 ++++++------ wayland-server/src/lib.rs | 1 + wayland-server/src/rust_imp/clients.rs | 8 ++--- wayland-server/src/rust_imp/globals.rs | 9 ++--- wayland-server/src/rust_imp/mod.rs | 1 + 19 files changed, 106 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c99053d2ab0..49bad909c3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ - [client] the `cursor` and `egl` features are split into their own crates: `wayland-egl` and `wayland-cursor` - [server] All dependencies on `calloop` are now removed, `wayland-server` now only exposes a `dispatch(..)` and `get_poll_fd()` method, that you are responsible for integrating into your event loop. +- [commons] Use `smallvec` to store the arguments of messages having 4 or less, drastically reducing the + number of allocations when using the rust implementation of the protocol. ## 0.23.6 -- 2019-09-06 diff --git a/tests/protocol_errors.rs b/tests/protocol_errors.rs index 6fd7fd42445..052fb2834ef 100644 --- a/tests/protocol_errors.rs +++ b/tests/protocol_errors.rs @@ -5,6 +5,7 @@ use helpers::{roundtrip, wayc, ways, TestClient, TestServer}; extern crate nix; extern crate wayland_commons as wc; +use wc::smallvec; use wc::socket::{BufferedSocket, Socket}; use wc::wire::{Argument, Message}; @@ -28,7 +29,7 @@ fn client_wrong_id() { .write_message(&Message { sender_id: 1, // wl_display opcode: 1, // wl_registry - args: vec![ + args: smallvec![ Argument::NewId(3), // should be 2 ], }) @@ -54,7 +55,7 @@ fn client_wrong_opcode() { .write_message(&Message { sender_id: 1, // wl_display opcode: 42, // inexistant - args: vec![], + args: smallvec![], }) .unwrap(); socket.flush().unwrap(); @@ -78,7 +79,7 @@ fn client_wrong_sender() { .write_message(&Message { sender_id: 54, // wl_display opcode: 0, // inexistant - args: vec![], + args: smallvec![], }) .unwrap(); socket.flush().unwrap(); diff --git a/tests/scanner_assets/client_code.rs b/tests/scanner_assets/client_code.rs index a0ac0b1bf3d..ef0e4ed8479 100644 --- a/tests/scanner_assets/client_code.rs +++ b/tests/scanner_assets/client_code.rs @@ -15,7 +15,7 @@ pub mod wl_foo { use super::sys::client::*; use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Proxy, NULLPTR, }; use std::os::raw::c_char; @@ -134,10 +134,12 @@ pub mod wl_foo { } => Message { sender_id: sender_id, opcode: 0, - args: vec![ + args: smallvec![ Argument::Int(number), Argument::Uint(unumber), - Argument::Str(unsafe { ::std::ffi::CString::from_vec_unchecked(text.into()) }), + Argument::Str(Box::new(unsafe { + ::std::ffi::CString::from_vec_unchecked(text.into()) + })), Argument::Fixed((float * 256.) as i32), Argument::Fd(file), ], @@ -145,7 +147,7 @@ pub mod wl_foo { Request::CreateBar {} => Message { sender_id: sender_id, opcode: 1, - args: vec![Argument::NewId(0)], + args: smallvec![Argument::NewId(0),], }, } } @@ -369,7 +371,7 @@ pub mod wl_bar { use super::sys::client::*; use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Proxy, NULLPTR, }; use std::os::raw::c_char; @@ -475,17 +477,17 @@ pub mod wl_bar { } => Message { sender_id: sender_id, opcode: 0, - args: vec![ + args: smallvec![ Argument::Uint(kind.to_raw()), Argument::Object(target.as_ref().id()), - Argument::Array(metadata), - Argument::Array(metametadata.unwrap_or_else(Vec::new)), + Argument::Array(Box::new(metadata)), + Argument::Array(Box::new(metametadata.unwrap_or_else(Vec::new))), ], }, Request::Release => Message { sender_id: sender_id, opcode: 1, - args: vec![], + args: smallvec![], }, Request::_Self { _self, @@ -499,7 +501,7 @@ pub mod wl_bar { } => Message { sender_id: sender_id, opcode: 2, - args: vec![ + args: smallvec![ Argument::Uint(_self), Argument::Uint(_mut), Argument::Uint(object), @@ -861,7 +863,7 @@ pub mod wl_display { use super::sys::client::*; use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Proxy, NULLPTR, }; use std::os::raw::c_char; @@ -1012,7 +1014,7 @@ pub mod wl_registry { use super::sys::client::*; use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Proxy, NULLPTR, }; use std::os::raw::c_char; @@ -1062,9 +1064,11 @@ pub mod wl_registry { Request::Bind { name, id } => Message { sender_id: sender_id, opcode: 0, - args: vec![ + args: smallvec![ Argument::Uint(name), - Argument::Str(unsafe { ::std::ffi::CString::from_vec_unchecked(id.0.into()) }), + Argument::Str(Box::new(unsafe { + ::std::ffi::CString::from_vec_unchecked(id.0.into()) + })), Argument::Uint(id.1), Argument::NewId(0), ], @@ -1213,7 +1217,7 @@ pub mod wl_callback { use super::sys::client::*; use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Proxy, NULLPTR, }; use std::os::raw::c_char; diff --git a/tests/scanner_assets/server_code.rs b/tests/scanner_assets/server_code.rs index bee819b7c24..254b6eb8d2d 100644 --- a/tests/scanner_assets/server_code.rs +++ b/tests/scanner_assets/server_code.rs @@ -15,7 +15,7 @@ pub mod wl_foo { use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::sys::server::*; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Resource, NULLPTR, }; use std::os::raw::c_char; @@ -264,7 +264,7 @@ pub mod wl_foo { Event::Cake { kind, amount } => Message { sender_id: sender_id, opcode: 0, - args: vec![Argument::Uint(kind.to_raw()), Argument::Uint(amount)], + args: smallvec![Argument::Uint(kind.to_raw()), Argument::Uint(amount),], }, } } @@ -371,7 +371,7 @@ pub mod wl_bar { use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::sys::server::*; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Resource, NULLPTR, }; use std::os::raw::c_char; @@ -484,7 +484,7 @@ pub mod wl_bar { }, metadata: { if let Some(Argument::Array(val)) = args.next() { - val + *val } else { return Err(()); } @@ -494,7 +494,7 @@ pub mod wl_bar { if val.len() == 0 { None } else { - Some(val) + Some(*val) } } else { return Err(()); @@ -692,7 +692,7 @@ pub mod wl_bar { } => Message { sender_id: sender_id, opcode: 0, - args: vec![ + args: smallvec![ Argument::Uint(_self), Argument::Uint(_mut), Argument::Uint(object), @@ -850,7 +850,7 @@ pub mod wl_callback { use super::sys::common::{wl_argument, wl_array, wl_interface, wl_message}; use super::sys::server::*; use super::{ - types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, + smallvec, types_null, AnonymousObject, Argument, ArgumentType, Interface, Main, Message, MessageDesc, MessageGroup, Object, ObjectMetadata, Resource, NULLPTR, }; use std::os::raw::c_char; @@ -951,7 +951,7 @@ pub mod wl_callback { Event::Done { callback_data } => Message { sender_id: sender_id, opcode: 0, - args: vec![Argument::Uint(callback_data)], + args: smallvec![Argument::Uint(callback_data),], }, } } diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index c21504a2382..cff0e374a2d 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -135,6 +135,7 @@ pub mod protocol { pub(crate) use crate::{AnonymousObject, Attached, Main, Proxy, ProxyMap}; pub(crate) use wayland_commons::map::{Object, ObjectMetadata}; + pub(crate) use wayland_commons::smallvec; pub(crate) use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc}; pub(crate) use wayland_commons::{Interface, MessageGroup}; pub(crate) use wayland_sys as sys; diff --git a/wayland-client/src/rust_imp/mod.rs b/wayland-client/src/rust_imp/mod.rs index 893c8eeac72..7cf303bd4b9 100644 --- a/wayland-client/src/rust_imp/mod.rs +++ b/wayland-client/src/rust_imp/mod.rs @@ -60,6 +60,7 @@ impl ProxyMap { /* * Dispatching logic */ +#[allow(clippy::large_enum_variant)] pub(crate) enum Dispatched { Yes, NoDispatch(Message, ProxyInner), diff --git a/wayland-client/src/rust_imp/queues.rs b/wayland-client/src/rust_imp/queues.rs index a1e4b25df53..bb8f3807766 100644 --- a/wayland-client/src/rust_imp/queues.rs +++ b/wayland-client/src/rust_imp/queues.rs @@ -264,7 +264,7 @@ fn message_to_rawevent(msg: Message, proxy: &ProxyInner, map: &mut super::ProxyM .map(|a| match a { Argument::Int(i) => crate::Argument::Int(i), Argument::Uint(u) => crate::Argument::Uint(u), - Argument::Array(v) => crate::Argument::Array(if v.is_empty() { None } else { Some(v) }), + Argument::Array(v) => crate::Argument::Array(if v.is_empty() { None } else { Some(*v) }), Argument::Fixed(f) => crate::Argument::Float((f as f32) / 256.), Argument::Fd(f) => crate::Argument::Fd(f), Argument::Str(cs) => crate::Argument::Str({ diff --git a/wayland-commons/Cargo.toml b/wayland-commons/Cargo.toml index 114467079a9..3bcaa819d4f 100644 --- a/wayland-commons/Cargo.toml +++ b/wayland-commons/Cargo.toml @@ -17,3 +17,4 @@ travis-ci = { repository = "Smithay/wayland-rs" } wayland-sys = { version = "0.24.0-pre", path = "../wayland-sys" } nix = "0.15" spin = "0.5" +smallvec = "0.6" \ No newline at end of file diff --git a/wayland-commons/examples/manual_global_list.rs b/wayland-commons/examples/manual_global_list.rs index 843f63a175a..88a9abd5741 100644 --- a/wayland-commons/examples/manual_global_list.rs +++ b/wayland-commons/examples/manual_global_list.rs @@ -5,6 +5,7 @@ use std::os::unix::io::{FromRawFd, IntoRawFd}; use std::os::unix::net::UnixStream; use std::path::PathBuf; +use wc::smallvec; use wc::socket::{BufferedSocket, Socket}; use wc::wire::{Argument, ArgumentType, Message, MessageDesc}; @@ -20,7 +21,7 @@ fn main() { .write_message(&Message { sender_id: 1, // wl_display opcode: 1, // get registry - args: vec![ + args: smallvec![ Argument::NewId(2), // id of the created registry ], }) diff --git a/wayland-commons/src/lib.rs b/wayland-commons/src/lib.rs index d02aae0dee2..85c7e66f30c 100644 --- a/wayland-commons/src/lib.rs +++ b/wayland-commons/src/lib.rs @@ -27,6 +27,8 @@ pub mod socket; pub mod user_data; pub mod wire; +pub use smallvec::smallvec; + /// A group of messages /// /// This represents a group of message that can be serialized on the protocol wire. diff --git a/wayland-commons/src/socket.rs b/wayland-commons/src/socket.rs index 047a47f88a1..cc52e9cc907 100644 --- a/wayland-commons/src/socket.rs +++ b/wayland-commons/src/socket.rs @@ -435,6 +435,8 @@ mod tests { use std::ffi::CString; + use smallvec::smallvec; + fn same_file(a: RawFd, b: RawFd) -> bool { let stat1 = ::nix::sys::stat::fstat(a).unwrap(); let stat2 = ::nix::sys::stat::fstat(b).unwrap(); @@ -463,11 +465,11 @@ mod tests { let msg = Message { sender_id: 42, opcode: 7, - args: vec![ + args: smallvec![ Argument::Uint(3), Argument::Fixed(-89), - Argument::Str(CString::new(&b"I like trains!"[..]).unwrap()), - Argument::Array(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]), + Argument::Str(Box::new(CString::new(&b"I like trains!"[..]).unwrap())), + Argument::Array(vec![1, 2, 3, 4, 5, 6, 7, 8, 9].into()), Argument::Object(88), Argument::NewId(56), Argument::Int(-25), @@ -516,7 +518,7 @@ mod tests { let msg = Message { sender_id: 42, opcode: 7, - args: vec![ + args: smallvec![ Argument::Fd(1), // stdin Argument::Fd(0), // stdout ], @@ -557,15 +559,15 @@ mod tests { Message { sender_id: 42, opcode: 0, - args: vec![ + args: smallvec![ Argument::Int(42), - Argument::Str(CString::new(&b"I like trains"[..]).unwrap()), + Argument::Str(Box::new(CString::new(&b"I like trains"[..]).unwrap())), ], }, Message { sender_id: 42, opcode: 1, - args: vec![ + args: smallvec![ Argument::Fd(1), // stdin Argument::Fd(0), // stdout ], @@ -573,7 +575,7 @@ mod tests { Message { sender_id: 42, opcode: 2, - args: vec![ + args: smallvec![ Argument::Uint(3), Argument::Fd(2), // stderr ], @@ -625,9 +627,9 @@ mod tests { let msg = Message { sender_id: 2, opcode: 0, - args: vec![ + args: smallvec![ Argument::Uint(18), - Argument::Str(CString::new(&b"wl_shell"[..]).unwrap()), + Argument::Str(Box::new(CString::new(&b"wl_shell"[..]).unwrap())), Argument::Uint(1), ], }; diff --git a/wayland-commons/src/wire.rs b/wayland-commons/src/wire.rs index f6a83b1f689..89c88bbe25c 100644 --- a/wayland-commons/src/wire.rs +++ b/wayland-commons/src/wire.rs @@ -7,6 +7,16 @@ use std::ptr; use nix::errno::Errno; use nix::{Error as NixError, Result as NixResult}; +use smallvec::SmallVec; + +// The value of 4 is chosen for the following reasons: +// - almost all messages have 4 arguments or less +// - there are some potentially spammy events that have 3/4 arguments (wl_touch.move has 4 for example) +// +// This brings the size of Message to 11*usize (instead of 4*usize with a regular vec), but eliminates +// almost all allocations that may occur during the processing of messages, both client-side and server-side. +const INLINE_ARGS: usize = 4; + /// Wire metadata of a given message #[derive(Copy, Clone, Debug)] pub struct MessageDesc { @@ -43,6 +53,7 @@ pub enum ArgumentType { /// Enum of possible argument as recognized by the wire, including values #[derive(Clone, PartialEq, Debug)] +#[allow(clippy::box_vec)] pub enum Argument { /// i32 Int(i32), @@ -51,13 +62,19 @@ pub enum Argument { /// fixed point, 1/256 precision Fixed(i32), /// CString - Str(CString), + /// + /// The value is boxed to reduce the stack size of Argument. The performance + /// impact is negligible as `string` arguments are pretty rare in the protocol. + Str(Box), /// id of a wayland object Object(u32), /// id of a newly created wayland object NewId(u32), /// Vec - Array(Vec), + /// + /// The value is boxed to reduce the stack size of Argument. The performance + /// impact is negligible as `array` arguments are pretty rare in the protocol. + Array(Box>), /// RawFd Fd(RawFd), } @@ -86,7 +103,7 @@ pub struct Message { /// Opcode of the message pub opcode: u16, /// Arguments of the message - pub args: Vec, + pub args: SmallVec<[Argument; INLINE_ARGS]>, } /// Error generated when trying to serialize a message into buffers @@ -296,7 +313,7 @@ impl Message { read_array_from_payload(front as usize, tail).and_then(|(v, rest)| { tail = rest; match CStr::from_bytes_with_nul(v) { - Ok(s) => Ok(Argument::Str(s.into())), + Ok(s) => Ok(Argument::Str(Box::new(s.into()))), Err(_) => Err(MessageParseError::Malformed), } }) @@ -306,7 +323,7 @@ impl Message { ArgumentType::Array => { read_array_from_payload(front as usize, tail).map(|(v, rest)| { tail = rest; - Argument::Array(v.into()) + Argument::Array(Box::new(v.into())) }) } ArgumentType::Fd => unreachable!(), @@ -317,7 +334,7 @@ impl Message { Err(MessageParseError::MissingData) } }) - .collect::, MessageParseError>>()?; + .collect::, MessageParseError>>()?; let msg = Message { sender_id, @@ -391,6 +408,7 @@ impl Drop for FdStore { #[cfg(test)] mod tests { use super::*; + use smallvec::smallvec; #[test] fn into_from_raw_cycle() { @@ -400,11 +418,11 @@ mod tests { let msg = Message { sender_id: 42, opcode: 7, - args: vec![ + args: smallvec![ Argument::Uint(3), Argument::Fixed(-89), - Argument::Str(CString::new(&b"I like trains!"[..]).unwrap()), - Argument::Array(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]), + Argument::Str(Box::new(CString::new(&b"I like trains!"[..]).unwrap())), + Argument::Array(vec![1, 2, 3, 4, 5, 6, 7, 8, 9].into()), Argument::Object(88), Argument::NewId(56), Argument::Int(-25), diff --git a/wayland-protocols/src/protocol_macro.rs b/wayland-protocols/src/protocol_macro.rs index 66c52f85d25..a45db9e817e 100644 --- a/wayland-protocols/src/protocol_macro.rs +++ b/wayland-protocols/src/protocol_macro.rs @@ -19,6 +19,7 @@ macro_rules! wayland_protocol( pub(crate) use wayland_commons::map::{Object, ObjectMetadata}; pub(crate) use wayland_commons::{Interface, MessageGroup}; pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message}; + pub(crate) use wayland_commons::smallvec; pub(crate) use wayland_client::protocol::{$($import),*}; pub(crate) use wayland_client::sys; $( @@ -34,6 +35,7 @@ macro_rules! wayland_protocol( pub(crate) use wayland_commons::map::{Object, ObjectMetadata}; pub(crate) use wayland_commons::{Interface, MessageGroup}; pub(crate) use wayland_commons::wire::{Argument, MessageDesc, ArgumentType, Message}; + pub(crate) use wayland_commons::smallvec; pub(crate) use wayland_server::protocol::{$($import),*}; pub(crate) use wayland_server::sys; $( diff --git a/wayland-scanner/src/c_code_gen.rs b/wayland-scanner/src/c_code_gen.rs index d13bccad9d5..4afd6f3afcb 100644 --- a/wayland-scanner/src/c_code_gen.rs +++ b/wayland-scanner/src/c_code_gen.rs @@ -64,7 +64,7 @@ pub(crate) fn generate_protocol_client(protocol: Protocol) -> TokenStream { use std::os::raw::c_char; use super::{ Proxy, AnonymousObject, Interface, MessageGroup, MessageDesc, ArgumentType, - Object, Message, Argument, ObjectMetadata, types_null, NULLPTR, Main, + Object, Message, Argument, ObjectMetadata, types_null, NULLPTR, Main, smallvec, }; use super::sys::common::{wl_interface, wl_array, wl_argument, wl_message}; use super::sys::client::*; @@ -148,7 +148,7 @@ pub(crate) fn generate_protocol_server(protocol: Protocol) -> TokenStream { pub mod #mod_name { use std::os::raw::c_char; use super::{ - Resource, AnonymousObject, Interface, MessageGroup, MessageDesc, Main, + Resource, AnonymousObject, Interface, MessageGroup, MessageDesc, Main, smallvec, ArgumentType, Object, Message, Argument, ObjectMetadata, types_null, NULLPTR }; use super::sys::common::{wl_argument, wl_interface, wl_array, wl_message}; diff --git a/wayland-scanner/src/common_gen.rs b/wayland-scanner/src/common_gen.rs index ff9c0493b5a..6c0306e9bff 100644 --- a/wayland-scanner/src/common_gen.rs +++ b/wayland-scanner/src/common_gen.rs @@ -419,9 +419,9 @@ pub(crate) fn gen_messagegroup( Type::Fixed => quote!((val as f64) / 256.), Type::Array => { if arg.allow_null { - quote!(if val.len() == 0 { None } else { Some(val) }) + quote!(if val.len() == 0 { None } else { Some(*val) }) } else { - quote!(val) + quote!(*val) } } Type::String => { @@ -550,25 +550,25 @@ pub(crate) fn gen_messagegroup( Type::String => { if arg.allow_null { quote! { - Argument::Str(unsafe { + Argument::Str(Box::new(unsafe { ::std::ffi::CString::from_vec_unchecked( #arg_ident.map(Into::into).unwrap_or_else(Vec::new), ) - }) + })) } } else { quote! { - Argument::Str(unsafe { + Argument::Str(Box::new(unsafe { ::std::ffi::CString::from_vec_unchecked(#arg_ident.into()) - }) + })) } } } Type::Array => { if arg.allow_null { - quote!(Argument::Array(#arg_ident.unwrap_or_else(Vec::new))) + quote!(Argument::Array(Box::new(#arg_ident.unwrap_or_else(Vec::new)))) } else { - quote!(Argument::Array(#arg_ident)) + quote!(Argument::Array(Box::new(#arg_ident))) } } Type::Fd => quote!(Argument::Fd(#arg_ident)), @@ -587,9 +587,9 @@ pub(crate) fn gen_messagegroup( quote!(#arg_ident.2.id()) }; quote! { - Argument::Str(unsafe { + Argument::Str(Box::new(unsafe { ::std::ffi::CString::from_vec_unchecked(#arg_ident.0.into()) - }), + })), Argument::Uint(#arg_ident.1), Argument::NewId(#id) } @@ -609,7 +609,7 @@ pub(crate) fn gen_messagegroup( quote!(#pattern => Message { sender_id: sender_id, opcode: #opcode_value, - args: vec![ + args: smallvec![ #(#args_values,)* ], }) diff --git a/wayland-server/src/lib.rs b/wayland-server/src/lib.rs index d40daf5df9b..bbb2b146602 100644 --- a/wayland-server/src/lib.rs +++ b/wayland-server/src/lib.rs @@ -120,6 +120,7 @@ pub mod protocol { pub(crate) use crate::{AnonymousObject, Main, Resource, ResourceMap}; pub(crate) use wayland_commons::map::{Object, ObjectMetadata}; + pub(crate) use wayland_commons::smallvec; pub(crate) use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc}; pub(crate) use wayland_commons::{Interface, MessageGroup}; pub(crate) use wayland_sys as sys; diff --git a/wayland-server/src/rust_imp/clients.rs b/wayland-server/src/rust_imp/clients.rs index 049b9a9bca8..13325171ce2 100644 --- a/wayland-server/src/rust_imp/clients.rs +++ b/wayland-server/src/rust_imp/clients.rs @@ -11,7 +11,7 @@ use nix::Result as NixResult; use wayland_commons::map::{Object, ObjectMap, ObjectMetadata, SERVER_ID_LIMIT}; use wayland_commons::socket::{BufferedSocket, Socket}; use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc, MessageParseError}; -use wayland_commons::ThreadGuard; +use wayland_commons::{smallvec, ThreadGuard}; use crate::{Interface, UserDataMap}; @@ -89,7 +89,7 @@ impl ClientConnection { self.write_message(&Message { sender_id: 1, opcode: 1, - args: vec![Argument::Uint(id)], + args: smallvec![Argument::Uint(id)], }) } else { Ok(()) @@ -271,10 +271,10 @@ impl ClientInner { let _ = data.write_message(&Message { sender_id: 1, opcode: 0, - args: vec![ + args: smallvec![ Argument::Object(object), Argument::Uint(error_code), - Argument::Str(CString::new(msg).unwrap()), + Argument::Str(Box::new(CString::new(msg).unwrap())), ], }); } diff --git a/wayland-server/src/rust_imp/globals.rs b/wayland-server/src/rust_imp/globals.rs index baea97dea0d..9fa7da5b92b 100644 --- a/wayland-server/src/rust_imp/globals.rs +++ b/wayland-server/src/rust_imp/globals.rs @@ -3,6 +3,7 @@ use std::ffi::CString; use std::rc::Rc; use wayland_commons::map::Object; +use wayland_commons::smallvec; use wayland_commons::wire::{Argument, Message}; use crate::{Interface, Main, Resource}; @@ -214,9 +215,9 @@ fn send_global_msg(reg: &(u32, ClientInner), global_id: u32, interface: CString, let _ = clientconn.write_message(&Message { sender_id: reg.0, opcode: 0, - args: vec![ + args: smallvec![ Argument::Uint(global_id), - Argument::Str(interface), + Argument::Str(Box::new(interface)), Argument::Uint(version), ], }); @@ -261,7 +262,7 @@ fn send_destroyed_global( let _ = clientconn.write_message(&Message { sender_id: id, opcode: 1, - args: vec![Argument::Uint(global_id)], + args: smallvec![Argument::Uint(global_id)], }); } } @@ -271,7 +272,7 @@ fn send_destroyed_global( let _ = clientconn.write_message(&Message { sender_id: id, opcode: 1, - args: vec![Argument::Uint(global_id)], + args: smallvec![Argument::Uint(global_id)], }); } } diff --git a/wayland-server/src/rust_imp/mod.rs b/wayland-server/src/rust_imp/mod.rs index 8ff4f5452f9..45fd71bf6d5 100644 --- a/wayland-server/src/rust_imp/mod.rs +++ b/wayland-server/src/rust_imp/mod.rs @@ -66,6 +66,7 @@ impl ResourceMap { /* * Dispatching logic */ +#[allow(clippy::large_enum_variant)] pub(crate) enum Dispatched { Yes, NoDispatch(Message, ResourceInner),