Error Handling
This commit is contained in:
60
src/lib.rs
60
src/lib.rs
@@ -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()))
|
||||
}
|
||||
messages::MessageType::Ping => {
|
||||
Some(Message::Ping(Ping::try_from(&raw_buffer[..]).unwrap()))
|
||||
}
|
||||
messages::MessageType::DebugMessage => {
|
||||
Some(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()))
|
||||
}
|
||||
if let Err(e) = self.stream.read_exact(&mut raw_buffer) {
|
||||
return Some(Err(e.into()));
|
||||
}
|
||||
|
||||
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 => {
|
||||
Message::DebugMessage(DebugMessage::from(raw_buffer))
|
||||
}
|
||||
messages::MessageType::Experimental => {
|
||||
Message::Experimental(Experimental::from(raw_buffer))
|
||||
}
|
||||
messages::MessageType::Hello => Message::Hello(Hello::try_from(raw_buffer)?),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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)?);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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()?)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user