118 lines
2.7 KiB
Rust
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>;
|
|
}
|