1
0
Fork 0
forked from wry/wry

autocommit 2022-03-22 23:24:17 CET

This commit is contained in:
Julian Orth 2022-03-22 23:24:17 +01:00
parent 18806a38fb
commit 2ff60ff817
36 changed files with 4934 additions and 237 deletions

103
src/xcon/consts.rs Normal file
View file

@ -0,0 +1,103 @@
#![allow(dead_code)]
pub const XGE_EVENT: u8 = 35;
pub const INPUT_DEVICE_ALL: u16 = 0;
pub const INPUT_DEVICE_ALL_MASTER: u16 = 1;
pub const WINDOW_CLASS_INPUT_OUTPUT: u16 = 1;
pub const PROP_MODE_REPLACE: u8 = 0;
pub const ATOM_WM_CLASS: u32 = 67;
pub const ATOM_STRING: u32 = 31;
pub const EVENT_MASK_NO_EVENT: u32 = 0;
pub const EVENT_MASK_KEY_PRESS: u32 = 1;
pub const EVENT_MASK_KEY_RELEASE: u32 = 2;
pub const EVENT_MASK_BUTTON_PRESS: u32 = 4;
pub const EVENT_MASK_BUTTON_RELEASE: u32 = 8;
pub const EVENT_MASK_ENTER_WINDOW: u32 = 16;
pub const EVENT_MASK_LEAVE_WINDOW: u32 = 32;
pub const EVENT_MASK_POINTER_MOTION: u32 = 64;
pub const EVENT_MASK_POINTER_MOTION_HINT: u32 = 128;
pub const EVENT_MASK_BUTTON_1_MOTION: u32 = 256;
pub const EVENT_MASK_BUTTON_2_MOTION: u32 = 512;
pub const EVENT_MASK_BUTTON_3_MOTION: u32 = 1024;
pub const EVENT_MASK_BUTTON_4_MOTION: u32 = 2048;
pub const EVENT_MASK_BUTTON_5_MOTION: u32 = 4096;
pub const EVENT_MASK_BUTTON_MOTION: u32 = 8192;
pub const EVENT_MASK_KEYMAP_STATE: u32 = 16384;
pub const EVENT_MASK_EXPOSURE: u32 = 32768;
pub const EVENT_MASK_VISIBILITY_CHANGE: u32 = 65536;
pub const EVENT_MASK_STRUCTURE_NOTIFY: u32 = 131072;
pub const EVENT_MASK_RESIZE_REDIRECT: u32 = 262144;
pub const EVENT_MASK_SUBSTRUCTURE_NOTIFY: u32 = 524288;
pub const EVENT_MASK_SUBSTRUCTURE_REDIRECT: u32 = 1048576;
pub const EVENT_MASK_FOCUS_CHANGE: u32 = 2097152;
pub const EVENT_MASK_PROPERTY_CHANGE: u32 = 4194304;
pub const EVENT_MASK_COLOR_MAP_CHANGE: u32 = 8388608;
pub const EVENT_MASK_OWNER_GRAB_BUTTON: u32 = 16777216;
pub const XI_EVENT_MASK_DEVICE_CHANGED: u32 = 2;
pub const XI_EVENT_MASK_KEY_PRESS: u32 = 4;
pub const XI_EVENT_MASK_KEY_RELEASE: u32 = 8;
pub const XI_EVENT_MASK_BUTTON_PRESS: u32 = 16;
pub const XI_EVENT_MASK_BUTTON_RELEASE: u32 = 32;
pub const XI_EVENT_MASK_MOTION: u32 = 64;
pub const XI_EVENT_MASK_ENTER: u32 = 128;
pub const XI_EVENT_MASK_LEAVE: u32 = 256;
pub const XI_EVENT_MASK_FOCUS_IN: u32 = 512;
pub const XI_EVENT_MASK_FOCUS_OUT: u32 = 1024;
pub const XI_EVENT_MASK_HIERARCHY: u32 = 2048;
pub const XI_EVENT_MASK_PROPERTY: u32 = 4096;
pub const XI_EVENT_MASK_RAW_KEY_PRESS: u32 = 8192;
pub const XI_EVENT_MASK_RAW_KEY_RELEASE: u32 = 16384;
pub const XI_EVENT_MASK_RAW_BUTTON_PRESS: u32 = 32768;
pub const XI_EVENT_MASK_RAW_BUTTON_RELEASE: u32 = 65536;
pub const XI_EVENT_MASK_RAW_MOTION: u32 = 131072;
pub const XI_EVENT_MASK_TOUCH_BEGIN: u32 = 262144;
pub const XI_EVENT_MASK_TOUCH_UPDATE: u32 = 524288;
pub const XI_EVENT_MASK_TOUCH_END: u32 = 1048576;
pub const XI_EVENT_MASK_TOUCH_OWNERSHIP: u32 = 2097152;
pub const XI_EVENT_MASK_RAW_TOUCH_BEGIN: u32 = 4194304;
pub const XI_EVENT_MASK_RAW_TOUCH_UPDATE: u32 = 8388608;
pub const XI_EVENT_MASK_RAW_TOUCH_END: u32 = 16777216;
pub const XI_EVENT_MASK_BARRIER_HIT: u32 = 33554432;
pub const XI_EVENT_MASK_BARRIER_LEAVE: u32 = 67108864;
pub const PRESENT_EVENT_MASK_NO_EVENT: u32 = 0;
pub const PRESENT_EVENT_MASK_CONFIGURE_NOTIFY: u32 = 1;
pub const PRESENT_EVENT_MASK_COMPLETE_NOTIFY: u32 = 2;
pub const PRESENT_EVENT_MASK_IDLE_NOTIFY: u32 = 4;
pub const PRESENT_EVENT_MASK_REDIRECT_NOTIFY: u32 = 8;
pub const INPUT_DEVICE_TYPE_MASTER_POINTER: u16 = 1;
pub const INPUT_DEVICE_TYPE_MASTER_KEYBOARD: u16 = 2;
pub const INPUT_DEVICE_TYPE_SLAVE_POINTER: u16 = 3;
pub const INPUT_DEVICE_TYPE_SLAVE_KEYBOARD: u16 = 4;
pub const INPUT_DEVICE_TYPE_FLOATING_SLAVE: u16 = 5;
pub const XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT: u32 = 1;
pub const XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE: u32 = 2;
pub const XKB_PER_CLIENT_FLAG_AUTO_RESET_CONTROLS: u32 = 4;
pub const XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED: u32 = 8;
pub const XKB_PER_CLIENT_FLAG_SEND_EVENT_USES_XKB_STATE: u32 = 16;
pub const INPUT_HIERARCHY_MASK_MASTER_ADDED: u32 = 1;
pub const INPUT_HIERARCHY_MASK_MASTER_REMOVED: u32 = 2;
pub const INPUT_HIERARCHY_MASK_SLAVE_ADDED: u32 = 4;
pub const INPUT_HIERARCHY_MASK_SLAVE_REMOVED: u32 = 8;
pub const INPUT_HIERARCHY_MASK_SLAVE_ATTACHED: u32 = 16;
pub const INPUT_HIERARCHY_MASK_SLAVE_DETACHED: u32 = 32;
pub const INPUT_HIERARCHY_MASK_DEVICE_ENABLED: u32 = 64;
pub const INPUT_HIERARCHY_MASK_DEVICE_DISABLED: u32 = 128;
pub const GRAB_MODE_SYNC: u8 = 0;
pub const GRAB_MODE_ASYNC: u8 = 1;
pub const GRAB_STATUS_SUCCESS: u8 = 0;
pub const GRAB_STATUS_ALREADY_GRABBED: u8 = 1;
pub const GRAB_STATUS_INVALID_TIME: u8 = 2;
pub const GRAB_STATUS_NOT_VIEWABLE: u8 = 3;
pub const GRAB_STATUS_FROZEN: u8 = 4;

