1macro_rules! loadable_trait {
21 ($Trait:ident, $Err:ty, $Out:ty, $get:ident, $get_with_path:ident) => {
22 pub(crate) trait $Trait {
23 fn $get(self) -> Result<$Out, $Err>;
24 fn $get_with_path(self) -> Result<(std::path::PathBuf, $Out), $Err>;
25 }
26
27 impl<T: $Trait> $Trait for Result<T, $Err> {
28 fn $get(self) -> Result<$Out, $Err> {
29 self.map(|t| t.$get())?
30 }
31 fn $get_with_path(self) -> Result<(std::path::PathBuf, $Out), $Err> {
32 self.map(|t| t.$get_with_path())?
33 }
34 }
35 };
36}
37
38macro_rules! loader_dir_doc {
40 (files_only) => {
41 "Creates a new loader on all files within a directory (ignores subdirectories)."
42 };
43 (all_entries) => {
44 "Creates a new loader on all entries within a directory. Entries are not \
45 filtered: a non-file entry's path is yielded too and surfaces as an error \
46 when loaded."
47 };
48}
49
50macro_rules! loader_dir_entries {
57 (files_only, $entries:expr, $Err:ty) => {
58 $entries.filter_map(|entry| {
59 let path = entry.ok()?.path();
60 if path.is_file() { Some(Ok(path)) } else { None }
61 })
62 };
63 (all_entries, $entries:expr, $Err:ty) => {
64 $entries.map(|entry| {
65 Ok(entry
66 .map_err($crate::loaders::file::FileLoaderError::IoError)
67 .map_err(<$Err>::from)?
68 .path())
69 })
70 };
71}
72
73macro_rules! loader_scaffold {
79 ($Loader:ident, $Err:ty, dir: $dir_kind:ident $(, extra: $P:ident)?) => {
80 pub struct IntoIter<'a, T> {
81 iterator: Box<dyn Iterator<Item = T> + 'a>,
82 }
83
84 impl<'a, T $(, $P)?> IntoIterator for $Loader<'a, T $(, $P)?> {
85 type Item = T;
86 type IntoIter = IntoIter<'a, T>;
87
88 fn into_iter(self) -> Self::IntoIter {
89 IntoIter {
90 iterator: self.iterator,
91 }
92 }
93 }
94
95 impl<T> Iterator for IntoIter<'_, T> {
96 type Item = T;
97
98 fn next(&mut self) -> Option<Self::Item> {
99 self.iterator.next()
100 }
101 }
102
103 impl<'a, T: 'a $(, $P)?> $Loader<'a, Result<T, $Err> $(, $P)?> {
104 pub fn ignore_errors(self) -> $Loader<'a, T $(, $P)?> {
107 $Loader {
108 iterator: Box::new(self.iterator.filter_map(|res| res.ok())),
109 $(_processor: std::marker::PhantomData::<$P>,)?
110 }
111 }
112 }
113
114 impl<'a $(, $P)?> $Loader<'a, Result<std::path::PathBuf, $Err> $(, $P)?> {
115 pub fn with_glob(
117 pattern: &str,
118 ) -> Result<$Loader<'_, Result<std::path::PathBuf, $Err> $(, $P)?>, $Err> {
119 let paths = ::glob::glob(pattern)
120 .map_err($crate::loaders::file::FileLoaderError::PatternError)
121 .map_err(<$Err>::from)?;
122 Ok($Loader {
123 iterator: Box::new(paths.map(|path| {
124 path.map_err($crate::loaders::file::FileLoaderError::GlobError)
125 .map_err(<$Err>::from)
126 })),
127 $(_processor: std::marker::PhantomData::<$P>,)?
128 })
129 }
130
131 #[doc = loader_dir_doc!($dir_kind)]
132 pub fn with_dir(
133 directory: &str,
134 ) -> Result<$Loader<'_, Result<std::path::PathBuf, $Err> $(, $P)?>, $Err> {
135 let entries = std::fs::read_dir(directory)
136 .map_err($crate::loaders::file::FileLoaderError::IoError)
137 .map_err(<$Err>::from)?;
138 Ok($Loader {
139 iterator: Box::new(loader_dir_entries!($dir_kind, entries, $Err)),
140 $(_processor: std::marker::PhantomData::<$P>,)?
141 })
142 }
143 }
144 };
145}
146
147macro_rules! loader_from_bytes {
149 ($Loader:ident) => {
150 impl<'a> $Loader<'a, Vec<u8>> {
151 pub fn from_bytes(bytes: Vec<u8>) -> $Loader<'a, Vec<u8>> {
153 $Loader {
154 iterator: Box::new(vec![bytes].into_iter()),
155 }
156 }
157
158 pub fn from_bytes_multi(bytes_vec: Vec<Vec<u8>>) -> $Loader<'a, Vec<u8>> {
160 $Loader {
161 iterator: Box::new(bytes_vec.into_iter()),
162 }
163 }
164 }
165 };
166}
167
168pub mod file;
169
170pub use file::FileLoader;
171
172#[cfg(all(test, any(feature = "pdf", feature = "epub")))]
175mod test_fixtures;
176
177#[cfg(feature = "pdf")]
178#[cfg_attr(docsrs, doc(cfg(feature = "pdf")))]
179pub mod pdf;
180
181#[cfg(feature = "pdf")]
182pub use pdf::PdfFileLoader;
183
184#[cfg(feature = "epub")]
185#[cfg_attr(docsrs, doc(cfg(feature = "epub")))]
186pub mod epub;
187
188#[cfg(feature = "epub")]
189pub use epub::{EpubFileLoader, RawTextProcessor, StripXmlProcessor, TextProcessor};