Skip to main content

netscape_cookie_file_parser/
error.rs

1use std::error::Error;
2use std::fmt;
3
4/// Error returned when parsing a cookie stream.
5///
6/// Single-line parsing returns [`ParseErrorKind`] directly. Stream parsing wraps
7/// the kind with the 1-based line number where parsing failed.
8#[derive(Debug)]
9pub struct ParseError {
10    /// 1-based line number in the input stream.
11    pub line: usize,
12    /// Detailed parse failure.
13    pub kind: ParseErrorKind,
14}
15
16/// Detailed reason a cookie line or stream could not be parsed.
17#[derive(Debug)]
18pub enum ParseErrorKind {
19    /// The underlying buffered reader failed.
20    Io(std::io::Error),
21    /// A non-comment cookie line had a field count other than seven.
22    MissingFields { found: usize },
23    /// The expires field was empty, non-decimal, or overflowed `u64`.
24    InvalidExpires,
25    /// The cookie name or value contained an ASCII control octet.
26    InvalidOctets,
27}
28
29impl fmt::Display for ParseError {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(f, "line {}: {}", self.line, self.kind)
32    }
33}
34
35impl fmt::Display for ParseErrorKind {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::Io(error) => write!(f, "read error: {error}"),
39            Self::MissingFields { found } => {
40                write!(f, "expected 7 tab-separated fields, found {found}")
41            }
42            Self::InvalidExpires => f.write_str("invalid expires timestamp"),
43            Self::InvalidOctets => f.write_str("cookie name or value contains control octets"),
44        }
45    }
46}
47
48impl Error for ParseError {
49    fn source(&self) -> Option<&(dyn Error + 'static)> {
50        match &self.kind {
51            ParseErrorKind::Io(error) => Some(error),
52            _ => None,
53        }
54    }
55}