diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 27a31a9d..8a59b7e0 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -1,5 +1,6 @@ mod memory_backend; mod noop_backend; +mod snapshot; mod std_backend; use std::io; @@ -8,6 +9,7 @@ use std::sync::{Arc, Mutex}; pub use memory_backend::MemoryBackend; pub use noop_backend::NoopBackend; +pub use snapshot::VfsSnapshot; pub use std_backend::StdBackend; mod sealed { diff --git a/vfs/src/memory_backend.rs b/vfs/src/memory_backend.rs index d16cdd04..4fe27269 100644 --- a/vfs/src/memory_backend.rs +++ b/vfs/src/memory_backend.rs @@ -1,16 +1,71 @@ +use std::collections::{BTreeSet, HashMap}; use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; -use crate::{Metadata, ReadDir, VfsBackend, VfsEvent}; +use crate::{Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; /// `VfsBackend` that reads from an in-memory filesystem. +#[derive(Debug)] #[non_exhaustive] -pub struct MemoryBackend; +pub struct MemoryBackend { + entries: HashMap, + orphans: BTreeSet, +} impl MemoryBackend { pub fn new() -> Self { - Self + Self { + entries: HashMap::new(), + orphans: BTreeSet::new(), + } } + + pub fn load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot) { + let path = path.into(); + + if let Some(parent_path) = path.parent() { + if let Some(parent_entry) = self.entries.get_mut(parent_path) { + if let Entry::Dir { children } = parent_entry { + children.insert(path.clone()); + } else { + panic!( + "Tried to load snapshot as child of file, {}", + parent_path.display() + ); + } + } else { + self.orphans.insert(path.clone()); + } + } else { + self.orphans.insert(path.clone()); + } + + match snapshot { + VfsSnapshot::File { contents } => { + self.entries.insert(path, Entry::File { contents }); + } + VfsSnapshot::Dir { children } => { + self.entries.insert( + path.clone(), + Entry::Dir { + children: BTreeSet::new(), + }, + ); + + for (child_name, child) in children { + let full_path = path.join(child_name); + self.load_snapshot(full_path, child); + } + } + }; + } +} + +#[derive(Debug)] +enum Entry { + File { contents: Vec }, + + Dir { children: BTreeSet }, } impl VfsBackend for MemoryBackend { diff --git a/vfs/src/snapshot.rs b/vfs/src/snapshot.rs new file mode 100644 index 00000000..5ddb9363 --- /dev/null +++ b/vfs/src/snapshot.rs @@ -0,0 +1,29 @@ +use std::collections::BTreeMap; + +#[non_exhaustive] +pub enum VfsSnapshot { + File { + contents: Vec, + }, + + Dir { + children: BTreeMap, + }, +} + +impl VfsSnapshot { + pub fn file>>(contents: C) -> Self { + Self::File { + contents: contents.into(), + } + } + + pub fn dir, I: IntoIterator>(children: I) -> Self { + Self::Dir { + children: children + .into_iter() + .map(|(key, value)| (key.into(), value)) + .collect(), + } + } +}