bitbottle 0.10.0

a modern archive file format
Documentation
use hex::encode;
use std::fs::File;
use bitbottle::{HashType, Scanner};

const FRENCH_TOAST_TOTAL: usize = 3376039;

const FRENCH_TOAST_SHA256_20_12: [(usize, &str); 17] = [
    (95196,  "c00262112cae1af08f8ea5f8661353a84be578fdb7672cc81668ad6e2f098160"),
    (155055, "ac4e0647f36d2413ba26d144f296f541e1526712ea93d066745d32fcae373291"),
    (222043, "100552457a83529df80b8fc81bb47acdbdf7f0848ca6d521f5f7e720a052a19d"),
    (120892, "3091d84d1bc9ef5304f20c63d1d9e1e532fa9a6f706419c302823fb60c225d2d"),
    (102780, "28082cfca0bf930a2c732e4acf5c02493b5f95f6059391bff92b3b33151b9fdb"),
    (142438, "099d4fdd009f9b36ff681994b8dbba6637f4036cdc0151b6419f96ec0769ffa3"),
    (275740, "1ac024ce191961bf1643e0cf00b05ddc8c0c1b32025ebd9eeb9f3969e877c32e"),
    (112803, "4228cff989ddcf36dd6258302857a169e2ae12934ab2707f3bf2f6a15b499e17"),
    (344973, "c1f8819e0dcd69212c17e868e78bdb6c1ac4379d46e70fa6939567e6e07999d2"),
    (556260, "8cf6d47eef48320557f1c76ad07a7b642bc144f3b37eb9b5fdaffd8c6628ebc2"),
    (114689, "6abb71c5241a26bbadd8f85714566b0ea782812abe7c2673354c9332527dfa3c"),
    (148823, "293f984262aabd06eb6a15ded10466da790ad2b87d67cdf1e6da6dfb2ea8b182"),
    (172196, "8b48be2d0f435cd055e7faf292c60beb49e348ab72d3a8ff8afad8ed4eb2c623"),
    (195363, "25e9168c1481f4efa925c4497d8391042bb89f33cb79414d62bf826291ead339"),
    (120787, "b542326a0faf5ab4b59f6fa2ba80b7ebe1da4217a7a7f4418fb82f2e86f39dc3"),
    (157259, "d6674cfe8a24b530741ec9efa01d65980de88f3ac5fac361a0a2eeca407a392d"),
    (338742, "9e5fa60805d21ce7aa42d23528a3bfc0c5b01f8885ee391018ac2262199a9070"),
];

const FRENCH_TOAST_BLAKE3_20_12: [(usize, &str); 17] = [
    (95196,  "8142241fe5261ca1877b70da1668da77d436d21219d654645a0771d9af6a99ae"),
    (155055, "9debf83ace6bb4f8c6c443f9eae700e5b5397c09ccf6099055aeccdd85cebb8f"),
    (222043, "267d2b458d0679bac1bb486d8f1073bfa3035ed0684eef4a10e7c163a63b1d63"),
    (120892, "eec02f44bab332989df57285646eb3d8c0c5feebe4551cd6b639c0d68785c480"),
    (102780, "e3bb8578884c671629cd3631e868e6a6d994937837427bee9844c1b83312a226"),
    (142438, "ce6d105b9b2afbec5a5414ee1bf825f8927abb786a967f3a7eeca7de3e7bda91"),
    (275740, "1f8f4b65b25e54e6d67604e049ef92cab6f4751160a0ef6e175a7b40ba74b797"),
    (112803, "560606aa6d69d0ae1272c5e730498b749ef1e0dea7994973be75870c4bddd732"),
    (344973, "30a1d971ce11fb338e144ae332321f8b4fa6b4f2385ba585b2ac3fe728701e98"),
    (556260, "89120d49ce7e55e516c09e523f5ee5740d8834d962c439a36630b6b75a814eb3"),
    (114689, "4608159783561534e83fe60f1648d32725796c59d168a6e7f3b32add207b1a07"),
    (148823, "011343139ce031bdee93ebe8dd638b7611f68705d92b2328efb7dfe028531254"),
    (172196, "393fbb6c22617315eb692cad39b1a259d70f95f86c80f95015b76f07a15719f7"),
    (195363, "a2cd54c069e584de1aeb6c53f0a93eab450d948e23ed5dfdcdccbed9f54bca74"),
    (120787, "bda58bcfad0d1f9258992f1c45c6b8a3cebdc91e011b8fa736697ff7a3d34037"),
    (157259, "05cac3ec4c54b130c052e07df8d99ef1b1f854df87b55224b05cc5873b7ca764"),
    (338742, "f20d44f0eca4548fcf728933d66dd451f6056da485bc14fe8f3601cbaf293fb3")
];

// from b3sum:
const FRENCH_TOAST_BLAKE3: &str = "30c65bd0c63895d2fe8ea18e9e20a8d3769ac6023c23d59d4f53b0993b7ef0e0";

// from sha256sum:
const FRENCH_TOAST_SHA256: &str = "ff47f850a5011559843dd6bc3497fd3acd7d0e3b9937635540ada19b924f996e";

// this one may take a second :)
#[test]
fn french_toast_sha256() {
    let mut scanner = Scanner::new(HashType::SHA256, 16, 18, 20, 12);
    let mut f = File::open("./tests/french-toast-4.jpg").unwrap();
    let mut buffer = vec![0u8; 1024];

    let file_blocks = scanner.scan_reader(&mut f, &mut buffer, HashType::SHA256).unwrap();
    let total = file_blocks.blocks.iter().fold(0, |sum, block| { sum + block.size });

    assert_eq!(total, FRENCH_TOAST_TOTAL);
    assert_eq!(file_blocks.blocks.len(), FRENCH_TOAST_SHA256_20_12.len());
    for i in 0..file_blocks.blocks.len() {
        let (size, hash) = FRENCH_TOAST_SHA256_20_12[i];
        assert_eq!(size, file_blocks.blocks[i].size);
        assert_eq!(hash.to_string(), encode(file_blocks.blocks[i].hash));
    }
    assert_eq!(encode(file_blocks.hash), FRENCH_TOAST_SHA256);
}

// this one may take a second :)
#[test]
fn french_toast_blake3() {
    let mut scanner = Scanner::new(HashType::BLAKE3, 16, 18, 20, 12);
    let mut f = File::open("./tests/french-toast-4.jpg").unwrap();
    let mut buffer = vec![0u8; 1024];

    let file_blocks = scanner.scan_reader(&mut f, &mut buffer, HashType::BLAKE3).unwrap();
    let total = file_blocks.blocks.iter().fold(0, |sum, block| { sum + block.size });

    assert_eq!(total, FRENCH_TOAST_TOTAL);
    assert_eq!(file_blocks.blocks.len(), FRENCH_TOAST_BLAKE3_20_12.len());
    for i in 0..file_blocks.blocks.len() {
        let (size, hash) = FRENCH_TOAST_BLAKE3_20_12[i];
        assert_eq!(size, file_blocks.blocks[i].size);
        assert_eq!(hash.to_string(), encode(file_blocks.blocks[i].hash));
    }
    assert_eq!(encode(file_blocks.hash), FRENCH_TOAST_BLAKE3);
}