vahanafs/src/fs/stackable/mod.rs

118 lines
2.7 KiB
Rust

pub mod fuse_overlay;
pub mod overlay;
use std::convert::Infallible;
use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::slice::Iter;
use std::str::FromStr;
use crate::macros::impl_deref;
use super::mount::DelimitedList;
use super::Mountpoint;
#[derive(Clone, Debug, Default)]
pub struct DirIter<'a> {
inner: Iter<'a, PathBuf>,
}
impl<'a> Iterator for DirIter<'a> {
type Item = &'a Path;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(PathBuf::as_path)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct LowerDirs(Vec<PathBuf>);
impl_deref!(LowerDirs(Vec<PathBuf>));
impl<A: Into<PathBuf>> FromIterator<A> for LowerDirs {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
Self(iter.into_iter().map(Into::into).collect())
}
}
impl<'a> IntoIterator for &'a LowerDirs {
type Item = &'a Path;
type IntoIter = DirIter<'a>;
fn into_iter(self) -> Self::IntoIter {
DirIter {
inner: self.as_slice().iter(),
}
}
}
impl Display for LowerDirs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut iter = self.0.iter();
if let Some(head) = iter.next() {
write!(f, "{}", head.to_string_lossy())?;
for item in iter {
write!(f, ":{}", item.to_string_lossy())?;
}
}
Ok(())
}
}
impl FromStr for LowerDirs {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(
s.split(':')
.filter(|s| !s.is_empty())
.map(Into::into)
.collect(),
))
}
}
#[derive(Debug)]
pub struct StackFs<const D: char, T> {
mountpoint: PathBuf,
options: DelimitedList<D, T>,
}
impl<const D: char, T> StackFs<D, T> {
pub fn new(target: impl Into<PathBuf>) -> Self {
Self {
mountpoint: target.into(),
options: Default::default(),
}
}
pub fn push_option(&mut self, value: T) {
self.options.push(value);
}
pub fn extend_options(&mut self, iter: impl IntoIterator<Item = T>) {
self.options.extend(iter);
}
pub fn find_option<'a, R, F>(&'a self, f: F) -> Option<R>
where
F: Fn(&'a T) -> Option<R>,
{
self.options.iter().filter_map(f).take(1).next()
}
}
impl<const D: char, T: Display> Mountpoint for StackFs<D, T> {
fn options(&self) -> impl Iterator<Item = impl Display> {
self.options.iter()
}
}
pub trait Stack {
fn lower_dirs(&self) -> impl Iterator<Item = &Path>;
fn upper_dir(&self) -> Option<&Path>;
fn work_dir(&self) -> Option<&Path>;
}