#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
mod engine;
mod registry;
pub use engine::{sweep, CarveOptions, Region, RegionSource, SweptItem};
pub use registry::{registered_carvers, CarverRegistration};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RecoveryMethod {
Tombstone,
FileInternalCarve,
UnallocatedCarve,
MemoryCarve,
}
impl RecoveryMethod {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
RecoveryMethod::Tombstone => "tombstone",
RecoveryMethod::FileInternalCarve => "file-internal-carve",
RecoveryMethod::UnallocatedCarve => "unallocated-carve",
RecoveryMethod::MemoryCarve => "memory-carve",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct Signature {
magic: &'static [u8],
offset: usize,
}
impl Signature {
#[must_use]
pub const fn new(magic: &'static [u8], offset: usize) -> Self {
Self { magic, offset }
}
#[must_use]
pub const fn magic(&self) -> &'static [u8] {
self.magic
}
#[must_use]
pub const fn offset(&self) -> usize {
self.offset
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ConfidencePolicy {
KeepAll,
Minimum(f32),
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub struct CarveContext {
base_offset: u64,
policy: ConfidencePolicy,
method: RecoveryMethod,
}
impl CarveContext {
#[must_use]
pub const fn at(base_offset: u64) -> Self {
Self {
base_offset,
policy: ConfidencePolicy::KeepAll,
method: RecoveryMethod::UnallocatedCarve,
}
}
#[must_use]
pub const fn with_policy(mut self, policy: ConfidencePolicy) -> Self {
self.policy = policy;
self
}
#[must_use]
pub const fn with_method(mut self, method: RecoveryMethod) -> Self {
self.method = method;
self
}
#[must_use]
pub const fn recovery_method(&self) -> RecoveryMethod {
self.method
}
#[must_use]
pub const fn base_offset(&self) -> u64 {
self.base_offset
}
#[must_use]
pub const fn policy(&self) -> ConfidencePolicy {
self.policy
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CarvedPayload {
Records,
ArtifactBytes(Vec<u8>),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct CarvedItem {
format: &'static str,
image_offset: u64,
confidence: f32,
method: RecoveryMethod,
payload: CarvedPayload,
}
impl CarvedItem {
#[must_use]
pub fn records(
format: &'static str,
image_offset: u64,
confidence: f32,
method: RecoveryMethod,
) -> Self {
Self {
format,
image_offset,
confidence,
method,
payload: CarvedPayload::Records,
}
}
#[must_use]
pub fn artifact_bytes(
format: &'static str,
image_offset: u64,
confidence: f32,
method: RecoveryMethod,
bytes: Vec<u8>,
) -> Self {
Self {
format,
image_offset,
confidence,
method,
payload: CarvedPayload::ArtifactBytes(bytes),
}
}
#[must_use]
pub const fn format(&self) -> &'static str {
self.format
}
#[must_use]
pub const fn image_offset(&self) -> u64 {
self.image_offset
}
#[must_use]
pub const fn confidence(&self) -> f32 {
self.confidence
}
#[must_use]
pub const fn recovery_method(&self) -> RecoveryMethod {
self.method
}
#[must_use]
pub const fn payload(&self) -> &CarvedPayload {
&self.payload
}
}
pub trait Carver: Send + Sync {
fn format(&self) -> &'static str;
fn signatures(&self) -> &[Signature];
fn max_window(&self) -> u64;
fn carve(&self, window: &[u8], ctx: &CarveContext) -> Vec<CarvedItem>;
}