use std::fmt; use tracing::instrument; use crate::vfs::ToDynDir; use super::{entries, Dir, DynDir, Entries, Query, VPath, VPathBuf}; pub struct Overlay { base: DynDir, overlay: DynDir, } impl Overlay { pub fn new(base: DynDir, overlay: DynDir) -> Self { Self { base, overlay } } #[instrument("Overlay::dir", skip(self))] fn dir(&self, path: &VPath) -> Vec { let mut dir = entries(&self.base, path); dir.append(&mut entries(&self.overlay, path)); dir.sort(); dir.dedup(); dir } } impl Dir for Overlay { fn query(&self, path: &VPath, query: &mut Query) { query.provide(|| Entries(self.dir(path))); self.overlay.query(path, query); self.base.query(path, query); } } impl fmt::Debug for Overlay { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Overlay({:?}, {:?})", self.base, self.overlay) } } pub fn layered_dir(layers: &[DynDir]) -> DynDir { match layers { [] => ().to_dyn(), [dir] => dir.clone(), [left, right] => Overlay::new(left.clone(), right.clone()).to_dyn(), [left, right, rest @ ..] => { let mut overlay = Overlay::new(left.clone(), right.clone()); for dir in rest { overlay = Overlay::new(overlay.to_dyn(), dir.clone()); } overlay.to_dyn() } } }