Skip to main content

xvc_protocol/
error.rs

1use std::{
2    error::Error,
3    fmt::{self, Display},
4    io,
5    num::ParseIntError,
6    str::Utf8Error,
7};
8
9use crate::codec::ParseErr;
10
11/// Errors that may occur when reading a message from a stream.
12#[derive(Debug)]
13pub enum ReadError {
14    IoError(io::Error),
15    InvalidCommand(String),
16    InvalidFormat(String),
17    TooManyBytes { max: usize, need: usize },
18}
19
20impl From<io::Error> for ReadError {
21    fn from(value: io::Error) -> Self {
22        ReadError::IoError(value)
23    }
24}
25
26impl From<Utf8Error> for ReadError {
27    fn from(value: Utf8Error) -> Self {
28        ReadError::InvalidFormat(format!("Invalid UTF8: {}", value))
29    }
30}
31
32impl From<ParseIntError> for ReadError {
33    fn from(value: ParseIntError) -> Self {
34        ReadError::InvalidFormat(format!("Invalid integer: {}", value))
35    }
36}
37
38impl From<ParseVersionError> for ReadError {
39    fn from(value: ParseVersionError) -> Self {
40        Self::InvalidFormat(format!("{}", value))
41    }
42}
43
44impl From<crate::codec::ParseErr> for ReadError {
45    fn from(value: crate::codec::ParseErr) -> Self {
46        match value {
47            ParseErr::Incomplete => ReadError::IoError(io::Error::new(
48                io::ErrorKind::UnexpectedEof,
49                "incomplete message",
50            )),
51            ParseErr::InvalidCommand(items) => {
52                ReadError::InvalidCommand(String::from_utf8_lossy(&items).to_string())
53            }
54            ParseErr::TooManyBytes { max, got } => ReadError::TooManyBytes { max, need: got },
55            ParseErr::Utf8Error(utf8_error) => {
56                ReadError::InvalidFormat(format!("Invalid utf8: {}", utf8_error))
57            }
58            ParseErr::ParseIntError(parse_int_error) => {
59                ReadError::InvalidFormat(format!("Invalid integer: {}", parse_int_error))
60            }
61            ParseErr::ParseVersionError(parse_version_error) => ReadError::InvalidFormat(format!(
62                "Could not parse version: {}",
63                parse_version_error
64            )),
65        }
66    }
67}
68
69impl Display for ReadError {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        match self {
72            ReadError::IoError(error) => write!(f, "{}", error),
73            ReadError::InvalidCommand(cmd) => write!(f, "Received invalid command {}", cmd),
74            ReadError::InvalidFormat(format) => write!(f, "{}", format),
75            ReadError::TooManyBytes { max, need: got } => {
76                write!(f, "Message too large! Maximum is {}, but got {}", max, got)
77            }
78        }
79    }
80}
81
82impl Error for ReadError {}
83
84/// Errors that may occur when parsing a Version.
85#[derive(Debug, Eq, PartialEq, Clone)]
86pub enum ParseVersionError {
87    MissingDot,
88    ParseInt(ParseIntError),
89}
90
91impl From<ParseIntError> for ParseVersionError {
92    fn from(value: ParseIntError) -> Self {
93        ParseVersionError::ParseInt(value)
94    }
95}
96
97impl Display for ParseVersionError {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        match self {
100            ParseVersionError::MissingDot => write!(f, "Missing dot in version"),
101            ParseVersionError::ParseInt(parse_err) => write!(f, "{}", parse_err),
102        }
103    }
104}
105
106impl Error for ParseVersionError {}