62
src/xcon/formatter.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::xcon::Message;
use std::rc::Rc;
use uapi::{AssertPacked, OwnedFd, Packed};
pub struct Formatter<'a> {
fds: &'a mut Vec<Rc<OwnedFd>>,
buf: &'a mut Vec<u8>,
ext_opcode: u8,
}
impl<'a> Formatter<'a> {
pub fn new(fds: &'a mut Vec<Rc<OwnedFd>>, buf: &'a mut Vec<u8>, ext_opcode: u8) -> Self {
Self {
fds,
buf,
ext_opcode,
}
}
pub fn ext_opcode(&self) -> u8 {
self.ext_opcode
}
pub fn pad(&mut self, pad: usize) {
static BUF: [u8; 8] = [0; 8];
self.buf.extend_from_slice(&BUF[..pad]);
}
pub fn align(&mut self, alignment: usize) {
static BUF: [u8; 8] = [0; 8];
let len = self.buf.len().wrapping_neg() & (alignment - 1);
self.buf.extend_from_slice(&BUF[..len]);
}
pub fn write_packed<T: Packed + ?Sized>(&mut self, t: &T) {
self.buf.extend_from_slice(uapi::as_bytes(t));
}
pub fn write_list<'b, T: Message<'b>>(&mut self, t: &[T]) {
if T::IS_POD {
self.buf
.extend_from_slice(uapi::as_bytes(unsafe { AssertPacked::new(t) }));
} else {
for t in t {
t.serialize(self);
}
}
}
pub fn write_bytes(&mut self, b: &[u8]) {
self.buf.extend_from_slice(b);
}
pub fn write_request_length(&mut self) {
let len: u16 = (self.buf.len() / 4) as u16;
self.buf[2..4].copy_from_slice(&len.to_ne_bytes());
}
pub fn add_fd(&mut self, fd: &Rc<OwnedFd>) {
self.fds.push(fd.clone());
}
}

