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.inner.next().map(PathBuf::as_path) } } #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct LowerDirs(Vec); impl_deref!(LowerDirs(Vec)); impl> FromIterator for LowerDirs { fn from_iter>(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 { Ok(Self( s.split(':') .filter(|s| !s.is_empty()) .map(Into::into) .collect(), )) } } #[derive(Debug)] pub struct StackFs { mountpoint: PathBuf, options: DelimitedList, } impl StackFs { pub fn new(target: impl Into) -> 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) { self.options.extend(iter); } pub fn find_option<'a, R, F>(&'a self, f: F) -> Option where F: Fn(&'a T) -> Option, { self.options.iter().filter_map(f).take(1).next() } } impl Mountpoint for StackFs { fn options(&self) -> impl Iterator { self.options.iter() } } pub trait Stack { fn lower_dirs(&self) -> impl Iterator; fn upper_dir(&self) -> Option<&Path>; fn work_dir(&self) -> Option<&Path>; }