wayland-scanner-0.31.6/.cargo_vcs_info.json0000644000000001550000000000100142120ustar { "git": { "sha1": "48b04f19ecf747104533f536ddf626e561346d19" }, "path_in_vcs": "wayland-scanner" }wayland-scanner-0.31.6/CHANGELOG.md000064400000000000000000000026201046102023000146120ustar 00000000000000# CHANGELOG: wayland-scanner ## Unreleased - Update `quick-xml` to 0.37 ## 0.31.5 -- 2024-09-04 - Update `quick-xml` to 0.36 - Allow `` in XML input ## 0.31.3 -- 2024-07-03 - Update `quick-xml` to 0.34 ## 0.31.2 -- 2024-05-30 - Use wrapper type implementing `Sync` instead of `static mut`s. - Add headerless xml file parsing possibility for `parse` function. ## 0.31.1 -- 2024-01-29 - Include an `std::convert::Infallible` in hidden `__phantom_lifetime` enum variants, so they're explicitly unconstructable. ## 0.31.0 -- 2023-09-02 #### Breaking changes - Bump bitflags to 2.0 - Remove `io-lifetimes` from the generated code following wayland-backend 0.3 dropping it. - Generate `BorrowedFd<'_>` arguments instead of `RawFd` # 0.30.1 -- 2023-06-17 - Generated protocol object types now implement `Borrow` and `Hash` ## 0.30.0 -- 2022-12-27 ## 0.30.0-beta.10 #### Additions - An `opcode()` method is added to message enums to retrive the opcode associated with a message variant. ## 0.30.0-beta.9 - Migrate from xml-rs to quick-xml ## 0.30.0-beta.6 - Generated enums now derive `Ord` and `Hash`. - The scanner now generates constants for the opcode values of the protocol messages. ## 0.30.0-alpha1 Full rework of the crate together of the reworks of `wayland-client` and `wayland-server`. The code generation is now achieved using procedural macros rather than build scripts. wayland-scanner-0.31.6/Cargo.lock0000644000000027240000000000100121710ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" dependencies = [ "memchr", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "similar" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "unicode-ident" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "wayland-scanner" version = "0.31.6" dependencies = [ "proc-macro2", "quick-xml", "quote", "similar", ] wayland-scanner-0.31.6/Cargo.toml0000644000000025410000000000100122110ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.65" name = "wayland-scanner" version = "0.31.6" authors = ["Elinor Berger "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Wayland Scanner for generating rust APIs from XML wayland protocol files." documentation = "https://docs.rs/wayland-scanner/" readme = "README.md" keywords = [ "wayland", "codegen", ] categories = [ "gui", "api-bindings", ] license = "MIT" repository = "https://github.com/smithay/wayland-rs" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [lib] name = "wayland_scanner" path = "src/lib.rs" proc-macro = true [dependencies.proc-macro2] version = "1.0.11" [dependencies.quick-xml] version = "0.37.0" [dependencies.quote] version = "1.0" [dev-dependencies.similar] version = "2" wayland-scanner-0.31.6/Cargo.toml.orig000064400000000000000000000012261046102023000156710ustar 00000000000000[package] name = "wayland-scanner" version = "0.31.6" authors = ["Elinor Berger "] repository = "https://github.com/smithay/wayland-rs" documentation = "https://docs.rs/wayland-scanner/" description = "Wayland Scanner for generating rust APIs from XML wayland protocol files." license = "MIT" categories = ["gui", "api-bindings"] keywords = ["wayland", "codegen"] edition = "2021" rust-version = "1.65" readme = "README.md" [lib] proc-macro = true [dependencies] proc-macro2 = "1.0.11" quote = "1.0" quick-xml = "0.37.0" [dev-dependencies] similar = "2" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] wayland-scanner-0.31.6/LICENSE.txt000064400000000000000000000020411046102023000146210ustar 00000000000000Copyright (c) 2015 Elinor Berger Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. wayland-scanner-0.31.6/README.md000064400000000000000000000016041046102023000142610ustar 00000000000000[![crates.io](https://img.shields.io/crates/v/wayland-scanner.svg)](https://crates.io/crates/wayland-scanner) [![docs.rs](https://docs.rs/wayland-scanner/badge.svg)](https://docs.rs/wayland-scanner) [![Continuous Integration](https://github.com/Smithay/wayland-rs/workflows/Continuous%20Integration/badge.svg)](https://github.com/Smithay/wayland-rs/actions?query=workflow%3A%22Continuous+Integration%22) [![codecov](https://codecov.io/gh/Smithay/wayland-rs/branch/master/graph/badge.svg)](https://codecov.io/gh/Smithay/wayland-rs) # wayland-scanner This crate provides procedural macros for generating the rust code associated with a Wayland XML protocol specification, for use with the `wayland-client`, `wayland-server` and `wayland-backend` crates. Before trying to use this crate, you may check if the protocol extension you want to use is not already exposed in the `wayland-protocols` crate.wayland-scanner-0.31.6/src/c_interfaces.rs000064400000000000000000000141401046102023000165630ustar 00000000000000use std::cmp; use proc_macro2::{Literal, TokenStream}; use quote::{format_ident, quote}; use crate::protocol::{Interface, Message, Protocol, Type}; pub(crate) fn generate_interfaces_prefix(protocol: &Protocol) -> TokenStream { let longest_nulls = protocol.interfaces.iter().fold(0, |max, interface| { let request_longest_null = interface.requests.iter().fold(0, |max, request| { if request.all_null() { cmp::max(request.args.len(), max) } else { max } }); let events_longest_null = interface.events.iter().fold(0, |max, event| { if event.all_null() { cmp::max(event.args.len(), max) } else { max } }); cmp::max(max, cmp::max(request_longest_null, events_longest_null)) }); let types_null_len = Literal::usize_unsuffixed(longest_nulls); quote! { use std::ptr::null; struct SyncWrapper(T); unsafe impl Sync for SyncWrapper {} static types_null: SyncWrapper<[*const wayland_backend::protocol::wl_interface; #types_null_len]> = SyncWrapper([ null::(); #types_null_len ]); } } pub(crate) fn generate_interface(interface: &Interface) -> TokenStream { let requests = gen_messages(interface, &interface.requests, "requests"); let events = gen_messages(interface, &interface.events, "events"); let interface_ident = format_ident!("{}_interface", interface.name); let name_value = null_terminated_byte_string_literal(&interface.name); let version_value = Literal::i32_unsuffixed(interface.version as i32); let request_count_value = Literal::i32_unsuffixed(interface.requests.len() as i32); let requests_value = if interface.requests.is_empty() { quote! { null::() } } else { let requests_ident = format_ident!("{}_requests", interface.name); quote! { #requests_ident.0.as_ptr() } }; let event_count_value = Literal::i32_unsuffixed(interface.events.len() as i32); let events_value = if interface.events.is_empty() { quote! { null::() } } else { let events_ident = format_ident!("{}_events", interface.name); quote! { #events_ident.0.as_ptr() } }; quote! { #requests #events pub static #interface_ident: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: #name_value as *const u8 as *const std::os::raw::c_char, version: #version_value, request_count: #request_count_value, requests: #requests_value, event_count: #event_count_value, events: #events_value, }; } } fn gen_messages(interface: &Interface, messages: &[Message], which: &str) -> TokenStream { if messages.is_empty() { return TokenStream::new(); } let types_arrays = messages.iter().filter_map(|msg| { if msg.all_null() { None } else { let array_ident = format_ident!("{}_{}_{}_types", interface.name, which, msg.name); let array_len = Literal::usize_unsuffixed(msg.args.len()); let array_values = msg.args.iter().map(|arg| match (arg.typ, &arg.interface) { (Type::Object, &Some(ref inter)) | (Type::NewId, &Some(ref inter)) => { let interface_ident =format_ident!("{}_interface", inter); quote! { &#interface_ident as *const wayland_backend::protocol::wl_interface } } _ => quote! { null::() }, }); Some(quote! { static #array_ident: SyncWrapper<[*const wayland_backend::protocol::wl_interface; #array_len]> = SyncWrapper([ #(#array_values,)* ]); }) } }); let message_array_ident = format_ident!("{}_{}", interface.name, which); let message_array_len = Literal::usize_unsuffixed(messages.len()); let message_array_values = messages.iter().map(|msg| { let name_value = null_terminated_byte_string_literal(&msg.name); let signature_value = Literal::byte_string(&message_signature(msg)); let types_ident = if msg.all_null() { format_ident!("types_null") } else { format_ident!("{}_{}_{}_types", interface.name, which, msg.name) }; quote! { wayland_backend::protocol::wl_message { name: #name_value as *const u8 as *const std::os::raw::c_char, signature: #signature_value as *const u8 as *const std::os::raw::c_char, types: #types_ident.0.as_ptr(), } } }); quote! { #(#types_arrays)* static #message_array_ident: SyncWrapper<[wayland_backend::protocol::wl_message; #message_array_len]> = SyncWrapper([ #(#message_array_values,)* ]); } } fn message_signature(msg: &Message) -> Vec { let mut res = Vec::new(); if msg.since > 1 { res.extend_from_slice(msg.since.to_string().as_bytes()); } for arg in &msg.args { if arg.typ.nullable() && arg.allow_null { res.push(b'?'); } match arg.typ { Type::NewId => { if arg.interface.is_none() { res.extend_from_slice(b"su"); } res.push(b'n'); } Type::Uint => res.push(b'u'), Type::Fixed => res.push(b'f'), Type::String => res.push(b's'), Type::Object => res.push(b'o'), Type::Array => res.push(b'a'), Type::Fd => res.push(b'h'), Type::Int => res.push(b'i'), _ => {} } } res.push(0); res } pub fn null_terminated_byte_string_literal(string: &str) -> Literal { let mut val = Vec::with_capacity(string.len() + 1); val.extend_from_slice(string.as_bytes()); val.push(0); Literal::byte_string(&val) } wayland-scanner-0.31.6/src/client_gen.rs000064400000000000000000000324501046102023000162510ustar 00000000000000use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use crate::{ protocol::{Interface, Protocol, Type}, util::{description_to_doc_attr, dotted_to_relname, is_keyword, snake_to_camel, to_doc_attr}, Side, }; pub fn generate_client_objects(protocol: &Protocol) -> TokenStream { protocol.interfaces.iter().map(generate_objects_for).collect() } fn generate_objects_for(interface: &Interface) -> TokenStream { let mod_name = Ident::new(&interface.name, Span::call_site()); let mod_doc = interface.description.as_ref().map(description_to_doc_attr); let iface_name = Ident::new(&snake_to_camel(&interface.name), Span::call_site()); let iface_const_name = format_ident!("{}_INTERFACE", interface.name.to_ascii_uppercase()); 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( &format_ident!("Request"), Side::Client, false, &interface.requests, ); let events = crate::common::gen_message_enum( &format_ident!("Event"), Side::Client, true, &interface.events, ); let parse_body = crate::common::gen_parse_body(interface, Side::Client); let write_body = crate::common::gen_write_body(interface, Side::Client); let methods = gen_methods(interface); let event_ref = if interface.events.is_empty() { "This interface has no events." } else { "See also the [Event] enum for this interface." }; let docs = match &interface.description { Some((short, long)) => format!("{}\n\n{}\n\n{}", short, long, event_ref), None => format!("{}\n\n{}", interface.name, event_ref), }; let doc_attr = to_doc_attr(&docs); quote! { #mod_doc pub mod #mod_name { use std::sync::Arc; use std::os::unix::io::OwnedFd; use super::wayland_client::{ backend::{ Backend, WeakBackend, smallvec, ObjectData, ObjectId, InvalidId, protocol::{WEnum, Argument, Message, Interface, same_interface} }, QueueProxyData, Proxy, Connection, Dispatch, QueueHandle, DispatchError, Weak, }; #enums #sinces #requests #events #doc_attr #[derive(Debug, Clone)] pub struct #iface_name { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for #iface_name { fn eq(&self, other: &#iface_name) -> bool { self.id == other.id } } impl std::cmp::Eq for #iface_name {} impl PartialEq> for #iface_name { fn eq(&self, other: &Weak<#iface_name>) -> bool { self.id == other.id() } } impl std::borrow::Borrow for #iface_name { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for #iface_name { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for #iface_name { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface{ &super::#iface_const_name } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(#iface_name { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { #iface_name { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event(conn: &Connection, msg: Message) -> Result<(Self, Self::Event), DispatchError> { #parse_body } fn write_request<'a>(&self, conn: &Connection, msg: Self::Request<'a>) -> Result<(Message>, Option<(&'static Interface, u32)>), InvalidId> { #write_body } } impl #iface_name { #methods } } } } fn gen_methods(interface: &Interface) -> TokenStream { interface.requests.iter().map(|request| { let created_interface = request.args.iter().find(|arg| arg.typ == Type::NewId).map(|arg| &arg.interface); let method_name = format_ident!("{}{}", if is_keyword(&request.name) { "_" } else { "" }, request.name); let enum_variant = Ident::new(&snake_to_camel(&request.name), Span::call_site()); let fn_args = request.args.iter().flat_map(|arg| { if arg.typ == Type::NewId { if arg.interface.is_none() { // the new_id argument of a bind-like method // it shoudl expand as a (interface, type) tuple, but the type is already handled by // the prototype type parameter, so just put a version here return Some(quote! { version: u32 }); } else { // this is a regular new_id, skip it return None; } } let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); let arg_type = if let Some(ref enu) = arg.enum_ { let enum_type = dotted_to_relname(enu); quote! { #enum_type } } else { match arg.typ { Type::Uint => quote! { u32 }, Type::Int => quote! { i32 }, 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::BorrowedFd<'_> }, Type::Object => { let iface = arg.interface.as_ref().unwrap(); let iface_mod = Ident::new(iface, Span::call_site()); let iface_type = Ident::new(&snake_to_camel(iface), Span::call_site()); if arg.allow_null { quote! { Option<&super::#iface_mod::#iface_type> } } else { quote! { &super::#iface_mod::#iface_type } } }, Type::NewId => unreachable!(), Type::Destructor => panic!("An argument cannot have type \"destructor\"."), } }; Some(quote! { #arg_name: #arg_type }) }); let enum_args = request.args.iter().flat_map(|arg| { let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); if arg.enum_.is_some() { Some(quote! { #arg_name: WEnum::Value(#arg_name) }) } else if arg.typ == Type::NewId { if arg.interface.is_none() { Some(quote! { #arg_name: (I::interface(), version) }) } else { None } } else if arg.typ == Type::Object { if arg.allow_null { Some(quote! { #arg_name: #arg_name.cloned() }) } else { Some(quote! { #arg_name: #arg_name.clone() }) } } else { Some(quote! { #arg_name }) } }); let doc_attr = request .description .as_ref() .map(description_to_doc_attr); match created_interface { Some(Some(ref created_interface)) => { // a regular creating request let created_iface_mod = Ident::new(created_interface, Span::call_site()); let created_iface_type = Ident::new(&snake_to_camel(created_interface), Span::call_site()); quote! { #doc_attr #[allow(clippy::too_many_arguments)] pub fn #method_name + 'static>(&self, #(#fn_args,)* qh: &QueueHandle, udata: U) -> super::#created_iface_mod::#created_iface_type { self.send_constructor( Request::#enum_variant { #(#enum_args),* }, qh.make_data::(udata), ).unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } }, Some(None) => { // a bind-like request quote! { #doc_attr #[allow(clippy::too_many_arguments)] pub fn #method_name + 'static>(&self, #(#fn_args,)* qh: &QueueHandle, udata: U) -> I { self.send_constructor( Request::#enum_variant { #(#enum_args),* }, qh.make_data::(udata), ).unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } }, None => { // a non-creating request quote! { #doc_attr #[allow(clippy::too_many_arguments)] pub fn #method_name(&self, #(#fn_args),*) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request( self, Request::#enum_variant { #(#enum_args),* }, None ); } } } } }).collect() } #[cfg(test)] mod tests { #[test] fn client_gen() { let protocol_file = std::fs::File::open("./tests/scanner_assets/test-protocol.xml").unwrap(); let protocol_parsed = crate::parse::parse(protocol_file); let generated: String = super::generate_client_objects(&protocol_parsed).to_string(); let generated = crate::format_rust_code(&generated); let reference = std::fs::read_to_string("./tests/scanner_assets/test-client-code.rs").unwrap(); let reference = crate::format_rust_code(&reference); if reference != generated { let diff = similar::TextDiff::from_lines(&reference, &generated); print!("{}", diff.unified_diff().context_radius(10).header("reference", "generated")); panic!("Generated does not match reference!") } } } wayland-scanner-0.31.6/src/common.rs000064400000000000000000000640101046102023000154270ustar 00000000000000use std::fmt::Write; use proc_macro2::{Ident, Literal, Span, TokenStream}; use quote::{format_ident, quote, ToTokens}; use crate::{protocol::*, util::*, Side}; pub(crate) fn generate_enums_for(interface: &Interface) -> TokenStream { interface.enums.iter().map(ToTokens::into_token_stream).collect() } impl ToTokens for Enum { fn to_tokens(&self, tokens: &mut TokenStream) { let enum_decl; let enum_impl; let doc_attr = self.description.as_ref().map(description_to_doc_attr); let ident = Ident::new(&snake_to_camel(&self.name), Span::call_site()); if self.bitfield { let entries = self.entries.iter().map(|entry| { let doc_attr = entry .description .as_ref() .map(description_to_doc_attr) .or_else(|| entry.summary.as_ref().map(|s| to_doc_attr(s))); let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; let ident = format_ident!("{}{}", prefix, snake_to_camel(&entry.name)); let value = Literal::u32_unsuffixed(entry.value); quote! { #doc_attr const #ident = #value; } }); enum_decl = quote! { bitflags::bitflags! { #doc_attr #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct #ident: u32 { #(#entries)* } } }; enum_impl = quote! { impl std::convert::TryFrom for #ident { type Error = (); fn try_from(val: u32) -> Result<#ident, ()> { #ident::from_bits(val).ok_or(()) } } impl std::convert::From<#ident> for u32 { fn from(val: #ident) -> u32 { val.bits() } } }; } else { let variants = self.entries.iter().map(|entry| { let doc_attr = entry .description .as_ref() .map(description_to_doc_attr) .or_else(|| entry.summary.as_ref().map(|s| to_doc_attr(s))); let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; let variant = format_ident!("{}{}", prefix, snake_to_camel(&entry.name)); let value = Literal::u32_unsuffixed(entry.value); quote! { #doc_attr #variant = #value } }); enum_decl = quote! { #doc_attr #[repr(u32)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] pub enum #ident { #(#variants,)* } }; let match_arms = self.entries.iter().map(|entry| { let value = Literal::u32_unsuffixed(entry.value); let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; let variant = format_ident!("{}{}", prefix, snake_to_camel(&entry.name)); quote! { #value => Ok(#ident::#variant) } }); enum_impl = quote! { impl std::convert::TryFrom for #ident { type Error = (); fn try_from(val: u32) -> Result<#ident, ()> { match val { #(#match_arms,)* _ => Err(()) } } } impl std::convert::From<#ident> for u32 { fn from(val: #ident) -> u32 { val as u32 } } }; } enum_decl.to_tokens(tokens); enum_impl.to_tokens(tokens); } } pub(crate) fn gen_msg_constants(requests: &[Message], events: &[Message]) -> TokenStream { let req_constants = requests.iter().enumerate().map(|(opcode, msg)| { let since_cstname = format_ident!("REQ_{}_SINCE", msg.name.to_ascii_uppercase()); let opcode_cstname = format_ident!("REQ_{}_OPCODE", msg.name.to_ascii_uppercase()); let since = msg.since; let opcode = opcode as u16; quote! { /// The minimal object version supporting this request pub const #since_cstname: u32 = #since; /// The wire opcode for this request pub const #opcode_cstname: u16 = #opcode; } }); let evt_constants = events.iter().enumerate().map(|(opcode, msg)| { let since_cstname = format_ident!("EVT_{}_SINCE", msg.name.to_ascii_uppercase()); let opcode_cstname = format_ident!("EVT_{}_OPCODE", msg.name.to_ascii_uppercase()); let since = msg.since; let opcode = opcode as u16; quote! { /// The minimal object version supporting this event pub const #since_cstname: u32 = #since; /// The wire opcode for this event pub const #opcode_cstname: u16 = #opcode; } }); quote! { #(#req_constants)* #(#evt_constants)* } } pub(crate) fn gen_message_enum( name: &Ident, side: Side, receiver: bool, messages: &[Message], ) -> TokenStream { let variants = messages .iter() .map(|msg| { let mut docs = String::new(); if let Some((ref short, ref long)) = msg.description { write!(docs, "{}\n\n{}\n", short, long.trim()).unwrap(); } if let Some(Type::Destructor) = msg.typ { write!( docs, "\nThis is a destructor, once {} this object cannot be used any longer.", if receiver { "received" } else { "sent" }, ) .unwrap() } if msg.since > 1 { write!(docs, "\nOnly available since version {} of the interface", msg.since) .unwrap(); } let doc_attr = to_doc_attr(&docs); let msg_name = Ident::new(&snake_to_camel(&msg.name), Span::call_site()); let msg_variant_decl = if msg.args.is_empty() { msg_name.into_token_stream() } else { let fields = msg.args.iter().flat_map(|arg| { let field_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); let field_type_inner = if let Some(ref enu) = arg.enum_ { let enum_type = dotted_to_relname(enu); quote! { WEnum<#enum_type> } } else { match arg.typ { Type::Uint => quote! { u32 }, Type::Int => quote! { i32 }, Type::Fixed => quote! { f64 }, Type::String => quote! { String }, Type::Array => quote! { Vec }, Type::Fd => { if receiver { quote! { OwnedFd } } else { quote! { std::os::unix::io::BorrowedFd<'a> } } } Type::Object => { if let Some(ref iface) = arg.interface { let iface_mod = Ident::new(iface, Span::call_site()); let iface_type = Ident::new(&snake_to_camel(iface), Span::call_site()); quote! { super::#iface_mod::#iface_type } } else if side == Side::Client { quote! { super::wayland_client::ObjectId } } else { quote! { super::wayland_server::ObjectId } } } Type::NewId if !receiver && side == Side::Client => { // Client-side sending does not have a pre-existing object // so skip serializing it if arg.interface.is_some() { return None; } else { quote! { (&'static Interface, u32) } } } Type::NewId => { if let Some(ref iface) = arg.interface { let iface_mod = Ident::new(iface, Span::call_site()); let iface_type = Ident::new(&snake_to_camel(iface), Span::call_site()); if receiver && side == Side::Server { quote! { New } } else { quote! { super::#iface_mod::#iface_type } } } else { // bind-like function if side == Side::Client { quote! { (String, u32, super::wayland_client::ObjectId) } } else { quote! { (String, u32, super::wayland_server::ObjectId) } } } } Type::Destructor => panic!("An argument cannot have type \"destructor\"."), } }; let field_type = if arg.allow_null { quote! { Option<#field_type_inner> } } else { field_type_inner.into_token_stream() }; let doc_attr = arg .description .as_ref() .map(description_to_doc_attr) .or_else(|| arg.summary.as_ref().map(|s| to_doc_attr(s))); Some(quote! { #doc_attr #field_name: #field_type }) }); quote! { #msg_name { #(#fields,)* } } }; quote! { #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()); let opcode = opcode as u16; if msg.args.is_empty() { quote! { #name::#msg_name => #opcode } } else { quote! { #name::#msg_name { .. } => #opcode } } }); // Placeholder to allow generic argument to be added later, without ABI // break. // TODO Use never type. let (generic, phantom_variant, phantom_case) = if !receiver { ( quote! { 'a }, quote! { #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible } }, quote! { #name::__phantom_lifetime { never, .. } => match never {} }, ) } else { (quote! {}, quote! {}, quote! {}) }; quote! { #[derive(Debug)] #[non_exhaustive] pub enum #name<#generic> { #(#variants,)* #phantom_variant } impl<#generic> #name<#generic> { #[doc="Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { #(#opcodes,)* #phantom_case } } } } } pub(crate) fn gen_parse_body(interface: &Interface, side: Side) -> TokenStream { let msgs = match side { Side::Client => &interface.events, Side::Server => &interface.requests, }; let object_type = Ident::new( match side { Side::Client => "Proxy", Side::Server => "Resource", }, Span::call_site(), ); let msg_type = Ident::new( match side { Side::Client => "Event", Side::Server => "Request", }, Span::call_site(), ); let match_arms = msgs.iter().enumerate().map(|(opcode, msg)| { let opcode = opcode as u16; let msg_name = Ident::new(&snake_to_camel(&msg.name), Span::call_site()); let args_pat = msg.args.iter().map(|arg| { let arg_name = Ident::new( &format!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name), Span::call_site(), ); match arg.typ { Type::Uint => quote!{ Some(Argument::Uint(#arg_name)) }, Type::Int => quote!{ Some(Argument::Int(#arg_name)) }, Type::String => quote!{ Some(Argument::Str(#arg_name)) }, Type::Fixed => quote!{ Some(Argument::Fixed(#arg_name)) }, Type::Array => quote!{ Some(Argument::Array(#arg_name)) }, Type::Object => quote!{ Some(Argument::Object(#arg_name)) }, Type::NewId => quote!{ Some(Argument::NewId(#arg_name)) }, Type::Fd => quote!{ Some(Argument::Fd(#arg_name)) }, Type::Destructor => panic!("Argument {}.{}.{} has type destructor ?!", interface.name, msg.name, arg.name), } }); let args_iter = msg.args.iter().map(|_| quote!{ arg_iter.next() }); let arg_names = msg.args.iter().map(|arg| { let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); if arg.enum_.is_some() { quote! { #arg_name: From::from(#arg_name as u32) } } else { match arg.typ { Type::Uint | Type::Int | Type::Fd => quote!{ #arg_name }, Type::Fixed => quote!{ #arg_name: (#arg_name as f64) / 256.}, Type::String => { if arg.allow_null { quote! { #arg_name: #arg_name.as_ref().map(|s| String::from_utf8_lossy(s.as_bytes()).into_owned()) } } else { quote! { #arg_name: String::from_utf8_lossy(#arg_name.as_ref().unwrap().as_bytes()).into_owned() } } }, Type::Object => { let create_proxy = if let Some(ref created_interface) = arg.interface { let created_iface_mod = Ident::new(created_interface, Span::call_site()); let created_iface_type = Ident::new(&snake_to_camel(created_interface), Span::call_site()); quote! { match ::from_id(conn, #arg_name.clone()) { Ok(p) => p, Err(_) => return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode }), } } } else { quote! { #arg_name.clone() } }; if arg.allow_null { quote! { #arg_name: if #arg_name.is_null() { None } else { Some(#create_proxy) } } } else { quote! { #arg_name: #create_proxy } } }, Type::NewId => { let create_proxy = if let Some(ref created_interface) = arg.interface { let created_iface_mod = Ident::new(created_interface, Span::call_site()); let created_iface_type = Ident::new(&snake_to_camel(created_interface), Span::call_site()); quote! { match ::from_id(conn, #arg_name.clone()) { Ok(p) => p, Err(_) => return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } } else if side == Side::Server { quote! { New::wrap(#arg_name.clone()) } } else { quote! { #arg_name.clone() } }; if arg.allow_null { if side == Side::Server { quote! { #arg_name: if #arg_name.is_null() { None } else { Some(New::wrap(#create_proxy)) } } } else { quote! { #arg_name: if #arg_name.is_null() { None } else { Some(#create_proxy) } } } } else if side == Side::Server { quote! { #arg_name: New::wrap(#create_proxy) } } else { quote! { #arg_name: #create_proxy } } }, Type::Array => { if arg.allow_null { quote! { if #arg_name.len() == 0 { None } else { Some(*#arg_name) } } } else { quote! { #arg_name: *#arg_name } } }, Type::Destructor => unreachable!(), } } }); quote! { #opcode => { if let (#(#args_pat),*) = (#(#args_iter),*) { Ok((me, #msg_type::#msg_name { #(#arg_names),* })) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode }) } } } }); quote! { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { #(#match_arms),* _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode }), } } } pub(crate) fn gen_write_body(interface: &Interface, side: Side) -> TokenStream { let msgs = match side { Side::Client => &interface.requests, Side::Server => &interface.events, }; let msg_type = Ident::new( match side { Side::Client => "Request", Side::Server => "Event", }, Span::call_site(), ); let arms = msgs.iter().enumerate().map(|(opcode, msg)| { let msg_name = Ident::new(&snake_to_camel(&msg.name), Span::call_site()); let opcode = opcode as u16; let arg_names = msg.args.iter().flat_map(|arg| { if arg.typ == Type::NewId && arg.interface.is_some() && side == Side::Client { None } else { Some(format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name)) } }); let mut child_spec = None; let args = msg.args.iter().flat_map(|arg| { let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); match arg.typ { Type::Int => vec![if arg.enum_.is_some() { quote!{ Argument::Int(Into::::into(#arg_name) as i32) } } else { quote!{ Argument::Int(#arg_name) } }], Type::Uint => vec![if arg.enum_.is_some() { quote!{ Argument::Uint(#arg_name.into()) } } else { quote!{ Argument::Uint(#arg_name) } }], Type::Fd => vec![quote!{ Argument::Fd(#arg_name) }], Type::Fixed => vec![quote! { Argument::Fixed((#arg_name * 256.) as i32) }], Type::Object => if arg.allow_null { if side == Side::Server { vec![quote! { if let Some(obj) = #arg_name { Argument::Object(Resource::id(&obj)) } else { Argument::Object(ObjectId::null()) } }] } else { vec![quote! { if let Some(obj) = #arg_name { Argument::Object(Proxy::id(&obj)) } else { Argument::Object(ObjectId::null()) } }] } } else if side == Side::Server { vec![quote!{ Argument::Object(Resource::id(&#arg_name)) }] } else { vec![quote!{ Argument::Object(Proxy::id(&#arg_name)) }] }, Type::Array => if arg.allow_null { vec![quote! { if let Some(array) = #arg_name { Argument::Array(Box::new(array)) } else { Argument::Array(Box::new(Vec::new()))}}] } else { vec![quote! { Argument::Array(Box::new(#arg_name)) }] }, Type::String => if arg.allow_null { vec![quote! { Argument::Str(#arg_name.map(|s| Box::new(std::ffi::CString::new(s).unwrap()))) }] } else { vec![quote! { Argument::Str(Some(Box::new(std::ffi::CString::new(#arg_name).unwrap()))) }] }, Type::NewId => if side == Side::Client { if let Some(ref created_interface) = arg.interface { let created_iface_mod = Ident::new(created_interface, Span::call_site()); let created_iface_type = Ident::new(&snake_to_camel(created_interface), Span::call_site()); assert!(child_spec.is_none()); child_spec = Some(quote! { { let my_info = conn.object_info(self.id())?; Some((super::#created_iface_mod::#created_iface_type::interface(), my_info.version)) } }); vec![quote! { Argument::NewId(ObjectId::null()) }] } else { assert!(child_spec.is_none()); child_spec = Some(quote! { Some((#arg_name.0, #arg_name.1)) }); vec![ quote! { Argument::Str(Some(Box::new(std::ffi::CString::new(#arg_name.0.name).unwrap()))) }, quote! { Argument::Uint(#arg_name.1) }, quote! { Argument::NewId(ObjectId::null()) }, ] } } else { // server-side NewId is the same as Object if arg.allow_null { vec![quote! { if let Some(obj) = #arg_name { Argument::NewId(Resource::id(&obj)) } else { Argument::NewId(ObjectId::null()) } }] } else { vec![quote!{ Argument::NewId(Resource::id(&#arg_name)) }] } }, Type::Destructor => panic!("Argument {}.{}.{} has type destructor ?!", interface.name, msg.name, arg.name), } }); let args = if msg.args.is_empty() { quote! { smallvec::SmallVec::new() } } else if msg.args.len() <= 4 { // Note: Keep in sync with `wayland_backend::protocol::INLINE_ARGS`. // Fits in SmallVec inline capacity quote! { { let mut vec = smallvec::SmallVec::new(); #( vec.push(#args); )* vec } } } else { quote! { smallvec::SmallVec::from_vec(vec![#(#args),*]) } }; if side == Side::Client { let child_spec = child_spec.unwrap_or_else(|| quote! { None }); quote! { #msg_type::#msg_name { #(#arg_names),* } => { let child_spec = #child_spec; let args = #args; Ok((Message { sender_id: self.id.clone(), opcode: #opcode, args }, child_spec)) } } } else { quote! { #msg_type::#msg_name { #(#arg_names),* } => Ok(Message { sender_id: self.id.clone(), opcode: #opcode, args: #args, }) } } }); quote! { match msg { #(#arms,)* #msg_type::__phantom_lifetime { never, .. } => match never {} } } } wayland-scanner-0.31.6/src/interfaces.rs000064400000000000000000000123201046102023000162570ustar 00000000000000use proc_macro2::TokenStream; use crate::protocol::{Interface, Message, Protocol, Type}; use quote::{format_ident, quote}; pub fn generate(protocol: &Protocol, with_c_interfaces: bool) -> TokenStream { let interfaces = protocol.interfaces.iter().map(|iface| generate_interface(iface, with_c_interfaces)); if with_c_interfaces { let prefix = super::c_interfaces::generate_interfaces_prefix(protocol); quote! { #prefix #(#interfaces)* } } else { interfaces.collect() } } pub(crate) fn generate_interface(interface: &Interface, with_c: bool) -> TokenStream { let const_name = format_ident!("{}_INTERFACE", interface.name.to_ascii_uppercase()); let iface_name = &interface.name; let iface_version = interface.version; let requests = build_messagedesc_list(&interface.requests); let events = build_messagedesc_list(&interface.events); let c_name = format_ident!("{}_interface", interface.name); if with_c { let c_iface = super::c_interfaces::generate_interface(interface); quote! { pub static #const_name: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: #iface_name, version: #iface_version, requests: #requests, events: #events, c_ptr: Some(unsafe { & #c_name }), }; #c_iface } } else { quote! { pub static #const_name: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: #iface_name, version: #iface_version, requests: #requests, events: #events, c_ptr: None, }; } } } fn build_messagedesc_list(list: &[Message]) -> TokenStream { let desc_list = list.iter().map(|message| { let name = &message.name; let since = message.since; let is_destructor = message.typ == Some(Type::Destructor); let signature = message.args.iter().map(|arg| { if arg.typ == Type::NewId && arg.interface.is_none() { // this is a special generic message, it expands to multiple arguments quote! { wayland_backend::protocol::ArgumentType::Str(wayland_backend::protocol::AllowNull::No), wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::NewId } } else { let typ = arg.typ.common_type(); if arg.typ.nullable() { if arg.allow_null { quote! { wayland_backend::protocol::ArgumentType::#typ(wayland_backend::protocol::AllowNull::Yes) } } else { quote! { wayland_backend::protocol::ArgumentType::#typ(wayland_backend::protocol::AllowNull::No) } } } else { quote! { wayland_backend::protocol::ArgumentType::#typ } } } }); let child_interface = match message .args .iter() .find(|arg| arg.typ == Type::NewId) .and_then(|arg| arg.interface.as_ref()) { Some(name) => { let target_iface = format_ident!("{}_INTERFACE", name.to_ascii_uppercase()); quote! { Some(&#target_iface) } } None => quote! { None }, }; let arg_interfaces = message.args.iter().filter(|arg| arg.typ == Type::Object).map(|arg| { match arg.interface { Some(ref name) => { let target_iface = format_ident!("{}_INTERFACE", name.to_ascii_uppercase()); quote! { &#target_iface } } None => { quote! { &wayland_backend::protocol::ANONYMOUS_INTERFACE } } } }); quote! { wayland_backend::protocol::MessageDesc { name: #name, signature: &[ #(#signature),* ], since: #since, is_destructor: #is_destructor, child_interface: #child_interface, arg_interfaces: &[ #(#arg_interfaces),* ], } } }); quote!( &[ #(#desc_list),* ] ) } #[cfg(test)] mod tests { #[test] fn interface_gen() { let protocol_file = std::fs::File::open("./tests/scanner_assets/test-protocol.xml").unwrap(); let protocol_parsed = crate::parse::parse(protocol_file); let generated: String = super::generate(&protocol_parsed, true).to_string(); let generated = crate::format_rust_code(&generated); let reference = std::fs::read_to_string("./tests/scanner_assets/test-interfaces.rs").unwrap(); let reference = crate::format_rust_code(&reference); if reference != generated { let diff = similar::TextDiff::from_lines(&reference, &generated); print!("{}", diff.unified_diff().context_radius(10).header("reference", "generated")); panic!("Generated does not match reference!") } } } wayland-scanner-0.31.6/src/lib.rs000064400000000000000000000113671046102023000147140ustar 00000000000000//! Wayland protocol code-generation machinnery //! //! This crate provides procedural macros for generating the rust code associated with a //! Wayland XML protocol specification, for use with the `wayland-client`, `wayland-server` //! and `wayland-backend` crates. //! //! Before trying to use this crate, you may check if the protocol extension you want to use //! is not already exposed in the `wayland-protocols` crate. //! //! ## Example usage //! //! Below is a template for generating the code for a custom protocol client-side. Server-side //! is identical, just replacing `client` by `server`. The path to the XML file is relative to the //! crate root. //! //! ```rust,ignore //! // Generate the bindings in their own module //! pub mod my_protocol { //! use wayland_client; //! // import objects from the core protocol if needed //! use wayland_client::protocol::*; //! //! // This module hosts a low-level representation of the protocol objects //! // you will not need to interact with it yourself, but the code generated //! // by the generate_client_code! macro will use it //! pub mod __interfaces { //! // import the interfaces from the core protocol if needed //! use wayland_client::protocol::__interfaces::*; //! wayland_scanner::generate_interfaces!("./path/to/the/protocol.xml"); //! } //! use self::__interfaces::*; //! //! // This macro generates the actual types that represent the wayland objects of //! // your custom protocol //! wayland_scanner::generate_client_code!("./path/to/the/protocol.xml"); //! } //! ``` use std::{ffi::OsString, path::PathBuf}; mod c_interfaces; mod client_gen; mod common; mod interfaces; mod parse; mod protocol; mod server_gen; mod token; mod util; /// Proc-macro for generating low-level interfaces associated with an XML specification #[proc_macro] pub fn generate_interfaces(stream: proc_macro::TokenStream) -> proc_macro::TokenStream { let path: OsString = token::parse_lit_str_token(stream).into(); let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") { let mut buf = PathBuf::from(manifest_dir); buf.push(path); buf } else { path.into() }; let file = match std::fs::File::open(&path) { Ok(file) => file, Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e), }; let protocol = parse::parse(file); interfaces::generate(&protocol, true).into() } /// Proc-macro for generating client-side API associated with an XML specification #[proc_macro] pub fn generate_client_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream { let path: OsString = token::parse_lit_str_token(stream).into(); let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") { let mut buf = PathBuf::from(manifest_dir); buf.push(path); buf } else { path.into() }; let file = match std::fs::File::open(&path) { Ok(file) => file, Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e), }; let protocol = parse::parse(file); client_gen::generate_client_objects(&protocol).into() } /// Proc-macro for generating server-side API associated with an XML specification #[proc_macro] pub fn generate_server_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream { let path: OsString = token::parse_lit_str_token(stream).into(); let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") { let mut buf = PathBuf::from(manifest_dir); buf.push(path); buf } else { path.into() }; let file = match std::fs::File::open(&path) { Ok(file) => file, Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e), }; let protocol = parse::parse(file); server_gen::generate_server_objects(&protocol).into() } #[cfg(test)] fn format_rust_code(code: &str) -> String { use std::{ io::Write, process::{Command, Stdio}, }; if let Ok(mut proc) = Command::new("rustfmt") .arg("--emit=stdout") .arg("--edition=2018") .stdin(Stdio::piped()) .stdout(Stdio::piped()) //.stderr(Stdio::null()) .spawn() { { let stdin = proc.stdin.as_mut().unwrap(); stdin.write_all(code.as_bytes()).unwrap(); } if let Ok(output) = proc.wait_with_output() { if output.status.success() { return std::str::from_utf8(&output.stdout).unwrap().to_owned(); } } } panic!("Rustfmt failed!"); } #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum Side { /// wayland client applications Client, /// wayland compositors Server, } wayland-scanner-0.31.6/src/parse.rs000064400000000000000000000341441046102023000152560ustar 00000000000000use super::protocol::*; use std::{ io::{BufRead, BufReader, Read}, str::FromStr, }; use quick_xml::{ events::{attributes::Attributes, Event}, Reader, }; macro_rules! extract_from( ($it: expr => $pattern: pat => $result: tt) => ( match $it.read_event_into(&mut Vec::new()) { Ok($pattern) => { $result }, e => panic!("Ill-formed protocol file: {:?}", e) } ) ); macro_rules! extract_end_tag( ($it: expr => $tag: expr) => ( extract_from!($it => Event::End(bytes) => { assert!(bytes.name().into_inner() == $tag.as_bytes(), "Ill-formed protocol file"); }); ) ); pub fn parse(stream: S) -> Protocol { let mut reader = Reader::from_reader(BufReader::new(stream)); let reader_config = reader.config_mut(); reader_config.trim_text(true); reader_config.expand_empty_elements = true; parse_protocol(reader) } fn decode_utf8_or_panic(txt: Vec) -> String { match String::from_utf8(txt) { Ok(txt) => txt, Err(e) => panic!("Invalid UTF8: '{}'", String::from_utf8_lossy(&e.into_bytes())), } } fn parse_or_panic(txt: &[u8]) -> T { match std::str::from_utf8(txt).ok().and_then(|val| val.parse().ok()) { Some(version) => version, None => panic!( "Invalid value '{}' for parsing type '{}'", String::from_utf8_lossy(txt), std::any::type_name::() ), } } fn init_protocol(reader: &mut Reader) -> Protocol { // Check two firsts lines for protocol tag for _ in 0..3 { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Decl(_) | Event::DocType(_)) => { continue; } Ok(Event::Start(bytes)) => { assert!(bytes.name().into_inner() == b"protocol", "Missing protocol toplevel tag"); if let Some(attr) = bytes .attributes() .filter_map(|res| res.ok()) .find(|attr| attr.key.into_inner() == b"name") { return Protocol::new(decode_utf8_or_panic(attr.value.into_owned())); } else { panic!("Protocol must have a name"); } } _ => panic!("Ill-formed protocol file"), } } panic!("Ill-formed protocol file"); } fn parse_protocol(mut reader: Reader) -> Protocol { let mut protocol = init_protocol(&mut reader); loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => { match bytes.name().into_inner() { b"copyright" => { // parse the copyright let copyright = match reader.read_event_into(&mut Vec::new()) { Ok(Event::Text(copyright)) => { copyright.unescape().ok().map(|x| x.to_string()) } Ok(Event::CData(copyright)) => { String::from_utf8(copyright.into_inner().into()).ok() } e => panic!("Ill-formed protocol file: {:?}", e), }; extract_end_tag!(reader => "copyright"); protocol.copyright = copyright } b"interface" => { protocol.interfaces.push(parse_interface(&mut reader, bytes.attributes())); } b"description" => { protocol.description = Some(parse_description(&mut reader, bytes.attributes())); } name => panic!( "Ill-formed protocol file: unexpected token `{}` in protocol {}", String::from_utf8_lossy(name), protocol.name ), } } Ok(Event::End(bytes)) => { let name = bytes.name().into_inner(); assert!( name == b"protocol", "Unexpected closing token `{}`", String::from_utf8_lossy(name) ); break; } // ignore comments Ok(Event::Comment(_)) => {} e => panic!("Ill-formed protocol file: unexpected token {:?}", e), } } protocol } fn parse_interface(reader: &mut Reader, attrs: Attributes) -> Interface { let mut interface = Interface::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => interface.name = decode_utf8_or_panic(attr.value.into_owned()), b"version" => interface.version = parse_or_panic(&attr.value), _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { interface.description = Some(parse_description(reader, bytes.attributes())) } b"request" => interface.requests.push(parse_request(reader, bytes.attributes())), b"event" => interface.events.push(parse_event(reader, bytes.attributes())), b"enum" => interface.enums.push(parse_enum(reader, bytes.attributes())), name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"interface" => break, _ => {} } } interface } fn parse_description(reader: &mut Reader, attrs: Attributes) -> (String, String) { let mut summary = String::new(); for attr in attrs.filter_map(|res| res.ok()) { if attr.key.into_inner() == b"summary" { summary = String::from_utf8_lossy(&attr.value) .split_whitespace() .collect::>() .join(" "); } } let mut description = String::new(); // Some protocols have comments inside their descriptions, so we need to parse them in a loop and // concatenate the parts into a single block of text loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Text(bytes)) => { if !description.is_empty() { description.push_str("\n\n"); } description.push_str(&bytes.unescape().unwrap_or_default()) } Ok(Event::End(bytes)) if bytes.name().into_inner() == b"description" => break, Ok(Event::Comment(_)) => {} e => panic!("Ill-formed protocol file: {:?}", e), } } (summary, description) } fn parse_request(reader: &mut Reader, attrs: Attributes) -> Message { let mut request = Message::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => request.name = decode_utf8_or_panic(attr.value.into_owned()), b"type" => request.typ = Some(parse_type(&attr.value)), b"since" => request.since = parse_or_panic(&attr.value), _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { request.description = Some(parse_description(reader, bytes.attributes())) } b"arg" => request.args.push(parse_arg(reader, bytes.attributes())), name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"request" => break, _ => {} } } request } fn parse_enum(reader: &mut Reader, attrs: Attributes) -> Enum { let mut enu = Enum::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => enu.name = decode_utf8_or_panic(attr.value.into_owned()), b"since" => enu.since = parse_or_panic(&attr.value), b"bitfield" => { if &attr.value[..] == b"true" { enu.bitfield = true } } _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { enu.description = Some(parse_description(reader, bytes.attributes())) } b"entry" => enu.entries.push(parse_entry(reader, bytes.attributes())), name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"enum" => break, _ => {} } } enu } fn parse_event(reader: &mut Reader, attrs: Attributes) -> Message { let mut event = Message::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => event.name = decode_utf8_or_panic(attr.value.into_owned()), b"type" => event.typ = Some(parse_type(&attr.value)), b"since" => event.since = parse_or_panic(&attr.value), _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { event.description = Some(parse_description(reader, bytes.attributes())) } b"arg" => event.args.push(parse_arg(reader, bytes.attributes())), name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"event" => break, _ => {} } } event } fn parse_arg(reader: &mut Reader, attrs: Attributes) -> Arg { let mut arg = Arg::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => arg.name = decode_utf8_or_panic(attr.value.into_owned()), b"type" => arg.typ = parse_type(&attr.value), b"summary" => { arg.summary = Some( String::from_utf8_lossy(&attr.value) .split_whitespace() .collect::>() .join(" "), ) } b"interface" => arg.interface = Some(parse_or_panic(&attr.value)), b"allow-null" => { if &*attr.value == b"true" { arg.allow_null = true } } b"enum" => arg.enum_ = Some(decode_utf8_or_panic(attr.value.into_owned())), _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { arg.description = Some(parse_description(reader, bytes.attributes())) } name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"arg" => break, _ => {} } } arg } fn parse_type(txt: &[u8]) -> Type { match txt { b"int" => Type::Int, b"uint" => Type::Uint, b"fixed" => Type::Fixed, b"string" => Type::String, b"object" => Type::Object, b"new_id" => Type::NewId, b"array" => Type::Array, b"fd" => Type::Fd, b"destructor" => Type::Destructor, e => panic!("Unexpected type: {}", String::from_utf8_lossy(e)), } } fn parse_entry(reader: &mut Reader, attrs: Attributes) -> Entry { let mut entry = Entry::new(); for attr in attrs.filter_map(|res| res.ok()) { match attr.key.into_inner() { b"name" => entry.name = decode_utf8_or_panic(attr.value.into_owned()), b"value" => { entry.value = if attr.value.starts_with(b"0x") { if let Some(val) = std::str::from_utf8(&attr.value[2..]) .ok() .and_then(|s| u32::from_str_radix(s, 16).ok()) { val } else { panic!("Invalid number: {}", String::from_utf8_lossy(&attr.value)) } } else { parse_or_panic(&attr.value) }; } b"since" => entry.since = parse_or_panic(&attr.value), b"summary" => { entry.summary = Some( String::from_utf8_lossy(&attr.value) .split_whitespace() .collect::>() .join(" "), ) } _ => {} } } loop { match reader.read_event_into(&mut Vec::new()) { Ok(Event::Start(bytes)) => match bytes.name().into_inner() { b"description" => { entry.description = Some(parse_description(reader, bytes.attributes())) } name => panic!("Unexpected token: `{}`", String::from_utf8_lossy(name)), }, Ok(Event::End(bytes)) if bytes.name().into_inner() == b"entry" => break, _ => {} } } entry } #[cfg(test)] mod tests { #[test] fn xml_parse() { let protocol_file = std::fs::File::open("./tests/scanner_assets/test-protocol.xml").unwrap(); let _ = crate::parse::parse(protocol_file); } #[test] fn headerless_xml_parse() { let protocol_file = std::fs::File::open("./tests/scanner_assets/test-headerless-protocol.xml").unwrap(); let _ = crate::parse::parse(protocol_file); } } wayland-scanner-0.31.6/src/protocol.rs000064400000000000000000000065731046102023000160120ustar 00000000000000use proc_macro2::TokenStream; use quote::quote; #[derive(Clone, Debug)] pub struct Protocol { pub name: String, pub copyright: Option, pub description: Option<(String, String)>, pub interfaces: Vec, } impl Protocol { pub fn new(name: String) -> Protocol { Protocol { name, copyright: None, description: None, interfaces: Vec::new() } } } #[derive(Clone, Debug)] pub struct Interface { pub name: String, pub version: u32, pub description: Option<(String, String)>, pub requests: Vec, pub events: Vec, pub enums: Vec, } impl Interface { pub fn new() -> Interface { Interface { name: String::new(), version: 1, description: None, requests: Vec::new(), events: Vec::new(), enums: Vec::new(), } } } #[derive(Clone, Debug)] pub struct Message { pub name: String, pub typ: Option, pub since: u32, pub description: Option<(String, String)>, pub args: Vec, } impl Message { pub fn new() -> Message { Message { name: String::new(), typ: None, since: 1, description: None, args: Vec::new() } } pub fn all_null(&self) -> bool { self.args .iter() .all(|a| !((a.typ == Type::Object || a.typ == Type::NewId) && a.interface.is_some())) } } #[derive(Clone, Debug)] pub struct Arg { pub name: String, pub typ: Type, pub interface: Option, pub summary: Option, pub description: Option<(String, String)>, pub allow_null: bool, pub enum_: Option, } impl Arg { pub fn new() -> Arg { Arg { name: String::new(), typ: Type::Object, interface: None, summary: None, description: None, allow_null: false, enum_: None, } } } #[derive(Clone, Debug)] pub struct Enum { pub name: String, pub since: u16, pub description: Option<(String, String)>, pub entries: Vec, pub bitfield: bool, } impl Enum { pub fn new() -> Enum { Enum { name: String::new(), since: 1, description: None, entries: Vec::new(), bitfield: false, } } } #[derive(Clone, Debug)] pub struct Entry { pub name: String, pub value: u32, pub since: u16, pub description: Option<(String, String)>, pub summary: Option, } impl Entry { pub fn new() -> Entry { Entry { name: String::new(), value: 0, since: 1, description: None, summary: None } } } #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Type { Int, Uint, Fixed, String, Object, NewId, Array, Fd, Destructor, } impl Type { pub fn nullable(self) -> bool { matches!(self, Type::String | Type::Object) } pub fn common_type(self) -> TokenStream { match self { Type::Int => quote!(Int), Type::Uint => quote!(Uint), Type::Fixed => quote!(Fixed), Type::Array => quote!(Array), Type::Fd => quote!(Fd), Type::String => quote!(Str), Type::Object => quote!(Object), Type::NewId => quote!(NewId), Type::Destructor => panic!("Destructor is not a valid argument type."), } } } wayland-scanner-0.31.6/src/server_gen.rs000064400000000000000000000252461046102023000163060ustar 00000000000000use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use crate::{ protocol::{Interface, Protocol, Type}, util::{description_to_doc_attr, dotted_to_relname, is_keyword, snake_to_camel, to_doc_attr}, Side, }; pub fn generate_server_objects(protocol: &Protocol) -> TokenStream { protocol .interfaces .iter() .filter(|iface| iface.name != "wl_display" && iface.name != "wl_registry") .map(generate_objects_for) .collect() } fn generate_objects_for(interface: &Interface) -> TokenStream { let mod_name = Ident::new(&interface.name, Span::call_site()); let mod_doc = interface.description.as_ref().map(description_to_doc_attr); let iface_name = Ident::new(&snake_to_camel(&interface.name), Span::call_site()); let iface_const_name = format_ident!("{}_INTERFACE", interface.name.to_ascii_uppercase()); 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( &format_ident!("Request"), Side::Server, true, &interface.requests, ); let events = crate::common::gen_message_enum( &format_ident!("Event"), Side::Server, false, &interface.events, ); let parse_body = crate::common::gen_parse_body(interface, Side::Server); let write_body = crate::common::gen_write_body(interface, Side::Server); let methods = gen_methods(interface); let event_ref = if interface.requests.is_empty() { "This interface has no requests." } else { "See also the [Request] enum for this interface." }; let docs = match &interface.description { Some((short, long)) => format!("{}\n\n{}\n\n{}", short, long, event_ref), None => format!("{}\n\n{}", interface.name, event_ref), }; let doc_attr = to_doc_attr(&docs); quote! { #mod_doc pub mod #mod_name { use std::sync::Arc; use std::os::unix::io::OwnedFd; use super::wayland_server::{ backend::{ smallvec, ObjectData, ObjectId, InvalidId, WeakHandle, protocol::{WEnum, Argument, Message, Interface, same_interface} }, Resource, Dispatch, DisplayHandle, DispatchError, ResourceData, New, Weak, }; #enums #msg_constants #requests #events #doc_attr #[derive(Debug, Clone)] pub struct #iface_name { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for #iface_name { #[inline] fn eq(&self, other: &#iface_name) -> bool { self.id == other.id } } impl std::cmp::Eq for #iface_name {} impl PartialEq> for #iface_name { #[inline] fn eq(&self, other: &Weak<#iface_name>) -> bool { self.id == other.id() } } impl std::borrow::Borrow for #iface_name { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for #iface_name { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for #iface_name { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface{ &super::#iface_const_name } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| (&**arc).downcast_ref::>()).map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null(){ return Err(InvalidId) } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(#iface_name { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request(conn: &DisplayHandle, msg: Message) -> Result<(Self, Self::Request), DispatchError> { #parse_body } fn write_event<'a>(&self, conn: &DisplayHandle, msg: Self::Event<'a>) -> Result>, InvalidId> { #write_body } fn __set_object_data(&mut self, odata: std::sync::Arc) { self.data = Some(odata); } } impl #iface_name { #methods } } } } fn gen_methods(interface: &Interface) -> TokenStream { interface .events .iter() .map(|request| { let method_name = format_ident!( "{}{}", if is_keyword(&request.name) { "_" } else { "" }, request.name ); let enum_variant = Ident::new(&snake_to_camel(&request.name), Span::call_site()); let fn_args = request.args.iter().flat_map(|arg| { let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); let arg_type = if let Some(ref enu) = arg.enum_ { let enum_type = dotted_to_relname(enu); quote! { #enum_type } } else { match arg.typ { Type::Uint => quote! { u32 }, Type::Int => quote! { i32 }, 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::BorrowedFd<'_> }, Type::Object | Type::NewId => { let iface = arg.interface.as_ref().unwrap(); let iface_mod = Ident::new(iface, Span::call_site()); let iface_type = Ident::new(&snake_to_camel(iface), Span::call_site()); if arg.allow_null { quote! { Option<&super::#iface_mod::#iface_type> } } else { quote! { &super::#iface_mod::#iface_type } } } Type::Destructor => panic!("An argument cannot have type \"destructor\"."), } }; Some(quote! { #arg_name: #arg_type }) }); let enum_args = request.args.iter().flat_map(|arg| { let arg_name = format_ident!("{}{}", if is_keyword(&arg.name) { "_" } else { "" }, arg.name); if arg.enum_.is_some() { Some(quote! { #arg_name: WEnum::Value(#arg_name) }) } else if arg.typ == Type::Object || arg.typ == Type::NewId { if arg.allow_null { Some(quote! { #arg_name: #arg_name.cloned() }) } else { Some(quote! { #arg_name: #arg_name.clone() }) } } else { Some(quote! { #arg_name }) } }); let doc_attr = request.description.as_ref().map(description_to_doc_attr); quote! { #doc_attr #[allow(clippy::too_many_arguments)] pub fn #method_name(&self, #(#fn_args),*) { let _ = self.send_event( Event::#enum_variant { #(#enum_args),* } ); } } }) .collect() } #[cfg(test)] mod tests { #[test] fn server_gen() { let protocol_file = std::fs::File::open("./tests/scanner_assets/test-protocol.xml").unwrap(); let protocol_parsed = crate::parse::parse(protocol_file); let generated: String = super::generate_server_objects(&protocol_parsed).to_string(); let generated = crate::format_rust_code(&generated); let reference = std::fs::read_to_string("./tests/scanner_assets/test-server-code.rs").unwrap(); let reference = crate::format_rust_code(&reference); if reference != generated { let diff = similar::TextDiff::from_lines(&reference, &generated); print!("{}", diff.unified_diff().context_radius(10).header("reference", "generated")); panic!("Generated does not match reference!") } } } wayland-scanner-0.31.6/src/token.rs000064400000000000000000000127111046102023000152600ustar 00000000000000// `bytes`, `next_chr`, `parse_lit_str`, `parse_lit_str_cooked` and `parse_lit_str_raw` are adapted // from syn: // https://github.com/dtolnay/syn/blob/362ee2d02df3f1b2e74c7b7a4cf2ed3c106404c9/src/lit.rs#L1062-L1167 // and // https://github.com/dtolnay/syn/blob/362ee2d02df3f1b2e74c7b7a4cf2ed3c106404c9/src/lit.rs#L1327-L1388 /// Get the byte at offset idx, or a default of `b'\0'` if we're looking /// past the end of the input buffer. fn byte(s: &str, idx: usize) -> u8 { if idx < s.len() { s.as_bytes()[idx] } else { 0 } } fn next_chr(s: &str) -> char { s.chars().next().unwrap_or('\0') } // Returns (content, suffix). fn parse_lit_str(s: &str) -> String { match byte(s, 0) { b'"' => parse_lit_str_cooked(s), b'r' => parse_lit_str_raw(s), _ => unreachable!(), } } // Clippy false positive // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 #[allow(clippy::needless_continue)] fn parse_lit_str_cooked(mut s: &str) -> String { assert_eq!(byte(s, 0), b'"'); s = &s[1..]; let mut content = String::new(); 'outer: loop { let ch = match byte(s, 0) { b'"' => break, b'\\' => { let b = byte(s, 1); s = &s[2..]; match b { b'x' => { let (byte, rest) = backslash_x(s); s = rest; assert!(byte <= 0x80, "Invalid \\x byte in string literal"); char::from_u32(u32::from(byte)).unwrap() } b'u' => { let (chr, rest) = backslash_u(s); s = rest; chr } b'n' => '\n', b'r' => '\r', b't' => '\t', b'\\' => '\\', b'0' => '\0', b'\'' => '\'', b'"' => '"', b'\r' | b'\n' => loop { let ch = next_chr(s); if ch.is_whitespace() { s = &s[ch.len_utf8()..]; } else { continue 'outer; } }, b => panic!("unexpected byte {:?} after \\ character in byte literal", b), } } b'\r' => { assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string"); s = &s[2..]; '\n' } _ => { let ch = next_chr(s); s = &s[ch.len_utf8()..]; ch } }; content.push(ch); } assert!(s.starts_with('"')); content } fn parse_lit_str_raw(mut s: &str) -> String { assert_eq!(byte(s, 0), b'r'); s = &s[1..]; let mut pounds = 0; while byte(s, pounds) == b'#' { pounds += 1; } assert_eq!(byte(s, pounds), b'"'); let close = s.rfind('"').unwrap(); for end in s[close + 1..close + 1 + pounds].bytes() { assert_eq!(end, b'#'); } s[pounds + 1..close].to_owned() } fn backslash_x(s: &str) -> (u8, &str) { let mut ch = 0; let b0 = byte(s, 0); let b1 = byte(s, 1); ch += 0x10 * match b0 { b'0'..=b'9' => b0 - b'0', b'a'..=b'f' => 10 + (b0 - b'a'), b'A'..=b'F' => 10 + (b0 - b'A'), _ => panic!("unexpected non-hex character after \\x"), }; ch += match b1 { b'0'..=b'9' => b1 - b'0', b'a'..=b'f' => 10 + (b1 - b'a'), b'A'..=b'F' => 10 + (b1 - b'A'), _ => panic!("unexpected non-hex character after \\x"), }; (ch, &s[2..]) } fn backslash_u(mut s: &str) -> (char, &str) { if byte(s, 0) != b'{' { panic!("{}", "expected { after \\u"); } s = &s[1..]; let mut ch = 0; let mut digits = 0; loop { let b = byte(s, 0); let digit = match b { b'0'..=b'9' => b - b'0', b'a'..=b'f' => 10 + b - b'a', b'A'..=b'F' => 10 + b - b'A', b'_' if digits > 0 => { s = &s[1..]; continue; } b'}' if digits == 0 => panic!("invalid empty unicode escape"), b'}' => break, _ => panic!("unexpected non-hex character after \\u"), }; if digits == 6 { panic!("overlong unicode escape (must have at most 6 hex digits)"); } ch *= 0x10; ch += u32::from(digit); digits += 1; s = &s[1..]; } assert!(byte(s, 0) == b'}'); s = &s[1..]; if let Some(ch) = char::from_u32(ch) { (ch, s) } else { panic!("character code {:x} is not a valid unicode character", ch); } } // End of code adapted from syn pub fn parse_lit_str_token(mut stream: proc_macro::TokenStream) -> String { loop { let mut iter = stream.into_iter(); let token = iter.next().expect("expected string argument"); assert!(iter.next().is_none(), "unexpected trailing token"); let literal = match token { proc_macro::TokenTree::Literal(literal) => literal, proc_macro::TokenTree::Group(group) => { stream = group.stream(); continue; } _ => panic!("expected string argument found `{:?}`", token), }; return parse_lit_str(&literal.to_string()); } } wayland-scanner-0.31.6/src/util.rs000064400000000000000000000053301046102023000151140ustar 00000000000000use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; pub(crate) fn to_doc_attr(text: &str) -> TokenStream { let text = text.lines().map(str::trim).collect::>().join("\n"); let text = text.trim(); quote!(#[doc = #text]) } pub(crate) fn description_to_doc_attr((short, long): &(String, String)) -> TokenStream { to_doc_attr(&format!("{}\n\n{}", short, long)) } pub fn is_keyword(txt: &str) -> bool { matches!( txt, "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" | "__handler" | "__object" ) } pub fn is_camel_keyword(txt: &str) -> bool { matches!(txt, "Self") } pub fn snake_to_camel(input: &str) -> String { let result = input .split('_') .flat_map(|s| { let mut first = true; s.chars().map(move |c| { if first { first = false; c.to_ascii_uppercase() } else { c } }) }) .collect::(); if is_camel_keyword(&result) { format!("_{}", &result) } else { result } } pub fn dotted_to_relname(input: &str) -> TokenStream { let mut it = input.split('.'); match (it.next(), it.next()) { (Some(module), Some(name)) => { let module = Ident::new(module, Span::call_site()); let ident = Ident::new(&snake_to_camel(name), Span::call_site()); quote::quote!(super::#module::#ident) } (Some(name), None) => { Ident::new(&snake_to_camel(name), Span::call_site()).into_token_stream() } _ => unreachable!(), } } wayland-scanner-0.31.6/tests/scanner_assets/test-client-code.rs000064400000000000000000002250451046102023000226770ustar 00000000000000#[doc = "core global object\n\nThe core global object. This is a special singleton object. It\nis used for internal Wayland protocol features."] pub mod wl_display { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = "global error values\n\nThese errors are global and can be emitted in response to any\nserver request."] #[repr(u32)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] pub enum Error { #[doc = "server couldn't find object"] InvalidObject = 0, #[doc = "method doesn't exist on the specified interface or malformed request"] InvalidMethod = 1, #[doc = "server is out of memory"] NoMemory = 2, #[doc = "implementation error in compositor"] Implementation = 3, } impl std::convert::TryFrom for Error { type Error = (); fn try_from(val: u32) -> Result { match val { 0 => Ok(Error::InvalidObject), 1 => Ok(Error::InvalidMethod), 2 => Ok(Error::NoMemory), 3 => Ok(Error::Implementation), _ => Err(()), } } } impl std::convert::From for u32 { fn from(val: Error) -> u32 { val as u32 } } #[doc = r" The minimal object version supporting this request"] pub const REQ_SYNC_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] pub const REQ_SYNC_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_GET_REGISTRY_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] pub const REQ_GET_REGISTRY_OPCODE: u16 = 1u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_ERROR_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_ERROR_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_DELETE_ID_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_DELETE_ID_OPCODE: u16 = 1u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "asynchronous roundtrip\n\nThe sync request asks the server to emit the 'done' event\non the returned wl_callback object. Since requests are\nhandled in-order and events are delivered in-order, this can\nbe used as a barrier to ensure all previous requests and the\nresulting events have been handled.\n\nThe object returned by this request will be destroyed by the\ncompositor after the callback is fired and as such the client must not\nattempt to use it after that point.\n\nThe callback_data passed in the callback is the event serial."] Sync {}, #[doc = "get global registry object\n\nThis request creates a registry object that allows the client\nto list and bind the global objects available from the\ncompositor.\n\nIt should be noted that the server side resources consumed in\nresponse to a get_registry request can only be released when the\nclient disconnects, not when the client side proxy is destroyed.\nTherefore, clients should invoke get_registry as infrequently as\npossible to avoid wasting memory."] GetRegistry {}, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Sync { .. } => 0u16, Request::GetRegistry { .. } => 1u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event { #[doc = "fatal error event\n\nThe error event is sent out when a fatal (non-recoverable)\nerror has occurred. The object_id argument is the object\nwhere the error occurred, most often in response to a request\nto that object. The code identifies the error and is defined\nby the object interface. As such, each interface defines its\nown set of error codes. The message is a brief description\nof the error, for (debugging) convenience."] Error { #[doc = "object where the error occurred"] object_id: super::wayland_client::ObjectId, #[doc = "error code"] code: u32, #[doc = "error description"] message: String, }, #[doc = "acknowledge object ID deletion\n\nThis event is used internally by the object ID management\nlogic. When a client deletes an object that it had created,\nthe server will send this event to acknowledge that it has\nseen the delete request. When the client receives this event,\nit will know that it can safely reuse the object ID."] DeleteId { #[doc = "deleted object ID"] id: u32, }, } impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::Error { .. } => 0u16, Event::DeleteId { .. } => 1u16, } } } #[doc = "core global object\n\nThe core global object. This is a special singleton object. It\nis used for internal Wayland protocol features.\n\nSee also the [Event] enum for this interface."] #[derive(Debug, Clone)] pub struct WlDisplay { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for WlDisplay { fn eq(&self, other: &WlDisplay) -> bool { self.id == other.id } } impl std::cmp::Eq for WlDisplay {} impl PartialEq> for WlDisplay { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for WlDisplay { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for WlDisplay { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for WlDisplay { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::WL_DISPLAY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(WlDisplay { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { WlDisplay { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let ( Some(Argument::Object(object_id)), Some(Argument::Uint(code)), Some(Argument::Str(message)), ) = (arg_iter.next(), arg_iter.next(), arg_iter.next()) { Ok(( me, Event::Error { object_id: object_id.clone(), code, message: String::from_utf8_lossy( message.as_ref().unwrap().as_bytes(), ) .into_owned(), }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 1u16 => { if let (Some(Argument::Uint(id))) = (arg_iter.next()) { Ok((me, Event::DeleteId { id })) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::Sync {} => { let child_spec = { let my_info = conn.object_info(self.id())?; Some((super::wl_callback::WlCallback::interface(), my_info.version)) }; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(ObjectId::null())); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::GetRegistry {} => { let child_spec = { let my_info = conn.object_info(self.id())?; Some((super::wl_registry::WlRegistry::interface(), my_info.version)) }; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(ObjectId::null())); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 1u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl WlDisplay { #[doc = "asynchronous roundtrip\n\nThe sync request asks the server to emit the 'done' event\non the returned wl_callback object. Since requests are\nhandled in-order and events are delivered in-order, this can\nbe used as a barrier to ensure all previous requests and the\nresulting events have been handled.\n\nThe object returned by this request will be destroyed by the\ncompositor after the callback is fired and as such the client must not\nattempt to use it after that point.\n\nThe callback_data passed in the callback is the event serial."] #[allow(clippy::too_many_arguments)] pub fn sync< U: Send + Sync + 'static, D: Dispatch + 'static, >( &self, qh: &QueueHandle, udata: U, ) -> super::wl_callback::WlCallback { self.send_constructor( Request::Sync {}, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } #[doc = "get global registry object\n\nThis request creates a registry object that allows the client\nto list and bind the global objects available from the\ncompositor.\n\nIt should be noted that the server side resources consumed in\nresponse to a get_registry request can only be released when the\nclient disconnects, not when the client side proxy is destroyed.\nTherefore, clients should invoke get_registry as infrequently as\npossible to avoid wasting memory."] #[allow(clippy::too_many_arguments)] pub fn get_registry< U: Send + Sync + 'static, D: Dispatch + 'static, >( &self, qh: &QueueHandle, udata: U, ) -> super::wl_registry::WlRegistry { self.send_constructor( Request::GetRegistry {}, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } } #[doc = "global registry object\n\nThe singleton global registry object. The server has a number of\nglobal objects that are available to all clients. These objects\ntypically represent an actual object in the server (for example,\nan input device) or they are singleton objects that provide\nextension functionality.\n\nWhen a client creates a registry object, the registry object\nwill emit a global event for each global currently in the\nregistry. Globals come and go as a result of device or\nmonitor hotplugs, reconfiguration or other events, and the\nregistry will send out global and global_remove events to\nkeep the client up to date with the changes. To mark the end\nof the initial burst of events, the client can use the\nwl_display.sync request immediately after calling\nwl_display.get_registry.\n\nA client can bind to a global object by using the bind\nrequest. This creates a client-side handle that lets the object\nemit events to the client and lets the client invoke requests on\nthe object."] pub mod wl_registry { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_BIND_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] pub const REQ_BIND_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_GLOBAL_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_GLOBAL_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_GLOBAL_REMOVE_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_GLOBAL_REMOVE_OPCODE: u16 = 1u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "bind an object to the display\n\nBinds a new, client-created object to the server using the\nspecified name as the identifier."] Bind { #[doc = "unique numeric name of the object"] name: u32, #[doc = "bounded object"] id: (&'static Interface, u32), }, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Bind { .. } => 0u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event { #[doc = "announce global object\n\nNotify the client of global objects.\n\nThe event notifies the client that a global object with\nthe given name is now available, and it implements the\ngiven version of the given interface."] Global { #[doc = "numeric name of the global object"] name: u32, #[doc = "interface implemented by the object"] interface: String, #[doc = "interface version"] version: u32, }, #[doc = "announce removal of global object\n\nNotify the client of removed global objects.\n\nThis event notifies the client that the global identified\nby name is no longer available. If the client bound to\nthe global using the bind request, the client should now\ndestroy that object.\n\nThe object remains valid and requests to the object will be\nignored until the client destroys it, to avoid races between\nthe global going away and a client sending a request to it."] GlobalRemove { #[doc = "numeric name of the global object"] name: u32, }, } impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::Global { .. } => 0u16, Event::GlobalRemove { .. } => 1u16, } } } #[doc = "global registry object\n\nThe singleton global registry object. The server has a number of\nglobal objects that are available to all clients. These objects\ntypically represent an actual object in the server (for example,\nan input device) or they are singleton objects that provide\nextension functionality.\n\nWhen a client creates a registry object, the registry object\nwill emit a global event for each global currently in the\nregistry. Globals come and go as a result of device or\nmonitor hotplugs, reconfiguration or other events, and the\nregistry will send out global and global_remove events to\nkeep the client up to date with the changes. To mark the end\nof the initial burst of events, the client can use the\nwl_display.sync request immediately after calling\nwl_display.get_registry.\n\nA client can bind to a global object by using the bind\nrequest. This creates a client-side handle that lets the object\nemit events to the client and lets the client invoke requests on\nthe object.\n\nSee also the [Event] enum for this interface."] #[derive(Debug, Clone)] pub struct WlRegistry { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for WlRegistry { fn eq(&self, other: &WlRegistry) -> bool { self.id == other.id } } impl std::cmp::Eq for WlRegistry {} impl PartialEq> for WlRegistry { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for WlRegistry { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for WlRegistry { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for WlRegistry { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::WL_REGISTRY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(WlRegistry { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { WlRegistry { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let ( Some(Argument::Uint(name)), Some(Argument::Str(interface)), Some(Argument::Uint(version)), ) = (arg_iter.next(), arg_iter.next(), arg_iter.next()) { Ok(( me, Event::Global { name, interface: String::from_utf8_lossy( interface.as_ref().unwrap().as_bytes(), ) .into_owned(), version, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 1u16 => { if let (Some(Argument::Uint(name))) = (arg_iter.next()) { Ok((me, Event::GlobalRemove { name })) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::Bind { name, id } => { let child_spec = Some((id.0, id.1)); let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::Uint(name)); vec.push(Argument::Str(Some(Box::new( std::ffi::CString::new(id.0.name).unwrap(), )))); vec.push(Argument::Uint(id.1)); vec.push(Argument::NewId(ObjectId::null())); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl WlRegistry { #[doc = "bind an object to the display\n\nBinds a new, client-created object to the server using the\nspecified name as the identifier."] #[allow(clippy::too_many_arguments)] pub fn bind + 'static>( &self, name: u32, version: u32, qh: &QueueHandle, udata: U, ) -> I { self.send_constructor( Request::Bind { name, id: (I::interface(), version) }, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } } #[doc = "callback object\n\nClients can handle the 'done' event to get notified when\nthe related request is done."] pub mod wl_callback { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this event"] pub const EVT_DONE_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_DONE_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event { #[doc = "done event\n\nNotify the client when the related request is done.\n\nThis is a destructor, once received this object cannot be used any longer."] Done { #[doc = "request-specific data for the callback"] callback_data: u32, }, } impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::Done { .. } => 0u16, } } } #[doc = "callback object\n\nClients can handle the 'done' event to get notified when\nthe related request is done.\n\nSee also the [Event] enum for this interface."] #[derive(Debug, Clone)] pub struct WlCallback { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for WlCallback { fn eq(&self, other: &WlCallback) -> bool { self.id == other.id } } impl std::cmp::Eq for WlCallback {} impl PartialEq> for WlCallback { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for WlCallback { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for WlCallback { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for WlCallback { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::WL_CALLBACK_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(WlCallback { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { WlCallback { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let (Some(Argument::Uint(callback_data))) = (arg_iter.next()) { Ok((me, Event::Done { callback_data })) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::__phantom_lifetime { never, .. } => match never {}, } } } impl WlCallback {} } pub mod test_global { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_MANY_ARGS_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] pub const REQ_MANY_ARGS_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_GET_SECONDARY_SINCE: u32 = 2u32; #[doc = r" The wire opcode for this request"] pub const REQ_GET_SECONDARY_OPCODE: u16 = 1u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_GET_TERTIARY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_GET_TERTIARY_OPCODE: u16 = 2u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_LINK_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_LINK_OPCODE: u16 = 3u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 4u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 4u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_REVERSE_LINK_SINCE: u32 = 5u32; #[doc = r" The wire opcode for this request"] pub const REQ_REVERSE_LINK_OPCODE: u16 = 5u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_NEWID_AND_ALLOW_NULL_SINCE: u32 = 5u32; #[doc = r" The wire opcode for this request"] pub const REQ_NEWID_AND_ALLOW_NULL_OPCODE: u16 = 6u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_MANY_ARGS_EVT_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_MANY_ARGS_EVT_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_ACK_SECONDARY_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_ACK_SECONDARY_OPCODE: u16 = 1u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_CYCLE_QUAD_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_CYCLE_QUAD_OPCODE: u16 = 2u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "a request with every possible non-object arg"] ManyArgs { #[doc = "an unsigned int"] unsigned_int: u32, #[doc = "a singed int"] signed_int: i32, #[doc = "a fixed point number"] fixed_point: f64, #[doc = "an array"] number_array: Vec, #[doc = "some text"] some_text: String, #[doc = "a file descriptor"] file_descriptor: std::os::unix::io::BorrowedFd<'a>, }, #[doc = "Only available since version 2 of the interface"] GetSecondary {}, #[doc = "Only available since version 3 of the interface"] GetTertiary {}, #[doc = "link a secondary and a tertiary\n\n\n\nOnly available since version 3 of the interface"] Link { sec: super::secondary::Secondary, ter: Option, time: u32 }, #[doc = "This is a destructor, once sent this object cannot be used any longer.\nOnly available since version 4 of the interface"] Destroy, #[doc = "reverse link a secondary and a tertiary\n\n\n\nOnly available since version 5 of the interface"] ReverseLink { sec: Option, ter: super::tertiary::Tertiary }, #[doc = "a newid request that also takes allow null arg\n\n\n\nOnly available since version 5 of the interface"] NewidAndAllowNull { sec: Option, ter: super::tertiary::Tertiary, }, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::ManyArgs { .. } => 0u16, Request::GetSecondary { .. } => 1u16, Request::GetTertiary { .. } => 2u16, Request::Link { .. } => 3u16, Request::Destroy => 4u16, Request::ReverseLink { .. } => 5u16, Request::NewidAndAllowNull { .. } => 6u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event { #[doc = "an event with every possible non-object arg"] ManyArgsEvt { #[doc = "an unsigned int"] unsigned_int: u32, #[doc = "a singed int"] signed_int: i32, #[doc = "a fixed point number"] fixed_point: f64, #[doc = "an array"] number_array: Vec, #[doc = "some text"] some_text: String, #[doc = "a file descriptor"] file_descriptor: OwnedFd, }, #[doc = "acking the creation of a secondary"] AckSecondary { sec: super::secondary::Secondary }, #[doc = "create a new quad optionally replacing a previous one"] CycleQuad { new_quad: super::quad::Quad, old_quad: Option }, } impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::ManyArgsEvt { .. } => 0u16, Event::AckSecondary { .. } => 1u16, Event::CycleQuad { .. } => 2u16, } } } #[doc = "test_global\n\nSee also the [Event] enum for this interface."] #[derive(Debug, Clone)] pub struct TestGlobal { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for TestGlobal { fn eq(&self, other: &TestGlobal) -> bool { self.id == other.id } } impl std::cmp::Eq for TestGlobal {} impl PartialEq> for TestGlobal { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for TestGlobal { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for TestGlobal { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for TestGlobal { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::TEST_GLOBAL_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(TestGlobal { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { TestGlobal { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let ( Some(Argument::Uint(unsigned_int)), Some(Argument::Int(signed_int)), Some(Argument::Fixed(fixed_point)), Some(Argument::Array(number_array)), Some(Argument::Str(some_text)), Some(Argument::Fd(file_descriptor)), ) = ( arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), ) { Ok(( me, Event::ManyArgsEvt { unsigned_int, signed_int, fixed_point: (fixed_point as f64) / 256., number_array: *number_array, some_text: String::from_utf8_lossy( some_text.as_ref().unwrap().as_bytes(), ) .into_owned(), file_descriptor, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 1u16 => { if let (Some(Argument::Object(sec))) = (arg_iter.next()) { Ok(( me, Event::AckSecondary { sec: match ::from_id( conn, sec.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 2u16 => { if let (Some(Argument::NewId(new_quad)), Some(Argument::Object(old_quad))) = (arg_iter.next(), arg_iter.next()) { Ok(( me, Event::CycleQuad { new_quad: match ::from_id( conn, new_quad.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, old_quad: if old_quad.is_null() { None } else { Some( match ::from_id( conn, old_quad.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ) }, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::ManyArgs { unsigned_int, signed_int, fixed_point, number_array, some_text, file_descriptor, } => { let child_spec = None; let args = smallvec::SmallVec::from_vec(vec![ Argument::Uint(unsigned_int), Argument::Int(signed_int), Argument::Fixed((fixed_point * 256.) as i32), Argument::Array(Box::new(number_array)), Argument::Str(Some(Box::new(std::ffi::CString::new(some_text).unwrap()))), Argument::Fd(file_descriptor), ]); Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::GetSecondary {} => { let child_spec = { let my_info = conn.object_info(self.id())?; Some((super::secondary::Secondary::interface(), my_info.version)) }; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(ObjectId::null())); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 1u16, args }, child_spec)) } Request::GetTertiary {} => { let child_spec = { let my_info = conn.object_info(self.id())?; Some((super::tertiary::Tertiary::interface(), my_info.version)) }; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(ObjectId::null())); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 2u16, args }, child_spec)) } Request::Link { sec, ter, time } => { let child_spec = None; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::Object(Proxy::id(&sec))); vec.push(if let Some(obj) = ter { Argument::Object(Proxy::id(&obj)) } else { Argument::Object(ObjectId::null()) }); vec.push(Argument::Uint(time)); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 3u16, args }, child_spec)) } Request::Destroy {} => { let child_spec = None; let args = smallvec::SmallVec::new(); Ok((Message { sender_id: self.id.clone(), opcode: 4u16, args }, child_spec)) } Request::ReverseLink { sec, ter } => { let child_spec = None; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(if let Some(obj) = sec { Argument::Object(Proxy::id(&obj)) } else { Argument::Object(ObjectId::null()) }); vec.push(Argument::Object(Proxy::id(&ter))); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 5u16, args }, child_spec)) } Request::NewidAndAllowNull { sec, ter } => { let child_spec = { let my_info = conn.object_info(self.id())?; Some((super::quad::Quad::interface(), my_info.version)) }; let args = { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(ObjectId::null())); vec.push(if let Some(obj) = sec { Argument::Object(Proxy::id(&obj)) } else { Argument::Object(ObjectId::null()) }); vec.push(Argument::Object(Proxy::id(&ter))); vec }; Ok((Message { sender_id: self.id.clone(), opcode: 6u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl TestGlobal { #[doc = "a request with every possible non-object arg"] #[allow(clippy::too_many_arguments)] pub fn many_args( &self, unsigned_int: u32, signed_int: i32, fixed_point: f64, number_array: Vec, some_text: String, file_descriptor: ::std::os::unix::io::BorrowedFd<'_>, ) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request( self, Request::ManyArgs { unsigned_int, signed_int, fixed_point, number_array, some_text, file_descriptor, }, None, ); } #[allow(clippy::too_many_arguments)] pub fn get_secondary< U: Send + Sync + 'static, D: Dispatch + 'static, >( &self, qh: &QueueHandle, udata: U, ) -> super::secondary::Secondary { self.send_constructor( Request::GetSecondary {}, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } #[allow(clippy::too_many_arguments)] pub fn get_tertiary< U: Send + Sync + 'static, D: Dispatch + 'static, >( &self, qh: &QueueHandle, udata: U, ) -> super::tertiary::Tertiary { self.send_constructor( Request::GetTertiary {}, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } #[doc = "link a secondary and a tertiary"] #[allow(clippy::too_many_arguments)] pub fn link( &self, sec: &super::secondary::Secondary, ter: Option<&super::tertiary::Tertiary>, time: u32, ) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request( self, Request::Link { sec: sec.clone(), ter: ter.cloned(), time }, None, ); } #[allow(clippy::too_many_arguments)] pub fn destroy(&self) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request(self, Request::Destroy {}, None); } #[doc = "reverse link a secondary and a tertiary"] #[allow(clippy::too_many_arguments)] pub fn reverse_link( &self, sec: Option<&super::secondary::Secondary>, ter: &super::tertiary::Tertiary, ) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request( self, Request::ReverseLink { sec: sec.cloned(), ter: ter.clone() }, None, ); } #[doc = "a newid request that also takes allow null arg"] #[allow(clippy::too_many_arguments)] pub fn newid_and_allow_null< U: Send + Sync + 'static, D: Dispatch + 'static, >( &self, sec: Option<&super::secondary::Secondary>, ter: &super::tertiary::Tertiary, qh: &QueueHandle, udata: U, ) -> super::quad::Quad { self.send_constructor( Request::NewidAndAllowNull { sec: sec.cloned(), ter: ter.clone() }, qh.make_data::(udata), ) .unwrap_or_else(|_| Proxy::inert(self.backend.clone())) } } } pub mod secondary { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 2u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "This is a destructor, once sent this object cannot be used any longer.\nOnly available since version 2 of the interface"] Destroy, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event {} impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self {} } } #[doc = "secondary\n\nThis interface has no events."] #[derive(Debug, Clone)] pub struct Secondary { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for Secondary { fn eq(&self, other: &Secondary) -> bool { self.id == other.id } } impl std::cmp::Eq for Secondary {} impl PartialEq> for Secondary { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Secondary { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Secondary { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for Secondary { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::SECONDARY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(Secondary { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { Secondary { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::Destroy {} => { let child_spec = None; let args = smallvec::SmallVec::new(); Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl Secondary { #[allow(clippy::too_many_arguments)] pub fn destroy(&self) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request(self, Request::Destroy {}, None); } } } pub mod tertiary { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "This is a destructor, once sent this object cannot be used any longer.\nOnly available since version 3 of the interface"] Destroy, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event {} impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self {} } } #[doc = "tertiary\n\nThis interface has no events."] #[derive(Debug, Clone)] pub struct Tertiary { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for Tertiary { fn eq(&self, other: &Tertiary) -> bool { self.id == other.id } } impl std::cmp::Eq for Tertiary {} impl PartialEq> for Tertiary { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Tertiary { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Tertiary { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for Tertiary { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::TERTIARY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(Tertiary { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { Tertiary { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::Destroy {} => { let child_spec = None; let args = smallvec::SmallVec::new(); Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl Tertiary { #[allow(clippy::too_many_arguments)] pub fn destroy(&self) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request(self, Request::Destroy {}, None); } } } pub mod quad { use super::wayland_client::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, Backend, InvalidId, ObjectData, ObjectId, WeakBackend, }, Connection, Dispatch, DispatchError, Proxy, QueueHandle, QueueProxyData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request<'a> { #[doc = "This is a destructor, once sent this object cannot be used any longer.\nOnly available since version 3 of the interface"] Destroy, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Request<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, Request::__phantom_lifetime { never, .. } => match never {}, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event {} impl Event { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self {} } } #[doc = "quad\n\nThis interface has no events."] #[derive(Debug, Clone)] pub struct Quad { id: ObjectId, version: u32, data: Option>, backend: WeakBackend, } impl std::cmp::PartialEq for Quad { fn eq(&self, other: &Quad) -> bool { self.id == other.id } } impl std::cmp::Eq for Quad {} impl PartialEq> for Quad { fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Quad { fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Quad { fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_client::Proxy for Quad { type Request<'request> = Request<'request>; type Event = Event; #[inline] fn interface() -> &'static Interface { &super::QUAD_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data.as_ref().and_then(|arc| arc.data_as_any().downcast_ref::()) } fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn backend(&self) -> &WeakBackend { &self.backend } 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 { 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) } #[inline] fn from_id(conn: &Connection, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); let backend = conn.backend().downgrade(); Ok(Quad { id, data, version, backend }) } #[inline] fn inert(backend: WeakBackend) -> Self { Quad { id: ObjectId::null(), data: None, version: 0, backend } } fn parse_event( conn: &Connection, msg: Message, ) -> Result<(Self, Self::Event), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_request<'a>( &self, conn: &Connection, msg: Self::Request<'a>, ) -> Result< (Message>, Option<(&'static Interface, u32)>), InvalidId, > { match msg { Request::Destroy {} => { let child_spec = None; let args = smallvec::SmallVec::new(); Ok((Message { sender_id: self.id.clone(), opcode: 0u16, args }, child_spec)) } Request::__phantom_lifetime { never, .. } => match never {}, } } } impl Quad { #[allow(clippy::too_many_arguments)] pub fn destroy(&self) { let backend = match self.backend.upgrade() { Some(b) => b, None => return, }; let conn = Connection::from_backend(backend); let _ = conn.send_request(self, Request::Destroy {}, None); } } } wayland-scanner-0.31.6/tests/scanner_assets/test-headerless-protocol.xml000064400000000000000000000000531046102023000246310ustar 00000000000000 wayland-scanner-0.31.6/tests/scanner_assets/test-interfaces.rs000064400000000000000000000555261046102023000226410ustar 00000000000000use std::ptr::null; struct SyncWrapper(T); unsafe impl Sync for SyncWrapper {} static types_null: SyncWrapper<[*const wayland_backend::protocol::wl_interface; 6]> = SyncWrapper([null::(); 6]); pub static WL_DISPLAY_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "wl_display", version: 1u32, requests: &[ wayland_backend::protocol::MessageDesc { name: "sync", signature: &[wayland_backend::protocol::ArgumentType::NewId], since: 1u32, is_destructor: false, child_interface: Some(&WL_CALLBACK_INTERFACE), arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "get_registry", signature: &[wayland_backend::protocol::ArgumentType::NewId], since: 1u32, is_destructor: false, child_interface: Some(&WL_REGISTRY_INTERFACE), arg_interfaces: &[], }, ], events: &[ wayland_backend::protocol::MessageDesc { name: "error", signature: &[ wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::Str( wayland_backend::protocol::AllowNull::No, ), ], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[&wayland_backend::protocol::ANONYMOUS_INTERFACE], }, wayland_backend::protocol::MessageDesc { name: "delete_id", signature: &[wayland_backend::protocol::ArgumentType::Uint], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }, ], c_ptr: Some(unsafe { &wl_display_interface }), }; static wl_display_requests_sync_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 1], > = SyncWrapper([&wl_callback_interface as *const wayland_backend::protocol::wl_interface]); static wl_display_requests_get_registry_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 1], > = SyncWrapper([&wl_registry_interface as *const wayland_backend::protocol::wl_interface]); static wl_display_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 2]> = SyncWrapper([ wayland_backend::protocol::wl_message { name: b"sync\0" as *const u8 as *const std::os::raw::c_char, signature: b"n\0" as *const u8 as *const std::os::raw::c_char, types: wl_display_requests_sync_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"get_registry\0" as *const u8 as *const std::os::raw::c_char, signature: b"n\0" as *const u8 as *const std::os::raw::c_char, types: wl_display_requests_get_registry_types.0.as_ptr(), }, ]); static wl_display_events: SyncWrapper<[wayland_backend::protocol::wl_message; 2]> = SyncWrapper([ wayland_backend::protocol::wl_message { name: b"error\0" as *const u8 as *const std::os::raw::c_char, signature: b"ous\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"delete_id\0" as *const u8 as *const std::os::raw::c_char, signature: b"u\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, ]); pub static wl_display_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"wl_display\0" as *const u8 as *const std::os::raw::c_char, version: 1, request_count: 2, requests: wl_display_requests.0.as_ptr(), event_count: 2, events: wl_display_events.0.as_ptr(), }; pub static WL_REGISTRY_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "wl_registry", version: 1u32, requests: &[wayland_backend::protocol::MessageDesc { name: "bind", signature: &[ wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::Str( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::NewId, ], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }], events: &[ wayland_backend::protocol::MessageDesc { name: "global", signature: &[ wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::Str( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Uint, ], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "global_remove", signature: &[wayland_backend::protocol::ArgumentType::Uint], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }, ], c_ptr: Some(unsafe { &wl_registry_interface }), }; static wl_registry_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 1]> = SyncWrapper([wayland_backend::protocol::wl_message { name: b"bind\0" as *const u8 as *const std::os::raw::c_char, signature: b"usun\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }]); static wl_registry_events: SyncWrapper<[wayland_backend::protocol::wl_message; 2]> = SyncWrapper([ wayland_backend::protocol::wl_message { name: b"global\0" as *const u8 as *const std::os::raw::c_char, signature: b"usu\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"global_remove\0" as *const u8 as *const std::os::raw::c_char, signature: b"u\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, ]); pub static wl_registry_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"wl_registry\0" as *const u8 as *const std::os::raw::c_char, version: 1, request_count: 1, requests: wl_registry_requests.0.as_ptr(), event_count: 2, events: wl_registry_events.0.as_ptr(), }; pub static WL_CALLBACK_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "wl_callback", version: 1u32, requests: &[], events: &[wayland_backend::protocol::MessageDesc { name: "done", signature: &[wayland_backend::protocol::ArgumentType::Uint], since: 1u32, is_destructor: true, child_interface: None, arg_interfaces: &[], }], c_ptr: Some(unsafe { &wl_callback_interface }), }; static wl_callback_events: SyncWrapper<[wayland_backend::protocol::wl_message; 1]> = SyncWrapper([wayland_backend::protocol::wl_message { name: b"done\0" as *const u8 as *const std::os::raw::c_char, signature: b"u\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }]); pub static wl_callback_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"wl_callback\0" as *const u8 as *const std::os::raw::c_char, version: 1, request_count: 0, requests: null::(), event_count: 1, events: wl_callback_events.0.as_ptr(), }; pub static TEST_GLOBAL_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "test_global", version: 5u32, requests: &[ wayland_backend::protocol::MessageDesc { name: "many_args", signature: &[ wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::Int, wayland_backend::protocol::ArgumentType::Fixed, wayland_backend::protocol::ArgumentType::Array, wayland_backend::protocol::ArgumentType::Str( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Fd, ], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "get_secondary", signature: &[wayland_backend::protocol::ArgumentType::NewId], since: 2u32, is_destructor: false, child_interface: Some(&SECONDARY_INTERFACE), arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "get_tertiary", signature: &[wayland_backend::protocol::ArgumentType::NewId], since: 3u32, is_destructor: false, child_interface: Some(&TERTIARY_INTERFACE), arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "link", signature: &[ wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::Yes, ), wayland_backend::protocol::ArgumentType::Uint, ], since: 3u32, is_destructor: false, child_interface: None, arg_interfaces: &[&SECONDARY_INTERFACE, &TERTIARY_INTERFACE], }, wayland_backend::protocol::MessageDesc { name: "destroy", signature: &[], since: 4u32, is_destructor: true, child_interface: None, arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "reverse_link", signature: &[ wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::Yes, ), wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::No, ), ], since: 5u32, is_destructor: false, child_interface: None, arg_interfaces: &[&SECONDARY_INTERFACE, &TERTIARY_INTERFACE], }, wayland_backend::protocol::MessageDesc { name: "newid_and_allow_null", signature: &[ wayland_backend::protocol::ArgumentType::NewId, wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::Yes, ), wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::No, ), ], since: 5u32, is_destructor: false, child_interface: Some(&QUAD_INTERFACE), arg_interfaces: &[&SECONDARY_INTERFACE, &TERTIARY_INTERFACE], }, ], events: &[ wayland_backend::protocol::MessageDesc { name: "many_args_evt", signature: &[ wayland_backend::protocol::ArgumentType::Uint, wayland_backend::protocol::ArgumentType::Int, wayland_backend::protocol::ArgumentType::Fixed, wayland_backend::protocol::ArgumentType::Array, wayland_backend::protocol::ArgumentType::Str( wayland_backend::protocol::AllowNull::No, ), wayland_backend::protocol::ArgumentType::Fd, ], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[], }, wayland_backend::protocol::MessageDesc { name: "ack_secondary", signature: &[wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::No, )], since: 1u32, is_destructor: false, child_interface: None, arg_interfaces: &[&SECONDARY_INTERFACE], }, wayland_backend::protocol::MessageDesc { name: "cycle_quad", signature: &[ wayland_backend::protocol::ArgumentType::NewId, wayland_backend::protocol::ArgumentType::Object( wayland_backend::protocol::AllowNull::Yes, ), ], since: 1u32, is_destructor: false, child_interface: Some(&QUAD_INTERFACE), arg_interfaces: &[&QUAD_INTERFACE], }, ], c_ptr: Some(unsafe { &test_global_interface }), }; static test_global_requests_get_secondary_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 1], > = SyncWrapper([&secondary_interface as *const wayland_backend::protocol::wl_interface]); static test_global_requests_get_tertiary_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 1], > = SyncWrapper([&tertiary_interface as *const wayland_backend::protocol::wl_interface]); static test_global_requests_link_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 3], > = SyncWrapper([ &secondary_interface as *const wayland_backend::protocol::wl_interface, &tertiary_interface as *const wayland_backend::protocol::wl_interface, null::(), ]); static test_global_requests_reverse_link_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 2], > = SyncWrapper([ &secondary_interface as *const wayland_backend::protocol::wl_interface, &tertiary_interface as *const wayland_backend::protocol::wl_interface, ]); static test_global_requests_newid_and_allow_null_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 3], > = SyncWrapper([ &quad_interface as *const wayland_backend::protocol::wl_interface, &secondary_interface as *const wayland_backend::protocol::wl_interface, &tertiary_interface as *const wayland_backend::protocol::wl_interface, ]); static test_global_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 7]> = SyncWrapper([ wayland_backend::protocol::wl_message { name: b"many_args\0" as *const u8 as *const std::os::raw::c_char, signature: b"uifash\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"get_secondary\0" as *const u8 as *const std::os::raw::c_char, signature: b"2n\0" as *const u8 as *const std::os::raw::c_char, types: test_global_requests_get_secondary_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"get_tertiary\0" as *const u8 as *const std::os::raw::c_char, signature: b"3n\0" as *const u8 as *const std::os::raw::c_char, types: test_global_requests_get_tertiary_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"link\0" as *const u8 as *const std::os::raw::c_char, signature: b"3o?ou\0" as *const u8 as *const std::os::raw::c_char, types: test_global_requests_link_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"destroy\0" as *const u8 as *const std::os::raw::c_char, signature: b"4\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"reverse_link\0" as *const u8 as *const std::os::raw::c_char, signature: b"5?oo\0" as *const u8 as *const std::os::raw::c_char, types: test_global_requests_reverse_link_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"newid_and_allow_null\0" as *const u8 as *const std::os::raw::c_char, signature: b"5n?oo\0" as *const u8 as *const std::os::raw::c_char, types: test_global_requests_newid_and_allow_null_types.0.as_ptr(), }, ]); static test_global_events_ack_secondary_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 1], > = SyncWrapper([&secondary_interface as *const wayland_backend::protocol::wl_interface]); static test_global_events_cycle_quad_types: SyncWrapper< [*const wayland_backend::protocol::wl_interface; 2], > = SyncWrapper([ &quad_interface as *const wayland_backend::protocol::wl_interface, &quad_interface as *const wayland_backend::protocol::wl_interface, ]); static test_global_events: SyncWrapper<[wayland_backend::protocol::wl_message; 3]> = SyncWrapper([ wayland_backend::protocol::wl_message { name: b"many_args_evt\0" as *const u8 as *const std::os::raw::c_char, signature: b"uifash\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"ack_secondary\0" as *const u8 as *const std::os::raw::c_char, signature: b"o\0" as *const u8 as *const std::os::raw::c_char, types: test_global_events_ack_secondary_types.0.as_ptr(), }, wayland_backend::protocol::wl_message { name: b"cycle_quad\0" as *const u8 as *const std::os::raw::c_char, signature: b"n?o\0" as *const u8 as *const std::os::raw::c_char, types: test_global_events_cycle_quad_types.0.as_ptr(), }, ]); pub static test_global_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"test_global\0" as *const u8 as *const std::os::raw::c_char, version: 5, request_count: 7, requests: test_global_requests.0.as_ptr(), event_count: 3, events: test_global_events.0.as_ptr(), }; pub static SECONDARY_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "secondary", version: 5u32, requests: &[wayland_backend::protocol::MessageDesc { name: "destroy", signature: &[], since: 2u32, is_destructor: true, child_interface: None, arg_interfaces: &[], }], events: &[], c_ptr: Some(unsafe { &secondary_interface }), }; static secondary_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 1]> = SyncWrapper([wayland_backend::protocol::wl_message { name: b"destroy\0" as *const u8 as *const std::os::raw::c_char, signature: b"2\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }]); pub static secondary_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"secondary\0" as *const u8 as *const std::os::raw::c_char, version: 5, request_count: 1, requests: secondary_requests.0.as_ptr(), event_count: 0, events: null::(), }; pub static TERTIARY_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "tertiary", version: 5u32, requests: &[wayland_backend::protocol::MessageDesc { name: "destroy", signature: &[], since: 3u32, is_destructor: true, child_interface: None, arg_interfaces: &[], }], events: &[], c_ptr: Some(unsafe { &tertiary_interface }), }; static tertiary_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 1]> = SyncWrapper([wayland_backend::protocol::wl_message { name: b"destroy\0" as *const u8 as *const std::os::raw::c_char, signature: b"3\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }]); pub static tertiary_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"tertiary\0" as *const u8 as *const std::os::raw::c_char, version: 5, request_count: 1, requests: tertiary_requests.0.as_ptr(), event_count: 0, events: null::(), }; pub static QUAD_INTERFACE: wayland_backend::protocol::Interface = wayland_backend::protocol::Interface { name: "quad", version: 5u32, requests: &[wayland_backend::protocol::MessageDesc { name: "destroy", signature: &[], since: 3u32, is_destructor: true, child_interface: None, arg_interfaces: &[], }], events: &[], c_ptr: Some(unsafe { &quad_interface }), }; static quad_requests: SyncWrapper<[wayland_backend::protocol::wl_message; 1]> = SyncWrapper([wayland_backend::protocol::wl_message { name: b"destroy\0" as *const u8 as *const std::os::raw::c_char, signature: b"3\0" as *const u8 as *const std::os::raw::c_char, types: types_null.0.as_ptr(), }]); pub static quad_interface: wayland_backend::protocol::wl_interface = wayland_backend::protocol::wl_interface { name: b"quad\0" as *const u8 as *const std::os::raw::c_char, version: 5, request_count: 1, requests: quad_requests.0.as_ptr(), event_count: 0, events: null::(), }; wayland-scanner-0.31.6/tests/scanner_assets/test-protocol.xml000064400000000000000000000246741046102023000225330ustar 00000000000000 A dummy copyright to make the parser work Including a few more lines. Of text. The core global object. This is a special singleton object. It is used for internal Wayland protocol features. The sync request asks the server to emit the 'done' event on the returned wl_callback object. Since requests are handled in-order and events are delivered in-order, this can be used as a barrier to ensure all previous requests and the resulting events have been handled. The object returned by this request will be destroyed by the compositor after the callback is fired and as such the client must not attempt to use it after that point. The callback_data passed in the callback is the event serial. This request creates a registry object that allows the client to list and bind the global objects available from the compositor. It should be noted that the server side resources consumed in response to a get_registry request can only be released when the client disconnects, not when the client side proxy is destroyed. Therefore, clients should invoke get_registry as infrequently as possible to avoid wasting memory. The error event is sent out when a fatal (non-recoverable) error has occurred. The object_id argument is the object where the error occurred, most often in response to a request to that object. The code identifies the error and is defined by the object interface. As such, each interface defines its own set of error codes. The message is a brief description of the error, for (debugging) convenience. These errors are global and can be emitted in response to any server request. This event is used internally by the object ID management logic. When a client deletes an object that it had created, the server will send this event to acknowledge that it has seen the delete request. When the client receives this event, it will know that it can safely reuse the object ID. The singleton global registry object. The server has a number of global objects that are available to all clients. These objects typically represent an actual object in the server (for example, an input device) or they are singleton objects that provide extension functionality. When a client creates a registry object, the registry object will emit a global event for each global currently in the registry. Globals come and go as a result of device or monitor hotplugs, reconfiguration or other events, and the registry will send out global and global_remove events to keep the client up to date with the changes. To mark the end of the initial burst of events, the client can use the wl_display.sync request immediately after calling wl_display.get_registry. A client can bind to a global object by using the bind request. This creates a client-side handle that lets the object emit events to the client and lets the client invoke requests on the object. Binds a new, client-created object to the server using the specified name as the identifier. Notify the client of global objects. The event notifies the client that a global object with the given name is now available, and it implements the given version of the given interface. Notify the client of removed global objects. This event notifies the client that the global identified by name is no longer available. If the client bound to the global using the bind request, the client should now destroy that object. The object remains valid and requests to the object will be ignored until the client destroys it, to avoid races between the global going away and a client sending a request to it. Clients can handle the 'done' event to get notified when the related request is done. Notify the client when the related request is done. wayland-scanner-0.31.6/tests/scanner_assets/test-server-code.rs000064400000000000000000001413141046102023000227230ustar 00000000000000#[doc = "callback object\n\nClients can handle the 'done' event to get notified when\nthe related request is done."] pub mod wl_callback { use super::wayland_server::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this event"] pub const EVT_DONE_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_DONE_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request {} impl Request { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self {} } } #[derive(Debug)] #[non_exhaustive] pub enum Event<'a> { #[doc = "done event\n\nNotify the client when the related request is done.\n\nThis is a destructor, once sent this object cannot be used any longer."] Done { #[doc = "request-specific data for the callback"] callback_data: u32, }, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Event<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::Done { .. } => 0u16, Event::__phantom_lifetime { never, .. } => match never {}, } } } #[doc = "callback object\n\nClients can handle the 'done' event to get notified when\nthe related request is done.\n\nThis interface has no requests."] #[derive(Debug, Clone)] pub struct WlCallback { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for WlCallback { #[inline] fn eq(&self, other: &WlCallback) -> bool { self.id == other.id } } impl std::cmp::Eq for WlCallback {} impl PartialEq> for WlCallback { #[inline] fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for WlCallback { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for WlCallback { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for WlCallback { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface { &super::WL_CALLBACK_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data .as_ref() .and_then(|arc| (&**arc).downcast_ref::>()) .map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(WlCallback { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request( conn: &DisplayHandle, msg: Message, ) -> Result<(Self, Self::Request), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_event<'a>( &self, conn: &DisplayHandle, msg: Self::Event<'a>, ) -> Result>, InvalidId> { match msg { Event::Done { callback_data } => Ok(Message { sender_id: self.id.clone(), opcode: 0u16, args: { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::Uint(callback_data)); vec }, }), Event::__phantom_lifetime { never, .. } => match never {}, } } fn __set_object_data( &mut self, odata: std::sync::Arc, ) { self.data = Some(odata); } } impl WlCallback { #[doc = "done event\n\nNotify the client when the related request is done."] #[allow(clippy::too_many_arguments)] pub fn done(&self, callback_data: u32) { let _ = self.send_event(Event::Done { callback_data }); } } } pub mod test_global { use super::wayland_server::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_MANY_ARGS_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this request"] pub const REQ_MANY_ARGS_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_GET_SECONDARY_SINCE: u32 = 2u32; #[doc = r" The wire opcode for this request"] pub const REQ_GET_SECONDARY_OPCODE: u16 = 1u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_GET_TERTIARY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_GET_TERTIARY_OPCODE: u16 = 2u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_LINK_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_LINK_OPCODE: u16 = 3u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 4u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 4u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_REVERSE_LINK_SINCE: u32 = 5u32; #[doc = r" The wire opcode for this request"] pub const REQ_REVERSE_LINK_OPCODE: u16 = 5u16; #[doc = r" The minimal object version supporting this request"] pub const REQ_NEWID_AND_ALLOW_NULL_SINCE: u32 = 5u32; #[doc = r" The wire opcode for this request"] pub const REQ_NEWID_AND_ALLOW_NULL_OPCODE: u16 = 6u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_MANY_ARGS_EVT_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_MANY_ARGS_EVT_OPCODE: u16 = 0u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_ACK_SECONDARY_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_ACK_SECONDARY_OPCODE: u16 = 1u16; #[doc = r" The minimal object version supporting this event"] pub const EVT_CYCLE_QUAD_SINCE: u32 = 1u32; #[doc = r" The wire opcode for this event"] pub const EVT_CYCLE_QUAD_OPCODE: u16 = 2u16; #[derive(Debug)] #[non_exhaustive] pub enum Request { #[doc = "a request with every possible non-object arg"] ManyArgs { #[doc = "an unsigned int"] unsigned_int: u32, #[doc = "a singed int"] signed_int: i32, #[doc = "a fixed point number"] fixed_point: f64, #[doc = "an array"] number_array: Vec, #[doc = "some text"] some_text: String, #[doc = "a file descriptor"] file_descriptor: OwnedFd, }, #[doc = "Only available since version 2 of the interface"] GetSecondary { #[doc = "create a secondary"] sec: New, }, #[doc = "Only available since version 3 of the interface"] GetTertiary { #[doc = "create a tertiary"] ter: New, }, #[doc = "link a secondary and a tertiary\n\n\n\nOnly available since version 3 of the interface"] Link { sec: super::secondary::Secondary, ter: Option, time: u32 }, #[doc = "This is a destructor, once received this object cannot be used any longer.\nOnly available since version 4 of the interface"] Destroy, #[doc = "reverse link a secondary and a tertiary\n\n\n\nOnly available since version 5 of the interface"] ReverseLink { sec: Option, ter: super::tertiary::Tertiary }, #[doc = "a newid request that also takes allow null arg\n\n\n\nOnly available since version 5 of the interface"] NewidAndAllowNull { quad: New, sec: Option, ter: super::tertiary::Tertiary, }, } impl Request { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::ManyArgs { .. } => 0u16, Request::GetSecondary { .. } => 1u16, Request::GetTertiary { .. } => 2u16, Request::Link { .. } => 3u16, Request::Destroy => 4u16, Request::ReverseLink { .. } => 5u16, Request::NewidAndAllowNull { .. } => 6u16, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event<'a> { #[doc = "an event with every possible non-object arg"] ManyArgsEvt { #[doc = "an unsigned int"] unsigned_int: u32, #[doc = "a singed int"] signed_int: i32, #[doc = "a fixed point number"] fixed_point: f64, #[doc = "an array"] number_array: Vec, #[doc = "some text"] some_text: String, #[doc = "a file descriptor"] file_descriptor: std::os::unix::io::BorrowedFd<'a>, }, #[doc = "acking the creation of a secondary"] AckSecondary { sec: super::secondary::Secondary }, #[doc = "create a new quad optionally replacing a previous one"] CycleQuad { new_quad: super::quad::Quad, old_quad: Option }, #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Event<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::ManyArgsEvt { .. } => 0u16, Event::AckSecondary { .. } => 1u16, Event::CycleQuad { .. } => 2u16, Event::__phantom_lifetime { never, .. } => match never {}, } } } #[doc = "test_global\n\nSee also the [Request] enum for this interface."] #[derive(Debug, Clone)] pub struct TestGlobal { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for TestGlobal { #[inline] fn eq(&self, other: &TestGlobal) -> bool { self.id == other.id } } impl std::cmp::Eq for TestGlobal {} impl PartialEq> for TestGlobal { #[inline] fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for TestGlobal { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for TestGlobal { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for TestGlobal { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface { &super::TEST_GLOBAL_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data .as_ref() .and_then(|arc| (&**arc).downcast_ref::>()) .map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(TestGlobal { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request( conn: &DisplayHandle, msg: Message, ) -> Result<(Self, Self::Request), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let ( Some(Argument::Uint(unsigned_int)), Some(Argument::Int(signed_int)), Some(Argument::Fixed(fixed_point)), Some(Argument::Array(number_array)), Some(Argument::Str(some_text)), Some(Argument::Fd(file_descriptor)), ) = ( arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), arg_iter.next(), ) { Ok(( me, Request::ManyArgs { unsigned_int, signed_int, fixed_point: (fixed_point as f64) / 256., number_array: *number_array, some_text: String::from_utf8_lossy( some_text.as_ref().unwrap().as_bytes(), ) .into_owned(), file_descriptor, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 1u16 => { if let (Some(Argument::NewId(sec))) = (arg_iter.next()) { Ok(( me, Request::GetSecondary { sec: New::wrap( match ::from_id( conn, sec.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ), }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 2u16 => { if let (Some(Argument::NewId(ter))) = (arg_iter.next()) { Ok(( me, Request::GetTertiary { ter: New::wrap( match ::from_id( conn, ter.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ), }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 3u16 => { if let ( Some(Argument::Object(sec)), Some(Argument::Object(ter)), Some(Argument::Uint(time)), ) = (arg_iter.next(), arg_iter.next(), arg_iter.next()) { Ok(( me, Request::Link { sec: match ::from_id( conn, sec.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ter: if ter.is_null() { None } else { Some( match ::from_id( conn, ter.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ) }, time, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 4u16 => { if let () = () { Ok((me, Request::Destroy {})) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 5u16 => { if let (Some(Argument::Object(sec)), Some(Argument::Object(ter))) = (arg_iter.next(), arg_iter.next()) { Ok(( me, Request::ReverseLink { sec: if sec.is_null() { None } else { Some( match ::from_id( conn, sec.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ) }, ter: match ::from_id( conn, ter.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } 6u16 => { if let ( Some(Argument::NewId(quad)), Some(Argument::Object(sec)), Some(Argument::Object(ter)), ) = (arg_iter.next(), arg_iter.next(), arg_iter.next()) { Ok(( me, Request::NewidAndAllowNull { quad: New::wrap( match ::from_id( conn, quad.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ), sec: if sec.is_null() { None } else { Some( match ::from_id( conn, sec.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, ) }, ter: match ::from_id( conn, ter.clone(), ) { Ok(p) => p, Err(_) => { return Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } }, }, )) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_event<'a>( &self, conn: &DisplayHandle, msg: Self::Event<'a>, ) -> Result>, InvalidId> { match msg { Event::ManyArgsEvt { unsigned_int, signed_int, fixed_point, number_array, some_text, file_descriptor, } => Ok(Message { sender_id: self.id.clone(), opcode: 0u16, args: smallvec::SmallVec::from_vec(vec![ Argument::Uint(unsigned_int), Argument::Int(signed_int), Argument::Fixed((fixed_point * 256.) as i32), Argument::Array(Box::new(number_array)), Argument::Str(Some(Box::new(std::ffi::CString::new(some_text).unwrap()))), Argument::Fd(file_descriptor), ]), }), Event::AckSecondary { sec } => Ok(Message { sender_id: self.id.clone(), opcode: 1u16, args: { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::Object(Resource::id(&sec))); vec }, }), Event::CycleQuad { new_quad, old_quad } => Ok(Message { sender_id: self.id.clone(), opcode: 2u16, args: { let mut vec = smallvec::SmallVec::new(); vec.push(Argument::NewId(Resource::id(&new_quad))); vec.push(if let Some(obj) = old_quad { Argument::Object(Resource::id(&obj)) } else { Argument::Object(ObjectId::null()) }); vec }, }), Event::__phantom_lifetime { never, .. } => match never {}, } } fn __set_object_data( &mut self, odata: std::sync::Arc, ) { self.data = Some(odata); } } impl TestGlobal { #[doc = "an event with every possible non-object arg"] #[allow(clippy::too_many_arguments)] pub fn many_args_evt( &self, unsigned_int: u32, signed_int: i32, fixed_point: f64, number_array: Vec, some_text: String, file_descriptor: ::std::os::unix::io::BorrowedFd<'_>, ) { let _ = self.send_event(Event::ManyArgsEvt { unsigned_int, signed_int, fixed_point, number_array, some_text, file_descriptor, }); } #[doc = "acking the creation of a secondary"] #[allow(clippy::too_many_arguments)] pub fn ack_secondary(&self, sec: &super::secondary::Secondary) { let _ = self.send_event(Event::AckSecondary { sec: sec.clone() }); } #[doc = "create a new quad optionally replacing a previous one"] #[allow(clippy::too_many_arguments)] pub fn cycle_quad( &self, new_quad: &super::quad::Quad, old_quad: Option<&super::quad::Quad>, ) { let _ = self.send_event(Event::CycleQuad { new_quad: new_quad.clone(), old_quad: old_quad.cloned(), }); } } } pub mod secondary { use super::wayland_server::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 2u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request { #[doc = "This is a destructor, once received this object cannot be used any longer.\nOnly available since version 2 of the interface"] Destroy, } impl Request { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event<'a> { #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Event<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::__phantom_lifetime { never, .. } => match never {}, } } } #[doc = "secondary\n\nSee also the [Request] enum for this interface."] #[derive(Debug, Clone)] pub struct Secondary { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for Secondary { #[inline] fn eq(&self, other: &Secondary) -> bool { self.id == other.id } } impl std::cmp::Eq for Secondary {} impl PartialEq> for Secondary { #[inline] fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Secondary { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Secondary { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for Secondary { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface { &super::SECONDARY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data .as_ref() .and_then(|arc| (&**arc).downcast_ref::>()) .map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(Secondary { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request( conn: &DisplayHandle, msg: Message, ) -> Result<(Self, Self::Request), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let () = () { Ok((me, Request::Destroy {})) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_event<'a>( &self, conn: &DisplayHandle, msg: Self::Event<'a>, ) -> Result>, InvalidId> { match msg { Event::__phantom_lifetime { never, .. } => match never {}, } } fn __set_object_data( &mut self, odata: std::sync::Arc, ) { self.data = Some(odata); } } impl Secondary {} } pub mod tertiary { use super::wayland_server::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request { #[doc = "This is a destructor, once received this object cannot be used any longer.\nOnly available since version 3 of the interface"] Destroy, } impl Request { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event<'a> { #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Event<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::__phantom_lifetime { never, .. } => match never {}, } } } #[doc = "tertiary\n\nSee also the [Request] enum for this interface."] #[derive(Debug, Clone)] pub struct Tertiary { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for Tertiary { #[inline] fn eq(&self, other: &Tertiary) -> bool { self.id == other.id } } impl std::cmp::Eq for Tertiary {} impl PartialEq> for Tertiary { #[inline] fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Tertiary { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Tertiary { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for Tertiary { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface { &super::TERTIARY_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data .as_ref() .and_then(|arc| (&**arc).downcast_ref::>()) .map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(Tertiary { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request( conn: &DisplayHandle, msg: Message, ) -> Result<(Self, Self::Request), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let () = () { Ok((me, Request::Destroy {})) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_event<'a>( &self, conn: &DisplayHandle, msg: Self::Event<'a>, ) -> Result>, InvalidId> { match msg { Event::__phantom_lifetime { never, .. } => match never {}, } } fn __set_object_data( &mut self, odata: std::sync::Arc, ) { self.data = Some(odata); } } impl Tertiary {} } pub mod quad { use super::wayland_server::{ backend::{ protocol::{same_interface, Argument, Interface, Message, WEnum}, smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, }, Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, }; use std::sync::Arc; use std::os::unix::io::OwnedFd; #[doc = r" The minimal object version supporting this request"] pub const REQ_DESTROY_SINCE: u32 = 3u32; #[doc = r" The wire opcode for this request"] pub const REQ_DESTROY_OPCODE: u16 = 0u16; #[derive(Debug)] #[non_exhaustive] pub enum Request { #[doc = "This is a destructor, once received this object cannot be used any longer.\nOnly available since version 3 of the interface"] Destroy, } impl Request { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Request::Destroy => 0u16, } } } #[derive(Debug)] #[non_exhaustive] pub enum Event<'a> { #[doc(hidden)] __phantom_lifetime { phantom: std::marker::PhantomData<&'a ()>, never: std::convert::Infallible, }, } impl<'a> Event<'a> { #[doc = "Get the opcode number of this message"] pub fn opcode(&self) -> u16 { match *self { Event::__phantom_lifetime { never, .. } => match never {}, } } } #[doc = "quad\n\nSee also the [Request] enum for this interface."] #[derive(Debug, Clone)] pub struct Quad { id: ObjectId, version: u32, data: Option>, handle: WeakHandle, } impl std::cmp::PartialEq for Quad { #[inline] fn eq(&self, other: &Quad) -> bool { self.id == other.id } } impl std::cmp::Eq for Quad {} impl PartialEq> for Quad { #[inline] fn eq(&self, other: &Weak) -> bool { self.id == other.id() } } impl std::borrow::Borrow for Quad { #[inline] fn borrow(&self) -> &ObjectId { &self.id } } impl std::hash::Hash for Quad { #[inline] fn hash(&self, state: &mut H) { self.id.hash(state) } } impl super::wayland_server::Resource for Quad { type Request = Request; type Event<'event> = Event<'event>; #[inline] fn interface() -> &'static Interface { &super::QUAD_INTERFACE } #[inline] fn id(&self) -> ObjectId { self.id.clone() } #[inline] fn version(&self) -> u32 { self.version } #[inline] fn data(&self) -> Option<&U> { self.data .as_ref() .and_then(|arc| (&**arc).downcast_ref::>()) .map(|data| &data.udata) } #[inline] fn object_data(&self) -> Option<&Arc> { self.data.as_ref() } fn handle(&self) -> &WeakHandle { &self.handle } #[inline] fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { if !same_interface(id.interface(), Self::interface()) && !id.is_null() { return Err(InvalidId); } let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); let data = conn.get_object_data(id.clone()).ok(); Ok(Quad { id, data, version, handle: conn.backend_handle().downgrade() }) } fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); handle.send_event(self, evt) } fn parse_request( conn: &DisplayHandle, msg: Message, ) -> Result<(Self, Self::Request), DispatchError> { let me = Self::from_id(conn, msg.sender_id.clone()).unwrap(); let mut arg_iter = msg.args.into_iter(); match msg.opcode { 0u16 => { if let () = () { Ok((me, Request::Destroy {})) } else { Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }) } } _ => Err(DispatchError::BadMessage { sender_id: msg.sender_id, interface: Self::interface().name, opcode: msg.opcode, }), } } fn write_event<'a>( &self, conn: &DisplayHandle, msg: Self::Event<'a>, ) -> Result>, InvalidId> { match msg { Event::__phantom_lifetime { never, .. } => match never {}, } } fn __set_object_data( &mut self, odata: std::sync::Arc, ) { self.data = Some(odata); } } impl Quad {} }