222
src/xcon/incoming.rs Normal file
View file

@ -0,0 +1,222 @@
use crate::utils::bufio::BufIoIncoming;
use crate::xcon::consts::XGE_EVENT;
use crate::xcon::{Event, ExtensionData, ExtensionIdRange, Parser, XconData, XconError};
use crate::ErrorFmt;
use std::mem;
use std::rc::Rc;
pub(super) async fn handle_incoming(xorg: Rc<XconData>, incoming: BufIoIncoming) {
let mut incoming = Incoming {
incoming,
socket: xorg,
ed: None,
};
incoming.run().await;
}
pub struct Incoming {
socket: Rc<XconData>,
incoming: BufIoIncoming,
ed: Option<Rc<ExtensionData>>,
}
impl Incoming {
async fn run(&mut self) {
loop {
if self.socket.dead.get() {
return;
}
if let Err(e) = self.handle_msg().await {
log::error!("Could not process an incoming message: {}", ErrorFmt(e));
self.socket.kill();
return;
}
}
}
async fn handle_msg(&mut self) -> Result<(), XconError> {
const MAX_LENGTH_UNITS: usize = 0x4000 / 4;
const MIN_MSG_SIZE: usize = 32;
let mut msg_buf = self.socket.bufio.buf();
self.incoming
.fill_msg_buf(MIN_MSG_SIZE, &mut msg_buf)
.await?;
let mut serial = 0;
const KEYMAP_NOTIFY: u8 = 11;
let mut reply_handlers = self.socket.reply_handlers.borrow_mut();
if msg_buf[0] & 0x7f != KEYMAP_NOTIFY {
let serial_16 = u16::from_ne_bytes([msg_buf[2], msg_buf[3]]);
serial = (self.socket.last_recv_serial.get() & !0xffff) | (serial_16 as u64);
if serial < self.socket.last_recv_serial.get() {
serial += 0x10000;
}
self.socket.last_recv_serial.set(serial);
while let Some(first) = reply_handlers.front() {
if first.serial() < serial {
let handler = reply_handlers.pop_front().unwrap();
drop(reply_handlers);
handler.handle_noreply(&self.socket.bufio)?;
reply_handlers = self.socket.reply_handlers.borrow_mut();
} else {
break;
}
}
}
if self.ed.is_none() {
self.ed = self.socket.extensions.get();
}
match msg_buf[0] & 0x7f {
0 => 'handle_error: {
let code = msg_buf[1];
let (ext, code) = if code < 128 {
(None, code)
} else if let Some(ed) = &self.ed {
let r = match find_range(&ed.errors, code) {
Some(r) => r,
_ => {
log::error!("Received an out of bounds error code {}", code);
break 'handle_error;
}
};
match r.extension {
Some(e) => (Some(e), code - r.first),
None => {
log::warn!(
"Received an error from an unconfigured extension: `{}`",
r.name
);
break 'handle_error;
}
}
} else {
log::error!("Received an extension error before extension have been fetched");
break 'handle_error;
};
let e = match ext {
Some(e) => XconError::ExtensionError(e, code),
_ => XconError::CoreError(code),
};
if let Some(first) = reply_handlers.front() {
if first.serial() == serial {
let handler = reply_handlers.pop_front().unwrap();
drop(reply_handlers);
handler.handle_error(e);
break 'handle_error;
}
}
log::error!(
"Received an error with no corresponding handler: {}",
ErrorFmt(e)
);
}
1 => {
if let Some(first) = reply_handlers.front() {
if first.serial() == serial {
let handler = reply_handlers.pop_front().unwrap();
drop(reply_handlers);
let mut fds = vec![];
if handler.has_fds() {
let num_fds = msg_buf[1] as usize;
if self.incoming.fds.len() < num_fds {
return Err(XconError::MissingFds);
}
fds.extend(self.incoming.fds.drain(..num_fds));
}
let length =
u32::from_ne_bytes([msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]])
as usize;
if length > MAX_LENGTH_UNITS {
return Err(XconError::ExcessiveMessageSize);
}
let length = length * 4;
self.incoming.fill_msg_buf(length, &mut msg_buf).await?;
let mut parser = unsafe {
let msg_buf = mem::transmute::<&[u8], &'static [u8]>(&msg_buf[..]);
Parser::new(msg_buf, fds)
};
handler.handle_result(
&self.socket.bufio,
&mut parser,
mem::take(&mut msg_buf),
)?;
}
}
}
ev => 'handle_event: {
let (ext, code) = if ev == XGE_EVENT {
let length =
u32::from_ne_bytes([msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]])
as usize;
if length > MAX_LENGTH_UNITS {
return Err(XconError::ExcessiveMessageSize);
}
let length = length * 4;
self.incoming.fill_msg_buf(length, &mut msg_buf).await?;
let opcode = msg_buf[1];
let ext = match &self.ed {
Some(ed) => ed.ext_by_opcode.get(&opcode),
_ => {
log::error!("Received an XGE event before extension have been fetched");
break 'handle_event;
}
};
let ext = match ext {
Some(ext) => *ext,
_ => {
log::warn!(
"Received an event from an unconfigured extension: `{}`",
opcode
);
break 'handle_event;
}
};
let code = u16::from_ne_bytes([msg_buf[8], msg_buf[9]]);
(Some(ext), code)
} else if ev < 64 {
(None, ev as u16)
} else if let Some(ed) = &self.ed {
let r = match find_range(&ed.events, ev) {
Some(r) => r,
_ => {
log::error!("Received an out of bounds event {}", ev);
break 'handle_event;
}
};
match r.extension {
Some(e) => (Some(e), (ev - r.first) as u16),
None => {
log::warn!(
"Received an event from an unconfigured extension: `{}`",
r.name
);
break 'handle_event;
}
}
} else {
log::error!("Received an extension event before extension have been fetched");
break 'handle_event;
};
self.socket.events.push(Event {
bufio: self.socket.bufio.clone(),
ext,
code,
buf: mem::take(&mut msg_buf),
});
}
}
if msg_buf.capacity() > 0 {
self.socket.bufio.add_buf(msg_buf);
}
Ok(())
}
}
fn find_range(codes: &[ExtensionIdRange], code: u8) -> Option<&ExtensionIdRange> {
let idx = match codes.binary_search_by_key(&code, |v| v.first) {
Ok(v) => v,
Err(v) if v > 0 => v - 1,
_ => return None,
};
Some(&codes[idx])
}

