1use std::{
7 fs,
8 io::Read,
9 path::{Path, PathBuf},
10 str::FromStr,
11};
12use tectonic_errors::prelude::*;
13use tectonic_io_base::{digest, filesystem::FilesystemIo, InputHandle, IoProvider, OpenResult};
14use tectonic_status_base::{NoopStatusBackend, StatusBackend};
15
16use super::Bundle;
17
18pub struct DirBundle(FilesystemIo);
26
27impl DirBundle {
28 pub fn new<P: AsRef<Path>>(dir: P) -> DirBundle {
33 DirBundle(FilesystemIo::new(
34 dir.as_ref(),
35 false, false, Default::default(), ))
39 }
40}
41
42impl IoProvider for DirBundle {
43 fn input_open_name(
44 &mut self,
45 name: &str,
46 status: &mut dyn StatusBackend,
47 ) -> OpenResult<InputHandle> {
48 self.0.input_open_name(name, status)
49 }
50
51 fn input_open_name_with_abspath(
52 &mut self,
53 name: &str,
54 status: &mut dyn StatusBackend,
55 ) -> OpenResult<(InputHandle, Option<PathBuf>)> {
56 self.0.input_open_name_with_abspath(name, status)
57 }
58}
59
60impl Bundle for DirBundle {
61 fn all_files(&self) -> Vec<String> {
62 fs::read_dir(self.0.root())
63 .unwrap()
64 .filter_map(|x| x.ok())
65 .filter(|x| !x.file_type().map(|x| x.is_dir()).unwrap_or(false))
66 .map(|x| x.file_name().to_str().unwrap_or("").to_owned())
67 .filter(|x| !x.is_empty())
68 .collect()
69 }
70
71 fn get_digest(&mut self) -> Result<tectonic_io_base::digest::DigestData> {
72 let digest_text = match self.input_open_name(digest::DIGEST_NAME, &mut NoopStatusBackend {})
73 {
74 OpenResult::Ok(h) => {
75 let mut text = String::new();
76 h.take(64).read_to_string(&mut text)?;
77 text
78 }
79
80 OpenResult::NotAvailable => {
81 bail!("bundle does not provide needed SHA256SUM file");
82 }
83
84 OpenResult::Err(e) => {
85 return Err(e);
86 }
87 };
88
89 Ok(atry!(digest::DigestData::from_str(&digest_text); ["corrupted SHA256 digest data"]))
90 }
91}