easyofd_reader/
ofd_reader_facade.rs1use std::io::{Read, Seek};
10
11use easyofd_core::{OfdPage, OfdResult};
12
13use crate::OfdReader;
14use crate::page_info::PageInfo;
15use crate::read_options::ReadOptions;
16use crate::resource_locator::ResourceLocator;
17use crate::resource_manage::ResourceManage;
18
19pub struct OfdReaderFacade {
40 reader: OfdReader,
42 locator: ResourceLocator,
44 resource_manage: Option<ResourceManage>,
46}
47
48impl std::fmt::Debug for OfdReaderFacade {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 f.debug_struct("OfdReaderFacade")
51 .field("page_count", &self.reader.page_count())
52 .field("locator", &self.locator)
53 .field("resource_manage", &self.resource_manage.is_some())
54 .finish()
55 }
56}
57
58impl OfdReaderFacade {
59 pub fn open(path: impl AsRef<std::path::Path>) -> OfdResult<Self> {
67 let reader = OfdReader::open(path)?;
68 Ok(Self::from_reader(reader))
69 }
70
71 pub fn from_bytes(data: &[u8]) -> OfdResult<Self> {
79 let reader = OfdReader::from_bytes(data)?;
80 Ok(Self::from_reader(reader))
81 }
82
83 #[must_use]
85 pub fn from_reader(reader: OfdReader) -> Self {
86 Self {
87 reader,
88 locator: ResourceLocator::new(),
89 resource_manage: None,
90 }
91 }
92
93 pub fn from_seek<R: Read + Seek>(source: R, options: ReadOptions) -> OfdResult<Self> {
99 let reader = OfdReader::from_seek(source, options)?;
100 Ok(Self::from_reader(reader))
101 }
102
103 #[must_use]
105 pub fn reader(&self) -> &OfdReader {
106 &self.reader
107 }
108
109 #[must_use]
113 pub fn resource_locator(&self) -> &ResourceLocator {
114 &self.locator
115 }
116
117 #[must_use]
119 pub fn resource_locator_mut(&mut self) -> &mut ResourceLocator {
120 &mut self.locator
121 }
122
123 #[must_use]
127 pub fn page_count(&self) -> usize {
128 self.reader.page_count()
129 }
130
131 #[must_use]
133 pub fn pages(&self) -> &[OfdPage] {
134 self.reader.pages()
135 }
136
137 #[must_use]
143 pub fn get_page_info(&self, page_num: usize) -> Option<PageInfo> {
144 if page_num == 0 || page_num > self.reader.page_count() {
145 return None;
146 }
147 let page = &self.reader.pages()[page_num - 1];
148 let size = easyofd_core::ST_Box::new(0.0, 0.0, page.width, page.height);
149 let mut info = PageInfo::new(page_num, size);
150 info.page_n = page_num.saturating_sub(1);
151 Some(info)
152 }
153
154 #[must_use]
158 pub fn get_page_list(&self) -> Vec<PageInfo> {
159 (1..=self.page_count())
160 .filter_map(|i| self.get_page_info(i))
161 .collect()
162 }
163
164 #[must_use]
166 pub fn metadata(&self) -> &easyofd_core::OfdMetadata {
167 self.reader.metadata()
168 }
169
170 #[must_use]
172 pub fn extract_text(&self) -> Vec<String> {
173 self.reader.extract_text()
174 }
175
176 #[must_use]
178 pub fn extract_all_text(&self) -> String {
179 self.reader.extract_all_text()
180 }
181
182 #[must_use]
186 pub fn resource_manage(&self) -> Option<&ResourceManage> {
187 self.resource_manage.as_ref()
188 }
189
190 pub fn set_resource_manage(&mut self, mgr: ResourceManage) {
192 self.resource_manage = Some(mgr);
193 }
194
195 #[must_use]
199 pub fn has_signature(&self) -> bool {
200 self.reader.metadata().signatures_path.is_some()
201 }
202
203 #[must_use]
205 pub fn raw_entries(&self) -> &[(String, Vec<u8>)] {
206 self.reader.raw_entries()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use easyofd_core::{OfdPage, TextObject};
214 use easyofd_writer::OfdWriter;
215
216 fn build_test_ofd() -> Vec<u8> {
217 let mut writer = OfdWriter::new();
218 let mut page = OfdPage::new(210.0, 297.0);
219 page.add_text(TextObject::new(10.0, 20.0, "Facade Test"));
220 writer.add_page(page);
221 writer.build().unwrap()
222 }
223
224 #[test]
225 fn test_facade_from_bytes() {
226 let bytes = build_test_ofd();
227 let facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
228 assert_eq!(facade.page_count(), 1);
229 assert!(!facade.has_signature());
230 }
231
232 #[test]
233 fn test_facade_from_reader() {
234 let bytes = build_test_ofd();
235 let reader = OfdReader::from_bytes(&bytes).unwrap();
236 let facade = OfdReaderFacade::from_reader(reader);
237 assert_eq!(facade.page_count(), 1);
238 }
239
240 #[test]
241 fn test_facade_get_page_info() {
242 let bytes = build_test_ofd();
243 let facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
244 let info = facade.get_page_info(1).unwrap();
245 assert_eq!(info.index, 1);
246 assert!((info.width() - 210.0).abs() < f64::EPSILON);
247 }
248
249 #[test]
250 fn test_facade_get_page_info_out_of_range() {
251 let bytes = build_test_ofd();
252 let facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
253 assert!(facade.get_page_info(0).is_none());
254 assert!(facade.get_page_info(2).is_none());
255 }
256
257 #[test]
258 fn test_facade_get_page_list() {
259 let bytes = build_test_ofd();
260 let facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
261 let list = facade.get_page_list();
262 assert_eq!(list.len(), 1);
263 }
264
265 #[test]
266 fn test_facade_extract_text() {
267 let bytes = build_test_ofd();
268 let facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
269 let texts = facade.extract_text();
270 assert!(!texts.is_empty());
271 assert!(texts[0].contains("Facade Test"));
272 }
273
274 #[test]
275 fn test_facade_resource_locator() {
276 let bytes = build_test_ofd();
277 let mut facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
278 facade.resource_locator_mut().cd("/Doc_0").unwrap();
279 assert_eq!(facade.resource_locator().pwd(), "/Doc_0");
280 }
281
282 #[test]
283 fn test_facade_resource_manage() {
284 let bytes = build_test_ofd();
285 let mut facade = OfdReaderFacade::from_bytes(&bytes).unwrap();
286 assert!(facade.resource_manage().is_none());
287 facade.set_resource_manage(ResourceManage::new());
288 assert!(facade.resource_manage().is_some());
289 }
290}