10
src/xcon/outgoing.rs Normal file
View file

@ -0,0 +1,10 @@
use crate::xcon::XconData;
use crate::ErrorFmt;
use std::rc::Rc;
pub(super) async fn handle_outgoing(socket: Rc<XconData>) {
if let Err(e) = socket.bufio.clone().outgoing().await {
log::error!("{}", ErrorFmt(e));
}
socket.kill();
}

138
src/xcon/parser.rs Normal file
View file

@ -0,0 +1,138 @@
use crate::utils::ptr_ext::PtrExt;
use crate::xcon::wire_type::Message;
use crate::xcon::XconError;
use bstr::{BStr, ByteSlice};
use std::borrow::Cow;
use std::mem;
use std::rc::Rc;
use uapi::{OwnedFd, Pod};
pub struct Parser<'a> {
pos: usize,
buf: &'a [u8],
fds_pos: usize,
fds: Vec<Rc<OwnedFd>>,
}
impl<'a> Parser<'a> {
pub fn new(buf: &'a [u8], fds: Vec<Rc<OwnedFd>>) -> Self {
Self {
buf,
pos: 0,
fds,
fds_pos: 0,
}
}
pub fn eof(&self) -> bool {
self.pos == self.buf.len()
}
fn rem(&self) -> usize {
self.buf.len() - self.pos
}
pub fn unmarshal<T: Message<'a>>(&mut self) -> Result<T, XconError> {
T::deserialize(self)
}
pub fn pad(&mut self, new: usize) -> Result<(), XconError> {
if new > self.buf.len() - self.pos {
return Err(XconError::UnexpectedEof);
}
self.pos += new;
Ok(())
}
pub fn align(&mut self, n: usize) -> Result<(), XconError> {
let new = self.pos + (self.pos.wrapping_neg() & (n - 1));
if new > self.buf.len() {
return Err(XconError::UnexpectedEof);
}
self.pos = new;
Ok(())
}
pub fn read_fd(&mut self) -> Result<Rc<OwnedFd>, XconError> {
if self.fds_pos >= self.fds.len() {
return Err(XconError::NotEnoughFds);
}
self.fds_pos += 1;
Ok(self.fds[self.fds_pos - 1].clone())
}
pub fn read_pod<'b, T: Pod>(&mut self) -> Result<T, XconError> {
match uapi::pod_read_init(&self.buf[self.pos..]) {
Ok(v) => {
self.pos += mem::size_of::<T>();
Ok(v)
}
_ => Err(XconError::UnexpectedEof),
}
}
pub fn read_list_slice<T: Message<'a> + Pod>(
&mut self,
n: Option<usize>,
) -> Result<&'a [T], XconError> {
let n = match n {
Some(n) => n,
_ => self.rem() / mem::size_of::<T>(),
};
let len = mem::size_of::<T>() * n;
if len > self.rem() {
return Err(XconError::UnexpectedEof);
}
if self.buf[self.pos..].as_ptr() as usize & (mem::align_of::<T>() - 1) != 0 {
return Err(XconError::UnalignedSlice);
}
let res =
unsafe { std::slice::from_raw_parts(self.buf.as_ptr().add(self.pos) as *const T, n) };
self.pos += len;
Ok(res)
}
pub fn read_list<T: Message<'a> + Clone>(
&mut self,
n: Option<usize>,
) -> Result<Cow<'a, [T]>, XconError> {
let mut res = vec![];
if let Some(n) = n {
for _ in 0..n {
res.push(T::deserialize(self)?);
}
} else {
while !self.eof() {
res.push(T::deserialize(self)?);
}
}
Ok(res.into())
}
pub fn read_bytes<const N: usize>(&mut self) -> Result<&'a [u8; N], XconError> {
if N > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = unsafe { self.buf.as_ptr().add(self.pos).cast::<[u8; N]>().deref() };
self.pos += N;
Ok(res)
}
pub fn read_slice(&mut self, n: usize) -> Result<&'a [u8], XconError> {
if n > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = &self.buf[self.pos..self.pos + n];
self.pos += n;
Ok(res)
}
pub fn read_string(&mut self, n: usize) -> Result<&'a BStr, XconError> {
if n > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = &self.buf[self.pos..self.pos + n];
self.pos += n;
Ok(res.as_bstr())
}
}

