sunfish 0.7.3

Web Application Build Tool
Documentation
use std::{
	borrow::Cow,
	collections::BTreeMap,
	path::{Path, PathBuf},
};

pub enum IncludeDir {
	Fs(FsDirectory),
	Included(IncludedDirectory),
}

pub enum FsOrIncludedFile {
	Fs(FsFile),
	Included(IncludedFile),
}

impl IncludeDir {
	pub fn read(&self, path: &Path) -> Option<FsOrIncludedFile> {
		match self {
			IncludeDir::Fs(s) => s.read(path),
			IncludeDir::Included(s) => s.read(path),
		}
	}
}

impl IntoIterator for IncludeDir {
	type Item = (PathBuf, FsOrIncludedFile);
	type IntoIter = FsOrIncludedIntoIter;
	fn into_iter(self) -> Self::IntoIter {
		match self {
			IncludeDir::Fs(fs) => FsOrIncludedIntoIter::Fs(
				walkdir::WalkDir::new(fs.0).sort_by_file_name().into_iter(),
			),
			IncludeDir::Included(embedded) => {
				FsOrIncludedIntoIter::Included(embedded.0.into_iter())
			}
		}
	}
}

pub enum FsOrIncludedIntoIter {
	Fs(walkdir::IntoIter),
	Included(std::collections::btree_map::IntoIter<&'static Path, IncludedFile>),
}

impl Iterator for FsOrIncludedIntoIter {
	type Item = (PathBuf, FsOrIncludedFile);
	fn next(&mut self) -> Option<Self::Item> {
		match self {
			FsOrIncludedIntoIter::Fs(walkdir) => loop {
				let entry = match walkdir.next() {
					None => return None,
					Some(Err(e)) => panic!("{}", e),
					Some(Ok(entry)) => entry,
				};
				if entry.file_type().is_file() {
					let path = entry.path().to_owned();
					return Some((path.clone(), FsOrIncludedFile::Fs(FsFile(path))));
				} else {
					continue;
				}
			},
			FsOrIncludedIntoIter::Included(map) => map
				.next()
				.map(|(path, file)| (path.to_owned(), FsOrIncludedFile::Included(file))),
		}
	}
}

impl FsOrIncludedFile {
	pub fn data(&self) -> Cow<'static, [u8]> {
		match self {
			FsOrIncludedFile::Fs(s) => s.data(),
			FsOrIncludedFile::Included(s) => s.data(),
		}
	}

	pub fn hash(&self) -> Option<&'static str> {
		match self {
			FsOrIncludedFile::Fs(s) => s.hash(),
			FsOrIncludedFile::Included(s) => s.hash(),
		}
	}
}

pub struct FsDirectory(pub PathBuf);

impl FsDirectory {
	pub fn read(&self, path: &Path) -> Option<FsOrIncludedFile> {
		let path = self.0.join(path);
		if path.exists() {
			Some(FsOrIncludedFile::Fs(FsFile(path)))
		} else {
			None
		}
	}
}

pub struct FsFile(pub PathBuf);

impl FsFile {
	pub fn data(&self) -> Cow<'static, [u8]> {
		Cow::Owned(std::fs::read(&self.0).unwrap())
	}

	pub fn hash(&self) -> Option<&'static str> {
		None
	}
}

#[derive(Debug)]
pub struct IncludedDirectory(pub BTreeMap<&'static Path, IncludedFile>);

#[derive(Clone, Debug)]
pub struct IncludedFile {
	pub data: &'static [u8],
	pub hash: &'static str,
}

impl IncludedDirectory {
	pub fn read(&self, path: &Path) -> Option<FsOrIncludedFile> {
		self.0
			.get(path)
			.map(|file| FsOrIncludedFile::Included(file.clone()))
	}
}

impl IncludedFile {
	pub fn data(&self) -> Cow<'static, [u8]> {
		Cow::Borrowed(self.data)
	}

	pub fn hash(&self) -> Option<&'static str> {
		Some(self.hash)
	}
}