use std::path::PathBuf;
use crate::encryption::EncryptionScheme;
use crate::fs::{FileId, FsKind, StreamId};
use crate::registry::ContainerFormat;
use crate::volume::VolumeScheme;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Guid(pub [u8; 16]);
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SnapshotRef {
VssStore(usize),
ApfsXid(u64),
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum NodeAddr {
Path(Vec<Vec<u8>>),
File(FileId),
Both { path: Vec<Vec<u8>>, id: FileId },
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Layer {
File { path: PathBuf },
Range { start: u64, len: u64 },
Container { format: ContainerFormat },
Volume {
scheme: VolumeScheme,
index: usize,
guid: Option<Guid>,
},
Encryption { scheme: EncryptionScheme },
Snapshot { store: SnapshotRef },
Fs { kind: FsKind, at: NodeAddr },
Stream { id: StreamId },
Archive { member: Option<usize> },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Locator {
pub layer: Layer,
pub parent: Option<Box<Locator>>,
}
impl Locator {
#[must_use]
pub fn file(path: impl Into<PathBuf>) -> Self {
Self {
layer: Layer::File { path: path.into() },
parent: None,
}
}
#[deprecated(note = "renamed to file()")]
#[must_use]
pub fn os(path: impl Into<PathBuf>) -> Self {
Self::file(path)
}
#[must_use]
pub fn root(layer: Layer) -> Self {
Self {
layer,
parent: None,
}
}
#[must_use]
pub fn push(self, layer: Layer) -> Self {
Self {
layer,
parent: Some(Box::new(self)),
}
}
#[must_use]
pub fn depth(&self) -> usize {
1 + self.parent.as_ref().map_or(0, |p| p.depth())
}
#[must_use]
pub fn base(&self) -> &Locator {
match &self.parent {
Some(p) => p.base(),
None => self,
}
}
#[must_use]
pub fn layers(&self) -> Vec<&Layer> {
let mut out = match &self.parent {
Some(p) => p.layers(),
None => Vec::new(),
};
out.push(&self.layer);
out
}
}
#[cfg(test)]
mod tests {
use super::{Layer, Locator};
#[test]
#[allow(deprecated)]
fn deprecated_os_alias_matches_file() {
let via_os = Locator::os("/evidence/DC01.E01");
assert_eq!(via_os, Locator::file("/evidence/DC01.E01"));
assert!(matches!(via_os.layer, Layer::File { .. }));
}
}