blob: 80b358f9861dce5ef7e7bdbb99681b0796688a50 [file] [log] [blame] [edit]
//! Common definitions for wayland
//!
//! This crate hosts common type and traits used to represent wayland messages
//! and routines in the `wayland-client` and `wayland-server` crates.
//!
//! This notably includes the `Interface` trait, which can exhaustively describe
//! any wayland interface. Its implementations are intended to be generated by the
//! `wayland-scanner` crate.
//!
//! The principal user-facing definition provided by this crate is the `Implementation`
//! trait, which as a user of `wayland-client` or `wayland-server` you will be using
//! to define objects able to handle the messages your program receives. Note that
//! this trait is auto-implemented for closures with appropriate signature, for
//! convenience.
#![warn(missing_docs, missing_debug_implementations)]
#[macro_use]
extern crate nix;
use std::os::raw::c_void;
use wayland_sys::common as syscom;
pub mod debug;
pub mod filter;
pub mod map;
pub mod socket;
pub mod user_data;
pub mod wire;
pub use smallvec::smallvec;
/// A group of messages
///
/// This represents a group of message that can be serialized on the protocol wire.
/// Typically the set of events or requests of a single interface.
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait MessageGroup: Sized {
/// Wire representation of this MessageGroup
const MESSAGES: &'static [wire::MessageDesc];
/// The wrapper type for ObjectMap allowing the mapping of Object and
/// NewId arguments to the object map during parsing.
type Map;
/// The opcode of this message
fn opcode(&self) -> u16;
/// Whether this message is a destructor
///
/// If it is, once send or receive the associated object cannot be used any more.
fn is_destructor(&self) -> bool;
/// The minimal object version for which this message exists
fn since(&self) -> u32;
/// Retrieve the child `Object` associated with this message if any
fn child<Meta: self::map::ObjectMetadata>(
opcode: u16,
version: u32,
meta: &Meta,
) -> Option<crate::map::Object<Meta>>;
/// Construct a message from its raw representation
// -- The lint is allowed because fixing it would be a breaking change --
#[allow(clippy::result_unit_err)]
fn from_raw(msg: wire::Message, map: &mut Self::Map) -> Result<Self, ()>;
/// Turn this message into its raw representation
fn into_raw(self, send_id: u32) -> wire::Message;
/// Construct a message of this group from its C representation
///
/// # Safety
///
/// The pointers provided to this function must all be valid pointers from
/// `libwayland-client`
// -- The lint is allowed because fixing it would be a breaking change --
#[allow(clippy::result_unit_err)]
unsafe fn from_raw_c(
obj: *mut c_void,
opcode: u32,
args: *const syscom::wl_argument,
) -> Result<Self, ()>;
/// Build a C representation of this message
///
/// It can only be accessed from the provided closure, and this consumes
/// the message.
// -- The lint is allowed because fixing it would be a breaking change --
#[allow(clippy::wrong_self_convention)]
fn as_raw_c_in<F, T>(self, f: F) -> T
where
F: FnOnce(u32, &mut [syscom::wl_argument]) -> T;
}
/// The description of a wayland interface
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait Interface: 'static {
/// Set of requests associated to this interface
///
/// Requests are messages from the client to the server
type Request: MessageGroup + 'static;
/// Set of events associated to this interface
///
/// Events are messages from the server to the client
type Event: MessageGroup + 'static;
/// Name of this interface
const NAME: &'static str;
/// Maximum supported version of this interface
///
/// This is the maximum version supported by the protocol specification currently
/// used by this library, and should not be used as-is in your code, as a version
/// change can subtly change the behavior of some objects.
///
/// Server are supposed to be able to handle all versions from 1 to the one they
/// advertise through the registry, and clients can choose any version among the
/// ones the server supports.
const VERSION: u32;
/// Pointer to the C representation of this interface
fn c_interface() -> *const syscom::wl_interface;
}
/// An empty enum representing a MessageGroup with no messages
#[derive(Debug)]
pub enum NoMessage {}
#[cfg(not(tarpaulin_include))]
impl MessageGroup for NoMessage {
const MESSAGES: &'static [wire::MessageDesc] = &[];
type Map = ();
fn is_destructor(&self) -> bool {
match *self {}
}
fn opcode(&self) -> u16 {
match *self {}
}
fn since(&self) -> u32 {
match *self {}
}
fn child<M: self::map::ObjectMetadata>(_: u16, _: u32, _: &M) -> Option<crate::map::Object<M>> {
None
}
fn from_raw(_: wire::Message, _: &mut ()) -> Result<Self, ()> {
Err(())
}
fn into_raw(self, _: u32) -> wire::Message {
match self {}
}
unsafe fn from_raw_c(
_obj: *mut c_void,
_opcode: u32,
_args: *const syscom::wl_argument,
) -> Result<Self, ()> {
Err(())
}
fn as_raw_c_in<F, T>(self, _f: F) -> T
where
F: FnOnce(u32, &mut [syscom::wl_argument]) -> T,
{
match self {}
}
}
/// Stores a value in a threadafe container that
/// only lets you access it from its owning thread
///
/// If the ThreadGuard is dropped from the wrong thread,
/// the underlying value will be leaked.
#[derive(Debug)]
pub struct ThreadGuard<T: ?Sized> {
thread: std::thread::ThreadId,
val: std::mem::ManuallyDrop<T>,
}
impl<T> ThreadGuard<T> {
/// Create a new ThreadGuard wrapper
pub fn new(val: T) -> ThreadGuard<T> {
ThreadGuard { val: std::mem::ManuallyDrop::new(val), thread: std::thread::current().id() }
}
}
impl<T: ?Sized> ThreadGuard<T> {
/// Access the underlying value
///
/// Panics if done on the wrong thread
pub fn get(&self) -> &T {
self.try_get().expect("Attempted to access a ThreadGuard contents from the wrong thread.")
}
/// Mutably access the underlying value
///
/// Panics if done on the wrong thread
pub fn get_mut(&mut self) -> &mut T {
self.try_get_mut()
.expect("Attempted to access a ThreadGuard contents from the wrong thread.")
}
/// Try to access the underlying value
///
/// Returns `None` if done on the wrong thread
pub fn try_get(&self) -> Option<&T> {
if self.thread == ::std::thread::current().id() {
Some(&self.val)
} else {
None
}
}
/// Try to mutably access the underlying value
///
/// Returns `None` if done on the wrong thread
pub fn try_get_mut(&mut self) -> Option<&mut T> {
if self.thread == ::std::thread::current().id() {
Some(&mut self.val)
} else {
None
}
}
}
impl<T: ?Sized> Drop for ThreadGuard<T> {
fn drop(&mut self) {
// We can only actually perform the drop if we are on the right thread
// otherwise it may be racy, so we just leak the value
if self.thread == ::std::thread::current().id() {
unsafe { std::mem::ManuallyDrop::drop(&mut self.val) }
}
}
}
unsafe impl<T: ?Sized> Send for ThreadGuard<T> {}
unsafe impl<T: ?Sized> Sync for ThreadGuard<T> {}