Error Handling

This commit is contained in:
2026-02-26 20:35:04 +01:00
parent ae15494e85
commit bb3892a239
8 changed files with 60 additions and 45 deletions

View File

@@ -30,43 +30,53 @@ impl OtdIpc {
1,
)?;
stream.write_all(&Vec::from(hello))?;
stream.write_all(&Vec::try_from(hello)?)?;
Ok(Self { stream })
}
}
impl Iterator for OtdIpc {
type Item = Message;
type Item = Result<Message, Box<dyn std::error::Error>>;
fn next(&mut self) -> Option<Self::Item> {
let mut raw_header = [0; size_of::<Header>()];
self.stream.read_exact(&mut raw_header).unwrap();
if let Err(e) = self.stream.read_exact(&mut raw_header) {
return Some(Err(e.into()));
};
let header: Header = match raw_header[..].try_into() {
Ok(e) => e,
Err(e) => return Some(Err(e)),
};
let header: Header = raw_header[..].try_into().unwrap();
let mut raw_buffer = vec![0; (header.size as usize) - size_of::<Header>()];
self.stream.read_exact(&mut raw_buffer).unwrap();
match header.message_type {
messages::MessageType::None => None,
messages::MessageType::DeviceInfo => Some(Message::DeviceInfo(Box::new(
DeviceInfo::try_from(&raw_buffer[..]).unwrap(),
))),
messages::MessageType::State => {
Some(Message::State(State::try_from(&raw_buffer[..]).unwrap()))
if let Err(e) = self.stream.read_exact(&mut raw_buffer) {
return Some(Err(e.into()));
}
messages::MessageType::Ping => {
Some(Message::Ping(Ping::try_from(&raw_buffer[..]).unwrap()))
Some(get_message(header.message_type, &raw_buffer))
}
}
fn get_message(
message_type: MessageType,
raw_buffer: &[u8],
) -> Result<Message, Box<dyn std::error::Error>> {
Ok(match message_type {
messages::MessageType::None => Message::None,
messages::MessageType::DeviceInfo => {
Message::DeviceInfo(Box::new(DeviceInfo::try_from(raw_buffer)?))
}
messages::MessageType::State => Message::State(State::try_from(raw_buffer)?),
messages::MessageType::Ping => Message::Ping(Ping::try_from(raw_buffer)?),
messages::MessageType::DebugMessage => {
Some(Message::DebugMessage(DebugMessage::from(&raw_buffer[..])))
Message::DebugMessage(DebugMessage::from(raw_buffer))
}
messages::MessageType::Experimental => {
Some(Message::Experimental(Experimental::from(&raw_buffer[..])))
}
messages::MessageType::Hello => {
Some(Message::Hello(Hello::try_from(&raw_buffer[..]).unwrap()))
}
}
Message::Experimental(Experimental::from(raw_buffer))
}
messages::MessageType::Hello => Message::Hello(Hello::try_from(raw_buffer)?),
})
}

View File

@@ -4,7 +4,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let otd_ipc = OtdIpc::new("otd-ipc-rs", "master")?;
for msg in otd_ipc {
dbg!(msg);
dbg!(msg?);
}
Ok(())

View File

@@ -13,11 +13,11 @@ pub struct DeviceInfo {
}
impl TryFrom<&[u8]> for DeviceInfo {
type Error = &'static str;
type Error = Box<dyn std::error::Error>;
fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 12 + 256 + 256 {
return Err("buffer too small");
return Err("buffer too small".into());
}
let max_x = f32::from_le_bytes(take::<4>(&mut bytes)?);

View File

@@ -12,11 +12,11 @@ pub struct Header {
}
impl TryFrom<&[u8]> for Header {
type Error = &'static str;
type Error = Box<dyn std::error::Error>;
fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 12 {
return Err("buffer too small");
return Err("buffer too small".into());
}
Ok(Self {

View File

@@ -45,8 +45,10 @@ impl Hello {
}
}
impl From<Hello> for Vec<u8> {
fn from(value: Hello) -> Self {
impl TryFrom<Hello> for Vec<u8> {
type Error = Box<dyn std::error::Error>;
fn try_from(value: Hello) -> Result<Self, Self::Error> {
let mut output = Vec::with_capacity(std::mem::size_of::<Hello>());
// Header
@@ -56,22 +58,22 @@ impl From<Hello> for Vec<u8> {
// Hello
output.extend_from_slice(&value.protocol_version.to_le_bytes());
output.extend_from_slice(&str_to_fixed(&value.human_readable_name).unwrap());
output.extend_from_slice(&str_to_fixed(&value.human_readable_version).unwrap());
output.extend_from_slice(&str_to_fixed(&value.implementation_id).unwrap());
output.extend_from_slice(&str_to_fixed(&value.human_readable_name)?);
output.extend_from_slice(&str_to_fixed(&value.human_readable_version)?);
output.extend_from_slice(&str_to_fixed(&value.implementation_id)?);
output.push(value.compatibility_version);
output
Ok(output)
}
}
impl TryFrom<&[u8]> for Hello {
type Error = &'static str;
type Error = Box<dyn std::error::Error>;
fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 8 + 256 + 256 + 256 + 1 {
return Err("buffer too small");
return Err("buffer too small".into());
}
// random 4 bytes are here now, wtf?

View File

@@ -18,6 +18,7 @@ pub use state::*;
#[derive(Debug, Clone)]
pub enum Message {
None,
DeviceInfo(Box<DeviceInfo>),
State(State),
Ping(Ping),
@@ -27,11 +28,13 @@ pub enum Message {
}
// helper to read fixed-size chunks
pub(super) fn take<const N: usize>(bytes: &mut &[u8]) -> Result<[u8; N], &'static str> {
pub(super) fn take<const N: usize>(
bytes: &mut &[u8],
) -> Result<[u8; N], Box<dyn std::error::Error>> {
if bytes.len() < N {
return Err("buffer too small");
return Err("buffer too small".into());
}
let (head, tail) = bytes.split_at(N);
*bytes = tail;
Ok(head.try_into().unwrap())
Ok(head.try_into()?)
}

View File

@@ -10,11 +10,11 @@ pub struct Ping {
}
impl TryFrom<&[u8]> for Ping {
type Error = &'static str;
type Error = Box<dyn std::error::Error>;
fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 4 {
return Err("buffer too small");
return Err("buffer too small".into());
}
Ok(Self {

View File

@@ -131,11 +131,11 @@ impl State {
}
impl TryFrom<&[u8]> for State {
type Error = &'static str;
type Error = Box<dyn std::error::Error>;
fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 29 {
return Err("buffer too small");
return Err("buffer too small".into());
}
Ok(Self {