diff options
author | Daniel Schadt <kingdread@gmx.de> | 2023-01-17 23:06:54 +0100 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2023-01-17 23:06:54 +0100 |
commit | 160aba6258e1979ef85d66b2c27c33f6f28a7e38 (patch) | |
tree | 265f061f4b256a9dffac3abeb8bf283e1bc75c55 /src/storage.rs | |
parent | f824bef0e78e51c985c2333c400c6741782db2d0 (diff) | |
download | hittekaart-160aba6258e1979ef85d66b2c27c33f6f28a7e38.tar.gz hittekaart-160aba6258e1979ef85d66b2c27c33f6f28a7e38.tar.bz2 hittekaart-160aba6258e1979ef85d66b2c27c33f6f28a7e38.zip |
factor out saving logic
Since we want to support SQLite at some point, it makes sense to have
the exact storage method abstracted away.
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(()) + } +} |