1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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(())
}
}
|