Skip to main content

nzb_rs/
errors.rs

1use std::{io, path::PathBuf};
2use thiserror::Error;
3
4#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
5/// Represents the attributes that can be present in a 'file' element of an NZB document.
6pub enum FileAttributeKind {
7    Poster,
8    Date,
9    Subject,
10}
11
12impl std::fmt::Display for FileAttributeKind {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        match *self {
15            Self::Poster => write!(f, "poster"),
16            Self::Date => write!(f, "date"),
17            Self::Subject => write!(f, "subject"),
18        }
19    }
20}
21
22#[derive(Error, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
23/// Represents errors that can occur during the parsing of an NZB document.
24pub enum ParseNzbError {
25    /// Indicates an invalid or missing 'groups' element within a 'file' element.
26    /// Each 'file' element must contain at least one valid 'groups' element.
27    #[error(
28        "Invalid or missing 'groups' element within a 'file' element. \
29        Each 'file' element must contain at least one valid 'groups' element."
30    )]
31    GroupsElement,
32
33    /// Indicates an invalid or missing 'segments' element within a 'file' element.
34    /// Each 'file' element must contain at least one valid 'segments' element.
35    #[error(
36        "Invalid or missing 'segments' element within a 'file' element. \
37        Each 'file' element must contain at least one valid 'segments' element."
38    )]
39    SegmentsElement,
40
41    /// Indicates an invalid or missing 'file' element in the NZB document.
42    /// The NZB document must contain at least one valid 'file' element.
43    #[error(
44        "Invalid or missing 'file' element in the NZB document. \
45        The NZB document must contain at least one valid 'file' element."
46    )]
47    FileElement,
48
49    /// Indicates that the NZB document contains only `.par2` files.
50    /// The NZB document must include at least one non-`.par2` file.
51    #[error(
52        "The NZB document contains only `.par2` files. \
53        It must include at least one non-`.par2` file."
54    )]
55    OnlyPar2Files,
56
57    /// Indicates an invalid or missing required attribute in a 'file' element.
58    #[error("Invalid or missing required attribute '{attribute}' in a 'file' element.")]
59    FileAttribute {
60        /// The attribute that was invalid or missing.
61        attribute: FileAttributeKind,
62    },
63
64    /// Indicates that the NZB document is not valid XML and could not be parsed.
65    #[error("The NZB document is not valid XML and could not be parsed: {message}")]
66    XmlSyntax {
67        /// The error message provided by the underlying XML parsing library
68        /// ([`roxmltree`](https://crates.io/crates/roxmltree) in this case).
69        message: String,
70    },
71}
72
73impl From<roxmltree::Error> for ParseNzbError {
74    fn from(error: roxmltree::Error) -> Self {
75        ParseNzbError::XmlSyntax {
76            message: error.to_string(),
77        }
78    }
79}
80
81#[derive(Error, Debug)]
82/// Represents errors that can occur when attempting to parse an NZB file from a file path.
83pub enum ParseNzbFileError {
84    /// Input/Output error encountered while trying to read the NZB file.
85    #[error("I/O error while reading file '{file}': {source}")]
86    Io {
87        /// The underlying I/O error that occurred.
88        source: io::Error,
89        /// The path to the file that was being accessed when the error occurred.
90        file: PathBuf,
91    },
92
93    /// Error during Gzip decompression of the NZB file.
94    #[error("Gzip decompression error for file '{file}': {source}")]
95    Gzip {
96        /// The underlying I/O error reported by the Gzip decompression process.
97        source: io::Error,
98        /// The path to the file that was being decompressed when the error occurred.
99        file: PathBuf,
100    },
101
102    ///  Error encountered during the core NZB parsing logic.
103    #[error("NZB parsing error: {source}")]
104    Parse {
105        /// The specific NZB parsing error.
106        source: ParseNzbError,
107    },
108}
109
110impl ParseNzbFileError {
111    pub(crate) fn from_io_err(source: io::Error, file: impl Into<PathBuf>) -> Self {
112        ParseNzbFileError::Io {
113            source,
114            file: file.into(),
115        }
116    }
117
118    pub(crate) fn from_gzip_err(source: io::Error, file: impl Into<PathBuf>) -> Self {
119        ParseNzbFileError::Gzip {
120            source,
121            file: file.into(),
122        }
123    }
124}
125
126impl From<ParseNzbError> for ParseNzbFileError {
127    fn from(source: ParseNzbError) -> Self {
128        ParseNzbFileError::Parse { source }
129    }
130}