1
0
Fork 0
mirror of https://git.sr.ht/~adnano/kiln synced 2024-05-24 18:16:04 +02:00
kiln/src/index.rs
2019-05-18 14:00:12 -04:00

95 lines
2.3 KiB
Rust

use std::path::{Path, PathBuf};
use std::{env, fs, ops, slice};
use std::io::Result;
#[derive(Default)]
pub struct Index(Vec<(PathBuf, Vec<u8>)>);
impl Index {
pub fn from(dir: impl AsRef<Path>) -> Result<Index> {
let input = dir.as_ref();
let output = Path::new("");
let mut index = Index::default();
IndexDir::new(input, output, &mut index).index()?;
Ok(index)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn insert(&mut self, key: PathBuf, val: Vec<u8>) {
self.0.push((key, val));
}
pub fn remove(&mut self, index: usize) {
self.0.remove(index);
}
pub fn iter_mut(&mut self) -> slice::IterMut<(PathBuf, Vec<u8>)> {
self.0.iter_mut()
}
pub fn write(&self, output: impl AsRef<Path>) -> Result<()> {
let output = output.as_ref();
if output.exists() {
// empty the output directory
fs::remove_dir_all(output)?;
}
fs::create_dir_all(output)?;
env::set_current_dir(output)?;
for (path, contents) in &self.0 {
if let Some(parent) = path.parent() {
fs::create_dir_all(&parent)?;
}
fs::write(&path, &contents)?;
}
Ok(())
}
}
impl ops::Index<usize> for Index {
type Output = (PathBuf, Vec<u8>);
fn index(&self, i: usize) -> &(PathBuf, Vec<u8>) {
&self.0[i]
}
}
impl ops::IndexMut<usize> for Index {
fn index_mut(&mut self, i: usize) -> &mut (PathBuf, Vec<u8>) {
&mut self.0[i]
}
}
struct IndexDir<'a> {
input: &'a Path,
output: &'a Path,
index: &'a mut Index,
}
impl<'a> IndexDir<'a> {
fn new(input: &'a Path, output: &'a Path, index: &'a mut Index) -> IndexDir<'a> {
IndexDir {
input,
output,
index,
}
}
fn index(self) -> Result<()> {
for entry in fs::read_dir(self.input)? {
let path = entry?.path();
let mut output = self.output.to_path_buf();
output.push(path.file_name().unwrap());
if path.is_file() {
let contents = fs::read(&path)?;
self.index.insert(output, contents);
} else if path.is_dir() {
IndexDir::new(&path, &output, self.index).index()?;
}
}
Ok(())
}
}