src/client.rs
use crate::proto::{
WlCallbackDone, WlDisplayError, WlDisplaySync, WlMsg, WlOpCode, WlUnknowHeader,
};
use elvwf::{self as wf, Wired};
use std::{
io::{Read, Write},
os::unix::net::UnixStream,
path::Path,
};
#[derive(Debug)]
pub struct WlClient {
stream: UnixStream,
buffer: Box<[u8]>,
write_cursor: usize,
read_cursor: usize,
read_length: usize,
next_id: u32,
}
#[derive(Debug)]
pub enum Error {
IO(std::io::Error),
Msg(wf::Error),
Header(wf::header::Error),
}
impl From<std::io::Error> for Error {
fn from(value: std::io::Error) -> Self {
Self::IO(value)
}
}
impl From<wf::header::Error> for Error {
fn from(value: wf::header::Error) -> Self {
Self::Header(value)
}
}
impl From<wf::Error> for Error {
fn from(value: wf::Error) -> Self {
Self::Msg(value)
}
}
impl WlClient {
pub const ID: u32 = 1;
pub fn new(path: impl AsRef<Path>, capacity: usize) -> Result<Self, Error> {
Ok(Self {
stream: UnixStream::connect(path)?,
buffer: Box::from(vec![0u8; 1024]),
write_cursor: 0,
read_cursor: 0,
read_length: 0,
next_id: 2,
})
}
pub fn next(&mut self) -> u32 {
let next_id = self.next_id;
self.next_id += 1;
next_id
}
pub fn request<'a, T: WlOpCode + Wired<'a>>(&mut self, request: WlMsg<T>) -> Result<(), Error> {
let buf = &mut &mut self.buffer[self.write_cursor..];
let start = buf.len();
wf::msg::encode_value(buf, request)?;
let len = start - buf.len();
self.write_cursor += len;
Ok(())
}
pub fn flush(&mut self) -> Result<(), Error> {
self.stream.write_all(&self.buffer[..self.write_cursor])?;
self.write_cursor = 0;
Ok(())
}
pub fn pump(&mut self) -> Result<(), Error> {
let new_callback = self.next();
self.request(WlMsg::new(Self::ID, WlDisplaySync { new_callback }))?;
self.flush()?;
self.read_cursor = 0;
self.read_length = 0;
let buf = &mut &mut self.buffer[..];
loop {
self.stream.read_exact(&mut buf[..8])?;
let h = wf::msg::decode_value::<WlUnknowHeader>(&mut &buf[..8], 8)?;
self.stream.read_exact(&mut buf[8..h.len as usize])?;
if h.id == new_callback && h.op == WlCallbackDone::OP_CODE as u16 {
break Ok(());
}
if h.id == Self::ID && h.op == WlDisplayError::OP_CODE as u16 {
let error =
wf::msg::decode_value::<WlMsg<WlDisplayError>>(&mut &buf[..h.len as usize], 8)?;
eprintln!(
"[ERROR] ({}): {}",
error.payload().code,
error.payload().message
);
break Ok(());
}
*buf = &mut buf[h.len as usize..];
self.read_length += h.len as usize;
}
}
pub fn read<'a, T: WlOpCode + Wired<'a>>(&'a mut self) -> Result<Option<WlMsg<T>>, Error> {
if self.read_cursor == self.read_length {
return Ok(None);
}
let buf = &mut &self.buffer[self.read_cursor..self.read_length];
let start = buf.len();
let msg = wf::msg::decode_value::<WlMsg<T>>(buf, 8)?;
self.read_cursor += start - buf.len();
Ok(Some(msg))
}
}