macro_rules! efrom { ($ename:ty, $vname:ident) => { efrom!($ename, $vname, $vname); }; ($ename:ty, $vname:ident, $sname:ty) => { impl From<$sname> for $ename { fn from(e: $sname) -> Self { Self::$vname(Box::new(e)) } } }; } macro_rules! usr_object_base { ($self:ident = $oname:ident = $iname:ident; version = $version:expr;) => { impl crate::wl_usr::usr_object::UsrObjectBase for $oname { fn id(&$self) -> crate::object::ObjectId { $self.id.into() } fn version(&$self) -> crate::object::Version { $version } fn handle_event( $self: std::rc::Rc, con: &crate::wl_usr::UsrCon, event: u32, parser: crate::utils::buffd::MsgParser<'_, '_>, ) -> Result<(), crate::wl_usr::UsrConError> { $self.handle_event_impl(con, event, parser) } fn interface(&$self) -> crate::object::Interface { crate::wire::$iname } } }; } macro_rules! object_base { ($self:ident = $oname:ident; version = $version:expr;) => { impl crate::object::ObjectBase for $oname { fn id(&$self) -> crate::object::ObjectId { $self.id.into() } fn version(&$self) -> crate::object::Version { $version } fn into_any($self: std::rc::Rc) -> std::rc::Rc { $self } fn handle_request( $self: std::rc::Rc, client: &crate::client::Client, request: u32, parser: crate::utils::buffd::MsgParser<'_, '_>, ) -> Result<(), crate::client::ClientError> { $self.handle_request_impl(client, request, parser) } fn interface(&$self) -> crate::object::Interface { crate::wire::$oname } } }; } macro_rules! global_base { ($oname:ty, $ifname:ident, $ename:ty) => { impl crate::globals::GlobalBase for $oname { fn name(&self) -> crate::globals::GlobalName { self.name } fn bind<'a>( self: std::rc::Rc, client: &'a std::rc::Rc, id: crate::object::ObjectId, version: crate::object::Version, ) -> Result<(), crate::globals::GlobalsError> { if let Err(e) = self.bind_(id.into(), client, version) { return Err(crate::globals::GlobalsError::GlobalError(e.into())); } Ok(()) } fn interface(&self) -> crate::object::Interface { crate::wire::$ifname } } impl From<$ename> for crate::globals::GlobalError { fn from(e: $ename) -> Self { Self { interface: crate::wire::$ifname, error: Box::new(e), } } } }; } macro_rules! id { ($name:ident) => { #[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] pub struct $name(u32); #[expect(dead_code)] impl $name { pub const NONE: Self = $name(0); pub const fn from_raw(raw: u32) -> Self { Self(raw) } pub fn raw(self) -> u32 { self.0 } pub fn is_some(self) -> bool { self.0 != 0 } pub fn is_none(self) -> bool { self.0 == 0 } } impl From for $name { fn from(f: crate::object::ObjectId) -> Self { Self(f.raw()) } } impl From<$name> for crate::object::ObjectId { fn from(f: $name) -> Self { crate::object::ObjectId::from_raw(f.0) } } impl std::fmt::Display for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } }; } macro_rules! shared_ids { ($id:ident) => { shared_ids!($id, u32); }; ($id:ident, $ty:ty) => { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct $id($ty); impl $id { #[expect(dead_code)] pub fn raw(&self) -> $ty { self.0 } #[expect(dead_code)] pub fn from_raw(id: $ty) -> Self { Self(id) } } impl From<$ty> for $id { fn from(id: $ty) -> Self { Self(id) } } impl std::fmt::Display for $id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } }; } macro_rules! linear_ids { ($ids:ident, $id:ident) => { linear_ids!($ids, $id, u32); }; ($ids:ident, $id:ident, $ty:ty) => { pub struct $ids { next: crate::utils::numcell::NumCell<$ty>, } impl Default for $ids { fn default() -> Self { Self { next: crate::utils::numcell::NumCell::new(1), } } } impl $ids { pub fn next(&self) -> $id { $id(self.next.fetch_add(1)) } } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct $id($ty); impl $id { #[allow(clippy::allow_attributes, dead_code)] pub fn raw(&self) -> $ty { self.0 } #[allow(clippy::allow_attributes, dead_code)] pub fn from_raw(id: $ty) -> Self { Self(id) } } impl std::fmt::Display for $id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } }; } macro_rules! cenum { ($name:ident, $uc:ident; $($name2:ident = $val:expr,)*) => { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct $name(pub i32); impl $name { pub fn raw(self) -> i32 { self.0 } } pub const $uc: &[i32] = &[$($val,)*]; $( pub const $name2: $name = $name($val); )* } } macro_rules! bitor { ($name:ident) => { impl std::ops::BitOr for $name { type Output = Self; fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) } } impl $name { pub fn contains(self, rhs: Self) -> bool { self.0 & rhs.0 == rhs.0 } pub fn is_some(self) -> bool { self.0 != 0 } } }; } macro_rules! tree_id { ($id:ident) => { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct $id(u32); impl $id { #[allow(clippy::allow_attributes, dead_code)] pub fn raw(&self) -> u32 { self.0 } #[allow(clippy::allow_attributes, dead_code)] pub fn none() -> Self { Self(0) } } impl std::fmt::Display for $id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } impl From for $id { fn from(v: crate::tree::NodeId) -> $id { $id(v.0) } } impl From<$id> for crate::tree::NodeId { fn from(v: $id) -> crate::tree::NodeId { crate::tree::NodeId(v.0) } } impl PartialEq for $id { fn eq(&self, other: &crate::tree::NodeId) -> bool { self.0 == other.0 } } impl PartialEq<$id> for crate::tree::NodeId { fn eq(&self, other: &$id) -> bool { self.0 == other.0 } } }; } macro_rules! dedicated_add_obj { ($oname:ident, $idname:ident, $field:ident) => { impl crate::client::WaylandObject for $oname { fn add(self: Rc, client: &crate::client::Client) { client.objects.$field.set(self.id.into(), self); } fn remove(&self, client: &crate::client::Client) { client.objects.$field.remove(&self.id.into()); } } impl crate::client::WaylandObjectLookup for $idname { type Object = $oname; const INTERFACE: crate::object::Interface = crate::wire::$oname; fn lookup(client: &crate::client::Client, id: Self) -> Option> { client.objects.$field.get(&id) } } }; } macro_rules! simple_add_obj { ($ty:ty) => { impl crate::client::WaylandObject for $ty {} }; } macro_rules! simple_add_global { ($ty:ty) => { impl crate::globals::WaylandGlobal for $ty {} }; } macro_rules! dedicated_add_global { ($oname:ident, $field:ident) => { impl crate::globals::WaylandGlobal for $oname { fn add(self: Rc, globals: &crate::globals::Globals) { globals.$field.set(self.name, self); } fn remove(&self, globals: &crate::globals::Globals) { globals.$field.remove(&self.name); } } }; } macro_rules! assert_size_eq { ($t:ty, $u:ty) => {{ struct AssertEqSize(std::marker::PhantomData, std::marker::PhantomData); impl AssertEqSize { const VAL: usize = { if std::mem::size_of::() != std::mem::size_of::() { panic!("Types have different size"); } 1 }; } let _ = AssertEqSize::<$t, $u>::VAL; }}; } #[expect(unused_macros)] macro_rules! assert_size_le { ($t:ty, $u:ty) => {{ struct AssertLeSize(std::marker::PhantomData, std::marker::PhantomData); impl AssertLeSize { const VAL: usize = { if std::mem::size_of::() > std::mem::size_of::() { panic!("Left type has size larger than right type"); } 1 }; } let _ = AssertLeSize::<$t, $u>::VAL; }}; } macro_rules! assert_align_eq { ($t:ty, $u:ty) => {{ struct AssertEqAlign(std::marker::PhantomData, std::marker::PhantomData); impl AssertEqAlign { const VAL: usize = { if std::mem::align_of::() != std::mem::align_of::() { panic!("Types have different alignment"); } 1 }; } let _ = AssertEqAlign::<$t, $u>::VAL; }}; } macro_rules! atoms { { $name:ident; $($field_name:ident,)* } => { #[expect(non_snake_case, dead_code)] #[derive(Debug, Clone, Copy)] struct $name { $( $field_name: u32, )* } impl $name { fn get( conn: &std::rc::Rc, ) -> impl std::future::Future> { #![allow(non_snake_case)] use bstr::ByteSlice; $( let $field_name = conn.call(&InternAtom { only_if_exists: 0, name: stringify!($field_name).as_bytes().as_bstr(), }); )* async move { Ok(Self { $( $field_name: $field_name.await?.get().atom, )* }) } } } } } macro_rules! fatal { ($($arg:tt)+) => {{ log::error!($($arg)+); std::process::exit(1); }} } macro_rules! stacked_node_impl { () => { fn stacked_into_node(self: Rc) -> Rc { self } }; } macro_rules! bitflags { ($name:ident: $rep:ty; $($var:ident = $val:expr,)*) => { #[derive(Copy, Clone, Eq, PartialEq, Default)] pub struct $name(pub $rep); $( #[allow(clippy::allow_attributes, dead_code)] pub const $var: $name = $name($val); )* #[allow(clippy::allow_attributes, dead_code)] impl $name { pub fn none() -> Self { Self(0) } pub fn is_some(self) -> bool { self.0 != 0 } pub fn all() -> Self { Self(0 $(| $val)*) } pub fn is_valid(self) -> bool { Self::all().contains(self) } pub fn contains(self, other: Self) -> bool { self.0 & other.0 == other.0 } pub fn not_contains(self, other: Self) -> bool { self.0 & other.0 != other.0 } pub fn intersects(self, other: Self) -> bool { self.0 & other.0 != 0 } } impl std::ops::BitOr for $name { type Output = Self; fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) } } impl std::ops::BitAnd for $name { type Output = Self; fn bitand(self, rhs: Self) -> Self::Output { Self(self.0 & rhs.0) } } impl std::ops::BitOrAssign for $name { fn bitor_assign(&mut self, rhs: Self) { self.0 |= rhs.0; } } impl std::ops::BitAndAssign for $name { fn bitand_assign(&mut self, rhs: Self) { self.0 &= rhs.0; } } impl std::ops::BitXorAssign for $name { fn bitxor_assign(&mut self, rhs: Self) { self.0 ^= rhs.0; } } impl std::ops::Not for $name { type Output = Self; fn not(self) -> Self::Output { Self(!self.0) } } impl std::fmt::Debug for $name { #[allow(clippy::allow_attributes, clippy::bad_bit_mask)] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut any = false; let mut v = self.0; $( if $val != 0 && v & $val == $val { if any { write!(f, "|")?; } any = true; write!(f, "{}", stringify!($var))?; v &= !$val; } )* if !any || v != 0 { if any { write!(f, "|")?; } write!(f, "0x{:x}", v)?; } Ok(()) } } } } macro_rules! pw_opcodes { ($name:ident; $($var:ident = $val:expr,)*) => { #[derive(Copy, Clone, Debug)] pub enum $name { $( $var, )* } #[allow(clippy::allow_attributes, dead_code)] impl $name { pub fn from_id(id: u8) -> Option { let v = match id { $($val => Self::$var,)* _ => return None, }; Some(v) } pub fn name(self) -> &'static str { match self { $(Self::$var => stringify!($var),)* } } } impl crate::pipewire::pw_object::PwOpcode for $name { fn id(&self) -> u8 { match self { $(Self::$var => $val,)* } } } } } macro_rules! pw_object_base { ($name:ident, $if:expr, $events:ident; $($event:ident => $method:ident,)*) => { impl crate::pipewire::pw_object::PwObjectBase for $name { fn data(&self) -> &crate::pipewire::pw_object::PwObjectData { &self.data } fn interface(&self) -> &str { $if } fn handle_msg(self: std::rc::Rc, opcode: u8, parser: crate::pipewire::pw_parser::PwParser<'_>) -> Result<(), crate::pipewire::pw_object::PwObjectError> { match $events::from_id(opcode) { None => Err(crate::pipewire::pw_object::PwObjectError { interface: $if, source: crate::pipewire::pw_object::PwObjectErrorType::UnknownEvent(opcode), }), Some(m) => { let (res, method) = match m { $( $events::$event => (self.$method(parser), stringify!($event)), )* }; match res { Ok(_) => Ok(()), Err(source) => Err(crate::pipewire::pw_object::PwObjectError { interface: $if, source: crate::pipewire::pw_object::PwObjectErrorType::EventError { method, source: Box::new(source), }, }) } }, } } fn event_name(&self, opcode: u8) -> Option<&'static str> { $events::from_id(opcode).map(|o| o.name()) } } } } macro_rules! ei_id { ($name:ident) => { #[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] pub struct $name(u64); #[expect(dead_code)] impl $name { pub const NONE: Self = $name(0); pub const fn from_raw(raw: u64) -> Self { Self(raw) } pub fn raw(self) -> u64 { self.0 } pub fn is_some(self) -> bool { self.0 != 0 } pub fn is_none(self) -> bool { self.0 == 0 } } impl From for $name { fn from(f: crate::ei::ei_object::EiObjectId) -> Self { Self(f.raw()) } } impl From<$name> for crate::ei::ei_object::EiObjectId { fn from(f: $name) -> Self { crate::ei::ei_object::EiObjectId::from_raw(f.0) } } impl std::fmt::Display for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } impl std::fmt::LowerHex for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::LowerHex::fmt(&self.0, f) } } }; } macro_rules! ei_object_base { ($self:ident = $oname:ident; version = $version:expr;) => { impl crate::ei::ei_object::EiObjectBase for $oname { fn id(&$self) -> crate::ei::ei_object::EiObjectId { $self.id.into() } fn version(&$self) -> crate::ei::ei_object::EiVersion { $version } fn client(&$self) -> &crate::ei::ei_client::EiClient { &$self.client } fn handle_request( $self: std::rc::Rc, client: &crate::ei::ei_client::EiClient, request: u32, parser: crate::utils::buffd::EiMsgParser<'_, '_>, ) -> Result<(), crate::ei::ei_client::EiClientError> { $self.handle_request_impl(client, request, parser) } fn interface(&$self) -> crate::ei::ei_object::EiInterface { crate::wire_ei::$oname } } }; }