weavatrix-scan 0.4.6

Deterministic, safe repository scanner for code intelligence
Documentation
use super::*;

pub(crate) fn inspect(mut scanned: ScannedFile, options: &ScanOptions) -> io::Result<Inspection> {
    let mut file = File::open(&scanned.absolute)?;
    let before = snapshot(&file)?;
    if before.bytes != scanned.bytes || !reusable(&scanned.version, &before.version) {
        return Ok(Inspection::Concurrent(scanned.relative));
    }
    if before.bytes > options.max_file_bytes {
        return Ok(Inspection::Concurrent(scanned.relative));
    }

    let mut hasher = options.hash_file_contents.then(FingerprintHasher::new);
    let mut fingerprint = options.hash_file_contents.then(ContentFingerprint::new);
    let reads_entire_file = hasher.is_some();
    let mut binary = false;
    let mut bytes_read = 0_u64;
    let mut buffer = vec![0_u8; 64 * 1024].into_boxed_slice();
    loop {
        let read = file.read(&mut buffer)?;
        if read == 0 {
            break;
        }
        bytes_read = bytes_read.saturating_add(read as u64);
        if options.detect_binary_files && buffer[..read].contains(&0) {
            binary = true;
        }
        if let Some(hasher) = hasher.as_mut() {
            hasher.write(&buffer[..read]);
        } else if bytes_read >= 8 * 1024 {
            break;
        }
        if let Some(fingerprint) = fingerprint.as_mut() {
            fingerprint.write(&buffer[..read]);
        }
    }

    let after = if options.content_validation == ContentValidationPolicy::Strict {
        Some(snapshot(&file)?)
    } else {
        None
    };
    if (reads_entire_file && bytes_read != before.bytes)
        || after.as_ref().is_some_and(|after| {
            before.bytes != after.bytes || !reusable(&before.version, &after.version)
        })
    {
        return Ok(Inspection::Concurrent(scanned.relative));
    }
    if binary {
        return Ok(Inspection::Binary(scanned.relative));
    }
    scanned.version = after.map_or(before.version, |after| after.version);
    scanned.binary_checked = options.detect_binary_files;
    scanned.content_hash = hasher.map(FingerprintHasher::finish);
    scanned.content_fingerprint = fingerprint.map(ContentFingerprint::finish);
    Ok(Inspection::Selected(scanned))
}