diff options
Diffstat (limited to 'src/storage.rs')
-rw-r--r-- | src/storage.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/storage.rs b/src/storage.rs new file mode 100644 index 0000000..fef8194 --- /dev/null +++ b/src/storage.rs @@ -0,0 +1,67 @@ +use color_eyre::{eyre::{bail, WrapErr}, Result}; +use std::{ + fs, + io::ErrorKind, + path::{Path, PathBuf}, +}; + +pub trait Storage { + fn prepare(&mut self) -> Result<()>; + fn prepare_zoom(&mut self, zoom: u32) -> Result<()>; + fn store(&mut self, zoom: u32, x: u64, y: u64, data: &[u8]) -> Result<()>; + fn finish(&mut self) -> Result<()>; +} + +#[derive(Debug)] +pub struct Folder { + base_dir: PathBuf, +} + +impl Folder { + pub fn new(base_dir: PathBuf) -> Self { + Folder { base_dir } + } +} + +impl Storage for Folder { + fn prepare(&mut self) -> Result<()> { + let path = &self.base_dir; + let metadata = fs::metadata(path); + match metadata { + Err(e) if e.kind() == ErrorKind::NotFound => { + let parent = path.parent().unwrap_or_else(|| Path::new("/")); + fs::create_dir(path) + .context(format!("Could not create output directory at {parent:?}"))? + } + Err(e) => Err(e).context("Error while checking output directory")?, + Ok(m) if m.is_dir() => (), + Ok(_) => bail!("Output directory is not a directory"), + } + Ok(()) + } + + fn prepare_zoom(&mut self, zoom: u32) -> Result<()> { + let target = [&self.base_dir, &zoom.to_string().into()] + .iter() + .collect::<PathBuf>(); + fs::create_dir(target)?; + Ok(()) + } + + fn store(&mut self, zoom: u32, x: u64, y: u64, data: &[u8]) -> Result<()> { + let folder = self.base_dir.join(zoom.to_string()).join(x.to_string()); + let metadata = folder.metadata(); + match metadata { + Err(_) => fs::create_dir(&folder)?, + Ok(m) if !m.is_dir() => bail!("Output path is not a directory"), + _ => {} + } + let file = folder.join(format!("{y}.png")); + fs::write(file, data)?; + Ok(()) + } + + fn finish(&mut self) -> Result<()> { + Ok(()) + } +} |