118
src/xcon/wire_type.rs Normal file
View file

@ -0,0 +1,118 @@
use crate::xcon::formatter::Formatter;
use crate::xcon::parser::Parser;
use crate::xcon::XconError;
use bstr::{BStr, ByteSlice};
use std::borrow::Cow;
use std::rc::Rc;
use uapi::OwnedFd;
#[cold]
fn unimplemented() -> ! {
unimplemented!();
}
pub unsafe trait Message<'a>: Clone + 'a {
type Generic<'b>: Message<'b>;
const IS_POD: bool;
const HAS_FDS: bool;
fn serialize(&self, formatter: &mut Formatter) {
let _ = formatter;
unimplemented()
}
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
let _ = parser;
unimplemented()
}
}
pub trait Request<'a>: Message<'a> {
type Reply: Message<'static>;
const EXTENSION: Option<usize>;
const IS_VOID: bool;
}
pub trait XEvent<'a>: Message<'a> {
const OPCODE: u16;
}
macro_rules! simple {
($ty:ty) => {
unsafe impl Message<'_> for $ty {
type Generic<'b> = $ty;
const IS_POD: bool = true;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_packed(self);
}
fn deserialize(parser: &mut Parser<'_>) -> Result<Self, XconError> {
parser.read_pod()
}
}
};
}
simple!(u8);
simple!(i8);
simple!(u16);
simple!(i16);
simple!(u32);
simple!(i32);
simple!(u64);
simple!(i64);
unsafe impl<'a> Message<'a> for () {
type Generic<'b> = ();
const IS_POD: bool = false;
const HAS_FDS: bool = false;
}
unsafe impl<'a> Message<'a> for &'a BStr {
type Generic<'b> = &'b BStr;
const IS_POD: bool = true;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_packed(self.as_bytes())
}
}
unsafe impl<'a, T: Message<'a>> Message<'a> for &'a [T] {
type Generic<'b> = &'b [T::Generic<'b>];
const IS_POD: bool = false;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_list(self);
}
}
unsafe impl<'a, T> Message<'a> for Cow<'a, [T]>
where
T: Message<'a>,
{
type Generic<'b> = Cow<'b, [T::Generic<'b>]>;
const IS_POD: bool = false;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_list(self);
}
}
unsafe impl<'a> Message<'a> for Rc<OwnedFd> {
type Generic<'b> = Rc<OwnedFd>;
const IS_POD: bool = false;
const HAS_FDS: bool = true;
fn serialize(&self, formatter: &mut Formatter) {
formatter.add_fd(self);
}
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
parser.read_fd()
}
}

