aboutsummaryrefslogtreecommitdiff
path: root/src/storage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/storage.rs')
-rw-r--r--src/storage.rs67
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(())
+ }
+}