use crate::error::Result;
use crate::ole::clsid;
use crate::ole::container::OleFile;
#[derive(Debug, Clone)]
pub struct DirectoryEntry {
pub path: String,
pub entry_type: EntryType,
pub size: u64,
pub clsid: Option<String>,
pub clsid_description: Option<&'static str>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EntryType {
RootEntry,
Storage,
Stream,
}
impl std::fmt::Display for EntryType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
EntryType::RootEntry => write!(f, "Root Entry"),
EntryType::Storage => write!(f, "Storage"),
EntryType::Stream => write!(f, "Stream"),
}
}
}
pub fn list_directory(ole: &OleFile) -> Result<Vec<DirectoryEntry>> {
let entries = ole.list_entries();
let mut result = Vec::with_capacity(entries.len() + 1);
let root_clsid = ole.root_clsid();
let root_clsid_str = if root_clsid.is_nil() {
None
} else {
Some(root_clsid.to_string())
};
let root_desc = clsid::lookup_clsid(&root_clsid);
result.push(DirectoryEntry {
path: "/".to_string(),
entry_type: EntryType::RootEntry,
size: 0,
clsid: root_clsid_str,
clsid_description: root_desc,
});
for entry in entries {
let entry_type = if entry.is_stream {
EntryType::Stream
} else {
EntryType::Storage
};
let clsid_str = if entry.clsid.is_nil() {
None
} else {
Some(entry.clsid.to_string())
};
let clsid_desc = if entry.clsid.is_nil() {
None
} else {
clsid::lookup_clsid(&entry.clsid)
};
result.push(DirectoryEntry {
path: entry.path,
entry_type,
size: entry.size,
clsid: clsid_str,
clsid_description: clsid_desc,
});
}
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_entry_type_display() {
assert_eq!(EntryType::RootEntry.to_string(), "Root Entry");
assert_eq!(EntryType::Storage.to_string(), "Storage");
assert_eq!(EntryType::Stream.to_string(), "Stream");
}
}