96
src/xcon/xauthority.rs Normal file
View file

@ -0,0 +1,96 @@
use crate::xcon::XconError;
use bstr::{BString, ByteSlice};
use std::fs::File;
use std::io::Read;
pub const LOCAL: u16 = 256;
pub const MIT_MAGIC_COOKIE: &[u8] = b"MIT-MAGIC-COOKIE-1";
#[derive(Debug)]
pub struct XAuthority {
pub family: u16,
pub host: BString,
pub display: u32,
pub method: BString,
pub value: BString,
}
impl XAuthority {
pub fn load() -> Result<Vec<XAuthority>, XconError> {
let path = 'path: {
if let Ok(p) = std::env::var("XAUTHORITY") {
break 'path p;
}
if let Ok(home) = std::env::var("HOME") {
break 'path format!("{home}/.Xauthority");
}
return Err(XconError::HomeNotSet);
};
let mut buf = vec![];
if let Err(e) = File::open(&path).and_then(|mut f| f.read_to_end(&mut buf)) {
return Err(XconError::ReadXAuthority(e));
}
Parser::parse(&buf)
}
}
struct Parser<'a> {
pos: usize,
buf: &'a [u8],
}
impl<'a> Parser<'a> {
fn parse(buf: &[u8]) -> Result<Vec<XAuthority>, XconError> {
let mut slf = Parser { pos: 0, buf };
let mut res = vec![];
while slf.rem() > 0 {
res.push(slf.parse_one()?);
}
Ok(res)
}
fn rem(&self) -> usize {
self.buf.len() - self.pos
}
fn parse_one(&mut self) -> Result<XAuthority, XconError> {
Ok(XAuthority {
family: self.read_u16()?,
host: self.read_string()?,
display: {
let s = self.read_string()?;
match s.to_str() {
Ok(s) => match s.parse() {
Ok(v) => v,
_ => return Err(XconError::InvalidAuthorityDisplay),
},
_ => return Err(XconError::InvalidAuthorityDisplay),
}
},
method: self.read_string()?,
value: self.read_string()?,
})
}
fn read_u16(&mut self) -> Result<u16, XconError> {
if self.rem() < 2 {
return Err(XconError::UnexpectedEof);
}
let bytes = [self.buf[self.pos], self.buf[self.pos + 1]];
self.pos += 2;
Ok(u16::from_be_bytes(bytes))
}
fn read_string(&mut self) -> Result<BString, XconError> {
let len = self.read_u16()? as usize;
if self.rem() < len {
log::info!("rem = {}; len = {}", self.rem(), len);
return Err(XconError::UnexpectedEof);
}
let res = self.buf[self.pos..self.pos + len].to_vec();
self.pos += len;
let res = res.into();
Ok(res)
}
}