use std::collections::BTreeMap;
use littlefs2_core::{path, DynFilesystem, FileType, Path};
#[derive(Debug, PartialEq)]
pub enum Entry {
File,
EmptyDir,
}
#[derive(Debug, Default, PartialEq)]
pub struct Entries(pub BTreeMap<String, Entry>);
impl Entries {
pub fn remove_standard(&mut self) {
self.remove_file("fido/sec/00");
self.remove_file("fido/x5c/00");
self.remove_file("trussed/dat/rng-state.bin");
}
pub fn remove_state(&mut self) {
self.remove_file("fido/dat/persistent-state.cbor");
}
pub fn try_remove_state(&mut self) {
self.0.remove("fido/dat/persistent-state.cbor");
}
pub fn try_remove_keys(&mut self) -> usize {
self.try_remove_dir("fido/sec")
}
pub fn try_remove_rks(&mut self) -> usize {
self.try_remove_dir("fido/dat/rk")
}
pub fn try_remove_dir(&mut self, dir: &str) -> usize {
let n = self.0.len();
self.0.retain(|path, _| {
let (start, _) = path.rsplit_once('/').unwrap();
start != dir
});
n - self.0.len()
}
pub fn remove_file(&mut self, path: &str) {
let entry = self.0.remove(path);
assert_eq!(entry, Some(Entry::File), "{path}");
}
pub fn remove_empty_dir(&mut self, path: &str) {
let entry = self.0.remove(path);
assert_eq!(entry, Some(Entry::EmptyDir), "{path}");
}
pub fn assert_empty(&self) {
assert_eq!(self.0, Default::default());
}
}
pub fn list_fs(fs: &dyn DynFilesystem) -> Entries {
fn list_dir(fs: &dyn DynFilesystem, dir: &Path, files: &mut BTreeMap<String, Entry>) -> usize {
fs.read_dir_and_then(dir, &mut |iter| {
let mut child_count = 0;
for entry in iter {
let entry = entry.unwrap();
if entry.file_name().as_str() == "." || entry.file_name().as_str() == ".." {
continue;
}
child_count += 1;
match entry.file_type() {
FileType::File => {
files.insert(entry.path().as_str().to_owned(), Entry::File);
}
FileType::Dir => {
let n = list_dir(fs, entry.path(), files);
if n == 0 {
files.insert(entry.path().as_str().to_owned(), Entry::EmptyDir);
}
}
}
}
Ok(child_count)
})
.unwrap()
}
let mut entries = BTreeMap::new();
list_dir(fs, path!(""), &mut entries);
Entries(entries)
}