#![allow(clippy::too_many_arguments)]
#[allow(unused_imports)]
use std::borrow::Cow;
use std::convert::TryFrom;
#[allow(unused_imports)]
use std::convert::TryInto;
use std::io::IoSlice;
#[allow(unused_imports)]
use crate::utils::{RawFdContainer, pretty_print_bitmask, pretty_print_enum};
#[allow(unused_imports)]
use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd, TryIntoUSize};
use crate::connection::{BufWithFds, PiecewiseBuf, RequestConnection};
#[allow(unused_imports)]
use crate::connection::Connection as X11Connection;
#[allow(unused_imports)]
use crate::cookie::{Cookie, CookieWithFds, VoidCookie};
use crate::errors::{ConnectionError, ParseError};
#[allow(unused_imports)]
use crate::errors::ReplyOrIdError;
pub const X11_EXTENSION_NAME: &str = "XEVIE";
pub const X11_XML_VERSION: (u32, u32) = (1, 0);
fn major_opcode<Conn: RequestConnection + ?Sized>(conn: &Conn) -> Result<u8, ConnectionError> {
let info = conn.extension_information(X11_EXTENSION_NAME)?;
let info = info.ok_or(ConnectionError::UnsupportedExtension)?;
Ok(info.major_opcode)
}
pub const QUERY_VERSION_REQUEST: u8 = 0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct QueryVersionRequest {
pub client_major_version: u16,
pub client_minor_version: u16,
}
impl QueryVersionRequest {
fn serialize(self, major_opcode: u8) -> BufWithFds<PiecewiseBuf<'static>> {
let length_so_far = 0;
let client_major_version_bytes = self.client_major_version.serialize();
let client_minor_version_bytes = self.client_minor_version.serialize();
let mut request0 = vec![
major_opcode,
QUERY_VERSION_REQUEST,
0,
0,
client_major_version_bytes[0],
client_major_version_bytes[1],
client_minor_version_bytes[0],
client_minor_version_bytes[1],
];
let length_so_far = length_so_far + request0.len();
assert_eq!(length_so_far % 4, 0);
let length = u16::try_from(length_so_far / 4).unwrap_or(0);
request0[2..4].copy_from_slice(&length.to_ne_bytes());
(vec![request0.into()], vec![])
}
pub fn send<Conn>(self, conn: &Conn) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let (bytes, fds) = self.serialize(major_opcode(conn)?);
let slices = bytes.iter().map(|b| IoSlice::new(&*b)).collect::<Vec<_>>();
conn.send_request_with_reply(&slices, fds)
}
pub fn try_parse_request(header: RequestHeader, value: &[u8]) -> Result<Self, ParseError> {
if header.minor_opcode != QUERY_VERSION_REQUEST {
return Err(ParseError::InvalidValue);
}
let (client_major_version, remaining) = u16::try_parse(value)?;
let (client_minor_version, remaining) = u16::try_parse(remaining)?;
let _ = remaining;
Ok(QueryVersionRequest {
client_major_version,
client_minor_version,
})
}
}
impl Request for QueryVersionRequest {
type Reply = QueryVersionReply;
}
pub fn query_version<Conn>(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Conn, QueryVersionReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = QueryVersionRequest {
client_major_version,
client_minor_version,
};
request0.send(conn)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct QueryVersionReply {
pub sequence: u16,
pub length: u32,
pub server_major_version: u16,
pub server_minor_version: u16,
}
impl TryParse for QueryVersionReply {
fn try_parse(initial_value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = initial_value;
let (response_type, remaining) = u8::try_parse(remaining)?;
let remaining = remaining.get(1..).ok_or(ParseError::InsufficientData)?;
let (sequence, remaining) = u16::try_parse(remaining)?;
let (length, remaining) = u32::try_parse(remaining)?;
let (server_major_version, remaining) = u16::try_parse(remaining)?;
let (server_minor_version, remaining) = u16::try_parse(remaining)?;
let remaining = remaining.get(20..).ok_or(ParseError::InsufficientData)?;
if response_type != 1 {
return Err(ParseError::InvalidValue);
}
let result = QueryVersionReply { sequence, length, server_major_version, server_minor_version };
let _ = remaining;
let remaining = initial_value.get(32 + length as usize * 4..)
.ok_or(ParseError::InsufficientData)?;
Ok((result, remaining))
}
}
pub const START_REQUEST: u8 = 1;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StartRequest {
pub screen: u32,
}
impl StartRequest {
fn serialize(self, major_opcode: u8) -> BufWithFds<PiecewiseBuf<'static>> {
let length_so_far = 0;
let screen_bytes = self.screen.serialize();
let mut request0 = vec![
major_opcode,
START_REQUEST,
0,
0,
screen_bytes[0],
screen_bytes[1],
screen_bytes[2],
screen_bytes[3],
];
let length_so_far = length_so_far + request0.len();
assert_eq!(length_so_far % 4, 0);
let length = u16::try_from(length_so_far / 4).unwrap_or(0);
request0[2..4].copy_from_slice(&length.to_ne_bytes());
(vec![request0.into()], vec![])
}
pub fn send<Conn>(self, conn: &Conn) -> Result<Cookie<'_, Conn, StartReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let (bytes, fds) = self.serialize(major_opcode(conn)?);
let slices = bytes.iter().map(|b| IoSlice::new(&*b)).collect::<Vec<_>>();
conn.send_request_with_reply(&slices, fds)
}
pub fn try_parse_request(header: RequestHeader, value: &[u8]) -> Result<Self, ParseError> {
if header.minor_opcode != START_REQUEST {
return Err(ParseError::InvalidValue);
}
let (screen, remaining) = u32::try_parse(value)?;
let _ = remaining;
Ok(StartRequest {
screen,
})
}
}
impl Request for StartRequest {
type Reply = StartReply;
}
pub fn start<Conn>(conn: &Conn, screen: u32) -> Result<Cookie<'_, Conn, StartReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = StartRequest {
screen,
};
request0.send(conn)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StartReply {
pub sequence: u16,
pub length: u32,
}
impl TryParse for StartReply {
fn try_parse(initial_value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = initial_value;
let (response_type, remaining) = u8::try_parse(remaining)?;
let remaining = remaining.get(1..).ok_or(ParseError::InsufficientData)?;
let (sequence, remaining) = u16::try_parse(remaining)?;
let (length, remaining) = u32::try_parse(remaining)?;
let remaining = remaining.get(24..).ok_or(ParseError::InsufficientData)?;
if response_type != 1 {
return Err(ParseError::InvalidValue);
}
let result = StartReply { sequence, length };
let _ = remaining;
let remaining = initial_value.get(32 + length as usize * 4..)
.ok_or(ParseError::InsufficientData)?;
Ok((result, remaining))
}
}
pub const END_REQUEST: u8 = 2;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EndRequest {
pub cmap: u32,
}
impl EndRequest {
fn serialize(self, major_opcode: u8) -> BufWithFds<PiecewiseBuf<'static>> {
let length_so_far = 0;
let cmap_bytes = self.cmap.serialize();
let mut request0 = vec![
major_opcode,
END_REQUEST,
0,
0,
cmap_bytes[0],
cmap_bytes[1],
cmap_bytes[2],
cmap_bytes[3],
];
let length_so_far = length_so_far + request0.len();
assert_eq!(length_so_far % 4, 0);
let length = u16::try_from(length_so_far / 4).unwrap_or(0);
request0[2..4].copy_from_slice(&length.to_ne_bytes());
(vec![request0.into()], vec![])
}
pub fn send<Conn>(self, conn: &Conn) -> Result<Cookie<'_, Conn, EndReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let (bytes, fds) = self.serialize(major_opcode(conn)?);
let slices = bytes.iter().map(|b| IoSlice::new(&*b)).collect::<Vec<_>>();
conn.send_request_with_reply(&slices, fds)
}
pub fn try_parse_request(header: RequestHeader, value: &[u8]) -> Result<Self, ParseError> {
if header.minor_opcode != END_REQUEST {
return Err(ParseError::InvalidValue);
}
let (cmap, remaining) = u32::try_parse(value)?;
let _ = remaining;
Ok(EndRequest {
cmap,
})
}
}
impl Request for EndRequest {
type Reply = EndReply;
}
pub fn end<Conn>(conn: &Conn, cmap: u32) -> Result<Cookie<'_, Conn, EndReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = EndRequest {
cmap,
};
request0.send(conn)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EndReply {
pub sequence: u16,
pub length: u32,
}
impl TryParse for EndReply {
fn try_parse(initial_value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = initial_value;
let (response_type, remaining) = u8::try_parse(remaining)?;
let remaining = remaining.get(1..).ok_or(ParseError::InsufficientData)?;
let (sequence, remaining) = u16::try_parse(remaining)?;
let (length, remaining) = u32::try_parse(remaining)?;
let remaining = remaining.get(24..).ok_or(ParseError::InsufficientData)?;
if response_type != 1 {
return Err(ParseError::InvalidValue);
}
let result = EndReply { sequence, length };
let _ = remaining;
let remaining = initial_value.get(32 + length as usize * 4..)
.ok_or(ParseError::InsufficientData)?;
Ok((result, remaining))
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Datatype(bool);
impl Datatype {
pub const UNMODIFIED: Self = Self(false);
pub const MODIFIED: Self = Self(true);
}
impl From<Datatype> for bool {
#[inline]
fn from(input: Datatype) -> Self {
input.0
}
}
impl From<Datatype> for Option<bool> {
#[inline]
fn from(input: Datatype) -> Self {
Some(input.0)
}
}
impl From<Datatype> for u8 {
#[inline]
fn from(input: Datatype) -> Self {
u8::from(input.0)
}
}
impl From<Datatype> for Option<u8> {
#[inline]
fn from(input: Datatype) -> Self {
Some(u8::from(input.0))
}
}
impl From<Datatype> for u16 {
#[inline]
fn from(input: Datatype) -> Self {
u16::from(input.0)
}
}
impl From<Datatype> for Option<u16> {
#[inline]
fn from(input: Datatype) -> Self {
Some(u16::from(input.0))
}
}
impl From<Datatype> for u32 {
#[inline]
fn from(input: Datatype) -> Self {
u32::from(input.0)
}
}
impl From<Datatype> for Option<u32> {
#[inline]
fn from(input: Datatype) -> Self {
Some(u32::from(input.0))
}
}
impl From<bool> for Datatype {
#[inline]
fn from(value: bool) -> Self {
Self(value)
}
}
impl std::fmt::Debug for Datatype {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let variants = [
(Self::UNMODIFIED.0.into(), "UNMODIFIED", "Unmodified"),
(Self::MODIFIED.0.into(), "MODIFIED", "Modified"),
];
pretty_print_enum(fmt, self.0.into(), &variants)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Event {
}
impl TryParse for Event {
fn try_parse(remaining: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = remaining.get(32..).ok_or(ParseError::InsufficientData)?;
let result = Event { };
Ok((result, remaining))
}
}
impl Serialize for Event {
type Bytes = [u8; 32];
fn serialize(&self) -> [u8; 32] {
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
]
}
fn serialize_into(&self, bytes: &mut Vec<u8>) {
bytes.reserve(32);
bytes.extend_from_slice(&[0; 32]);
}
}
pub const SEND_REQUEST: u8 = 3;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SendRequest {
pub event: Event,
pub data_type: u32,
}
impl SendRequest {
fn serialize(self, major_opcode: u8) -> BufWithFds<PiecewiseBuf<'static>> {
let length_so_far = 0;
let event_bytes = self.event.serialize();
let data_type_bytes = self.data_type.serialize();
let mut request0 = vec![
major_opcode,
SEND_REQUEST,
0,
0,
event_bytes[0],
event_bytes[1],
event_bytes[2],
event_bytes[3],
event_bytes[4],
event_bytes[5],
event_bytes[6],
event_bytes[7],
event_bytes[8],
event_bytes[9],
event_bytes[10],
event_bytes[11],
event_bytes[12],
event_bytes[13],
event_bytes[14],
event_bytes[15],
event_bytes[16],
event_bytes[17],
event_bytes[18],
event_bytes[19],
event_bytes[20],
event_bytes[21],
event_bytes[22],
event_bytes[23],
event_bytes[24],
event_bytes[25],
event_bytes[26],
event_bytes[27],
event_bytes[28],
event_bytes[29],
event_bytes[30],
event_bytes[31],
data_type_bytes[0],
data_type_bytes[1],
data_type_bytes[2],
data_type_bytes[3],
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
];
let length_so_far = length_so_far + request0.len();
assert_eq!(length_so_far % 4, 0);
let length = u16::try_from(length_so_far / 4).unwrap_or(0);
request0[2..4].copy_from_slice(&length.to_ne_bytes());
(vec![request0.into()], vec![])
}
pub fn send<Conn>(self, conn: &Conn) -> Result<Cookie<'_, Conn, SendReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let (bytes, fds) = self.serialize(major_opcode(conn)?);
let slices = bytes.iter().map(|b| IoSlice::new(&*b)).collect::<Vec<_>>();
conn.send_request_with_reply(&slices, fds)
}
pub fn try_parse_request(header: RequestHeader, value: &[u8]) -> Result<Self, ParseError> {
if header.minor_opcode != SEND_REQUEST {
return Err(ParseError::InvalidValue);
}
let (event, remaining) = Event::try_parse(value)?;
let (data_type, remaining) = u32::try_parse(remaining)?;
let remaining = remaining.get(64..).ok_or(ParseError::InsufficientData)?;
let _ = remaining;
Ok(SendRequest {
event,
data_type,
})
}
}
impl Request for SendRequest {
type Reply = SendReply;
}
pub fn send<Conn>(conn: &Conn, event: Event, data_type: u32) -> Result<Cookie<'_, Conn, SendReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SendRequest {
event,
data_type,
};
request0.send(conn)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SendReply {
pub sequence: u16,
pub length: u32,
}
impl TryParse for SendReply {
fn try_parse(initial_value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = initial_value;
let (response_type, remaining) = u8::try_parse(remaining)?;
let remaining = remaining.get(1..).ok_or(ParseError::InsufficientData)?;
let (sequence, remaining) = u16::try_parse(remaining)?;
let (length, remaining) = u32::try_parse(remaining)?;
let remaining = remaining.get(24..).ok_or(ParseError::InsufficientData)?;
if response_type != 1 {
return Err(ParseError::InvalidValue);
}
let result = SendReply { sequence, length };
let _ = remaining;
let remaining = initial_value.get(32 + length as usize * 4..)
.ok_or(ParseError::InsufficientData)?;
Ok((result, remaining))
}
}
pub const SELECT_INPUT_REQUEST: u8 = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SelectInputRequest {
pub event_mask: u32,
}
impl SelectInputRequest {
fn serialize(self, major_opcode: u8) -> BufWithFds<PiecewiseBuf<'static>> {
let length_so_far = 0;
let event_mask_bytes = self.event_mask.serialize();
let mut request0 = vec![
major_opcode,
SELECT_INPUT_REQUEST,
0,
0,
event_mask_bytes[0],
event_mask_bytes[1],
event_mask_bytes[2],
event_mask_bytes[3],
];
let length_so_far = length_so_far + request0.len();
assert_eq!(length_so_far % 4, 0);
let length = u16::try_from(length_so_far / 4).unwrap_or(0);
request0[2..4].copy_from_slice(&length.to_ne_bytes());
(vec![request0.into()], vec![])
}
pub fn send<Conn>(self, conn: &Conn) -> Result<Cookie<'_, Conn, SelectInputReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let (bytes, fds) = self.serialize(major_opcode(conn)?);
let slices = bytes.iter().map(|b| IoSlice::new(&*b)).collect::<Vec<_>>();
conn.send_request_with_reply(&slices, fds)
}
pub fn try_parse_request(header: RequestHeader, value: &[u8]) -> Result<Self, ParseError> {
if header.minor_opcode != SELECT_INPUT_REQUEST {
return Err(ParseError::InvalidValue);
}
let (event_mask, remaining) = u32::try_parse(value)?;
let _ = remaining;
Ok(SelectInputRequest {
event_mask,
})
}
}
impl Request for SelectInputRequest {
type Reply = SelectInputReply;
}
pub fn select_input<Conn>(conn: &Conn, event_mask: u32) -> Result<Cookie<'_, Conn, SelectInputReply>, ConnectionError>
where
Conn: RequestConnection + ?Sized,
{
let request0 = SelectInputRequest {
event_mask,
};
request0.send(conn)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SelectInputReply {
pub sequence: u16,
pub length: u32,
}
impl TryParse for SelectInputReply {
fn try_parse(initial_value: &[u8]) -> Result<(Self, &[u8]), ParseError> {
let remaining = initial_value;
let (response_type, remaining) = u8::try_parse(remaining)?;
let remaining = remaining.get(1..).ok_or(ParseError::InsufficientData)?;
let (sequence, remaining) = u16::try_parse(remaining)?;
let (length, remaining) = u32::try_parse(remaining)?;
let remaining = remaining.get(24..).ok_or(ParseError::InsufficientData)?;
if response_type != 1 {
return Err(ParseError::InvalidValue);
}
let result = SelectInputReply { sequence, length };
let _ = remaining;
let remaining = initial_value.get(32 + length as usize * 4..)
.ok_or(ParseError::InsufficientData)?;
Ok((result, remaining))
}
}
pub trait ConnectionExt: RequestConnection {
fn xevie_query_version(&self, client_major_version: u16, client_minor_version: u16) -> Result<Cookie<'_, Self, QueryVersionReply>, ConnectionError>
{
query_version(self, client_major_version, client_minor_version)
}
fn xevie_start(&self, screen: u32) -> Result<Cookie<'_, Self, StartReply>, ConnectionError>
{
start(self, screen)
}
fn xevie_end(&self, cmap: u32) -> Result<Cookie<'_, Self, EndReply>, ConnectionError>
{
end(self, cmap)
}
fn xevie_send(&self, event: Event, data_type: u32) -> Result<Cookie<'_, Self, SendReply>, ConnectionError>
{
send(self, event, data_type)
}
fn xevie_select_input(&self, event_mask: u32) -> Result<Cookie<'_, Self, SelectInputReply>, ConnectionError>
{
select_input(self, event_mask)
}
}
impl<C: RequestConnection + ?Sized> ConnectionExt for C {}