stork_lib/index_v3/build/
errors.rs1use std::{fmt, path::PathBuf};
2use thiserror::Error;
3
4use crate::config::File;
5
6#[derive(Debug, Error, Clone, PartialEq)]
7pub enum WordListGenerationError {
8 #[error("SRT file could not be parsed.")]
9 InvalidSRT,
10
11 #[error("The file `{0}` could not be found.")]
12 FileNotFound(PathBuf),
13
14 #[error("Could not determine the file's filetype. Please give this file a file extension Stork knows about, or disambiguate the file's filetype within your config.")]
15 CannotDetermineFiletype,
16
17 #[error("The selector `{0}` is not present in the HTML document.")]
18 SelectorNotPresent(String),
19
20 #[error("The web page could not be fetched")]
21 WebPageNotFetched,
22
23 #[error("When fetched, the web page returned a {0} status code.")]
24 WebPageErrorfulStatusCode(u16),
25
26 #[error("Content-Type is not present or invalid")]
27 UnknownContentType,
28
29 #[error("After parsing the document, there were no words found in the word list.")]
30 EmptyWordList,
31
32 #[error("Stork was not built with the `web-scraping` feature enabled.")]
33 FeatureNotAvailable,
34}
35
36fn pluralize_with_count(count: usize, singular: &str, plural: &str) -> String {
37 format!("{count} {}", if count == 1 { singular } else { plural })
38}
39
40#[derive(Debug, Error)]
41pub enum IndexGenerationError {
42 #[error("No files specified in config file")]
43 NoFilesSpecified,
44
45 #[error("All files failed to be indexed.\n{}", DocumentError::display_list(.0))]
46 AllDocumentErrors(Vec<DocumentError>),
47
48 #[error(
49 "{} found while indexing files. If you want to fail silently and still build an index, remove `break_on_file_error` from your config.\n{}",
50 pluralize_with_count(.0.len(), "error", "errors"),
51 DocumentError::display_list(.0)
52 )]
53 PartialDocumentErrors(Vec<DocumentError>),
54}
55
56impl PartialEq for IndexGenerationError {
57 fn eq(&self, other: &Self) -> bool {
58 match (self, other) {
59 (Self::PartialDocumentErrors(_), Self::PartialDocumentErrors(_))
60 | (Self::AllDocumentErrors(_), Self::AllDocumentErrors(_)) => true,
61 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
62 }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq)]
70pub struct DocumentError {
71 pub file: File,
72 pub word_list_generation_error: WordListGenerationError,
73}
74
75impl std::fmt::Display for DocumentError {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(
78 f,
79 "In file `{}`: {}",
80 self.file, self.word_list_generation_error,
81 )
82 }
83}
84
85impl DocumentError {
86 #[must_use]
87 pub fn display_list(vec: &[DocumentError]) -> String {
88 format!(
89 "Warning: Stork couldn't include {} in the index because of the following errors:\n",
90 pluralize_with_count(vec.len(), "file", "files"),
91 ) + &vec
92 .iter()
93 .map(ToString::to_string)
94 .collect::<Vec<String>>()
95 .join("\n")
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::config::DataSource;
102
103 use super::*;
104 use pretty_assertions::assert_eq;
105
106 #[test]
107 fn test_documenterrors_display() {
108 let computed = DocumentError {
109 file: File {
110 title: "My Test File".to_string(),
111 explicit_source: Some(DataSource::Contents("ignored".to_string())),
112 ..File::default()
113 },
114 word_list_generation_error: WordListGenerationError::FileNotFound(PathBuf::from(
115 "/test",
116 )),
117 }
118 .to_string();
119
120 let expected = "In file `My Test File`: The file `/test` could not be found.";
121 assert_eq!(computed, expected);
122 }
123
124 #[test]
125 fn test_documenterror_list_display() {
126 let computed = DocumentError::display_list(&[
127 DocumentError {
128 file: File {
129 title: "My Test File".to_string(),
130 explicit_source: Some(DataSource::Contents("ignored".to_string())),
131 ..File::default()
132 },
133 word_list_generation_error: WordListGenerationError::FileNotFound(PathBuf::from(
134 "/test",
135 )),
136 },
137 DocumentError {
138 file: File {
139 title: "My Test File 2".to_string(),
140 explicit_source: Some(DataSource::Contents("ignored 2".to_string())),
141 ..File::default()
142 },
143 word_list_generation_error: WordListGenerationError::FileNotFound(PathBuf::from(
144 "/test2",
145 )),
146 },
147 ]);
148
149 let expected = "Warning: Stork couldn't include 2 files in the index because of the following errors:\nIn file `My Test File`: The file `/test` could not be found.\nIn file `My Test File 2`: The file `/test2` could not be found.";
150 assert_eq!(computed, expected);
151 }
152}