Skip to main content

lab_rs/
error.rs

1//! error types for parsing `.lab` files
2
3use std::fmt;
4
5/// an error produced while parsing a `.lab` file
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct ParseError {
8    /// 1-indexed line number the error occurred on
9    pub line: usize,
10    /// what went wrong on that line
11    pub kind: ParseErrorKind,
12}
13
14/// the specific kind of parse failure
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum ParseErrorKind {
18    /// the line is empty or has invalid label syntax
19    InvalidLabel(String),
20    /// a field that looked like a time could not be parsed as an integer
21    InvalidTime(String),
22    /// the start time is greater than the end time
23    StartAfterEnd {
24        /// parsed start time, in 100ns units
25        start: u64,
26        /// parsed end time, in 100ns units
27        end: u64,
28    },
29}
30
31impl fmt::Display for ParseError {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        write!(f, "line {}: ", self.line)?;
34        match &self.kind {
35            ParseErrorKind::InvalidLabel(s) => write!(f, "invalid label: {s}"),
36            ParseErrorKind::InvalidTime(s) => write!(f, "invalid time value `{s}`"),
37            ParseErrorKind::StartAfterEnd { start, end } => {
38                write!(f, "start time {start} is after end time {end}")
39            }
40        }
41    }
42}
43
44/// an error produced while scaling label timestamps
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46#[non_exhaustive]
47pub enum ScaleError {
48    /// the scaling factor is not a finite number
49    NonFiniteFactor,
50    /// the scaling factor is negative
51    NegativeFactor,
52}
53
54impl fmt::Display for ScaleError {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            ScaleError::NonFiniteFactor => f.write_str("scale factor must be finite"),
58            ScaleError::NegativeFactor => f.write_str("scale factor must not be negative"),
59        }
60    }
61}
62
63impl std::error::Error for ScaleError {}
64
65impl std::error::Error for ParseError {}
66
67/// an error produced while reading a .lab from a reader or path
68#[derive(Debug)]
69#[non_exhaustive]
70pub enum ReadError {
71    /// an io error occurred while reading
72    Io(std::io::Error),
73    /// the contents were read but could not be parsed
74    Parse(ParseError),
75}
76
77impl fmt::Display for ReadError {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            ReadError::Io(e) => write!(f, "i/o error: {e}"),
81            ReadError::Parse(e) => write!(f, "parse error: {e}"),
82        }
83    }
84}
85
86impl std::error::Error for ReadError {
87    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
88        match self {
89            ReadError::Io(e) => Some(e),
90            ReadError::Parse(e) => Some(e),
91        }
92    }
93}
94
95impl From<std::io::Error> for ReadError {
96    fn from(e: std::io::Error) -> Self {
97        ReadError::Io(e)
98    }
99}
100
101impl From<ParseError> for ReadError {
102    fn from(e: ParseError) -> Self {
103        ReadError::Parse(e)
104    }
105}