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, 1,
)?; )?;
stream.write_all(&Vec::from(hello))?; stream.write_all(&Vec::try_from(hello)?)?;
Ok(Self { stream }) Ok(Self { stream })
} }
} }
impl Iterator for OtdIpc { impl Iterator for OtdIpc {
type Item = Message; type Item = Result<Message, Box<dyn std::error::Error>>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let mut raw_header = [0; size_of::<Header>()]; 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>()]; 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 { if let Err(e) = self.stream.read_exact(&mut raw_buffer) {
messages::MessageType::None => None, return Some(Err(e.into()));
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()))
} }
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 => { messages::MessageType::DebugMessage => {
Some(Message::DebugMessage(DebugMessage::from(&raw_buffer[..]))) Message::DebugMessage(DebugMessage::from(raw_buffer))
} }
messages::MessageType::Experimental => { messages::MessageType::Experimental => {
Some(Message::Experimental(Experimental::from(&raw_buffer[..]))) Message::Experimental(Experimental::from(raw_buffer))
}
messages::MessageType::Hello => {
Some(Message::Hello(Hello::try_from(&raw_buffer[..]).unwrap()))
}
}
} }
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")?; let otd_ipc = OtdIpc::new("otd-ipc-rs", "master")?;
for msg in otd_ipc { for msg in otd_ipc {
dbg!(msg); dbg!(msg?);
} }
Ok(()) Ok(())

View File

@@ -13,11 +13,11 @@ pub struct DeviceInfo {
} }
impl TryFrom<&[u8]> for 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> { fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 12 + 256 + 256 { 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)?); 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 { 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> { fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 12 { if bytes.len() < 12 {
return Err("buffer too small"); return Err("buffer too small".into());
} }
Ok(Self { Ok(Self {

View File

@@ -45,8 +45,10 @@ impl Hello {
} }
} }
impl From<Hello> for Vec<u8> { impl TryFrom<Hello> for Vec<u8> {
fn from(value: Hello) -> Self { 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>()); let mut output = Vec::with_capacity(std::mem::size_of::<Hello>());
// Header // Header
@@ -56,22 +58,22 @@ impl From<Hello> for Vec<u8> {
// Hello // Hello
output.extend_from_slice(&value.protocol_version.to_le_bytes()); 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_name)?);
output.extend_from_slice(&str_to_fixed(&value.human_readable_version).unwrap()); output.extend_from_slice(&str_to_fixed(&value.human_readable_version)?);
output.extend_from_slice(&str_to_fixed(&value.implementation_id).unwrap()); output.extend_from_slice(&str_to_fixed(&value.implementation_id)?);
output.push(value.compatibility_version); output.push(value.compatibility_version);
output Ok(output)
} }
} }
impl TryFrom<&[u8]> for Hello { 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> { fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 8 + 256 + 256 + 256 + 1 { 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? // random 4 bytes are here now, wtf?

View File

@@ -18,6 +18,7 @@ pub use state::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Message { pub enum Message {
None,
DeviceInfo(Box<DeviceInfo>), DeviceInfo(Box<DeviceInfo>),
State(State), State(State),
Ping(Ping), Ping(Ping),
@@ -27,11 +28,13 @@ pub enum Message {
} }
// helper to read fixed-size chunks // 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 { if bytes.len() < N {
return Err("buffer too small"); return Err("buffer too small".into());
} }
let (head, tail) = bytes.split_at(N); let (head, tail) = bytes.split_at(N);
*bytes = tail; *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 { 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> { fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 4 { if bytes.len() < 4 {
return Err("buffer too small"); return Err("buffer too small".into());
} }
Ok(Self { Ok(Self {

View File

@@ -131,11 +131,11 @@ impl State {
} }
impl TryFrom<&[u8]> for 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> { fn try_from(mut bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() < 29 { if bytes.len() < 29 {
return Err("buffer too small"); return Err("buffer too small".into());
} }
Ok(Self { Ok(Self {