blazehash 0.2.4

Forensic file hasher — hashdeep for the modern era, BLAKE3 by default
Documentation
use anyhow::Result;
use std::collections::HashSet;
use std::path::{Path, PathBuf};

#[derive(Debug, Default)]
pub struct ResumeState {
    completed: HashSet<PathBuf>,
}

impl ResumeState {
    pub fn new() -> Self {
        Self {
            completed: HashSet::new(),
        }
    }

    pub fn from_manifest(content: &str) -> Result<Self> {
        let mut completed = HashSet::new();

        for line in content.lines() {
            if line.starts_with("%%%%") || line.starts_with('#') || line.is_empty() {
                continue;
            }
            // The filename is everything after the last expected comma-separated field.
            // For simplicity in resume, we use rfind to get the last comma and take the rest.
            if let Some(last_comma) = line.rfind(',') {
                let path = &line[last_comma + 1..];
                completed.insert(PathBuf::from(path));
            }
        }

        Ok(Self { completed })
    }

    /// Create resume state from pre-parsed manifest records.
    pub fn from_records(records: &[crate::manifest::ManifestRecord]) -> Self {
        let completed: HashSet<PathBuf> = records.iter().map(|r| r.path.clone()).collect();
        Self { completed }
    }

    pub fn is_done(&self, path: &Path) -> bool {
        self.completed.contains(path)
    }

    pub fn mark_done(&mut self, path: PathBuf) {
        self.completed.insert(path);
    }

    pub fn completed_count(&self) -> usize {
        self.completed.len()
    }
}