1use std::{io, path::PathBuf};
2use thiserror::Error;
3
4#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub 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)]
23pub enum ParseNzbError {
25 #[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 #[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 #[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 #[error(
52 "The NZB document contains only `.par2` files. \
53 It must include at least one non-`.par2` file."
54 )]
55 OnlyPar2Files,
56
57 #[error("Invalid or missing required attribute '{attribute}' in a 'file' element.")]
59 FileAttribute {
60 attribute: FileAttributeKind,
62 },
63
64 #[error("The NZB document is not valid XML and could not be parsed: {message}")]
66 XmlSyntax {
67 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)]
82pub enum ParseNzbFileError {
84 #[error("I/O error while reading file '{file}': {source}")]
86 Io {
87 source: io::Error,
89 file: PathBuf,
91 },
92
93 #[error("Gzip decompression error for file '{file}': {source}")]
95 Gzip {
96 source: io::Error,
98 file: PathBuf,
100 },
101
102 #[error("NZB parsing error: {source}")]
104 Parse {
105 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}