blkar 7.2.7

Multithreaded archiver offering bit rot protection and sector level recoverability
Documentation
#![allow(dead_code)]
pub const SBX_LARGEST_BLOCK_SIZE: usize = 4096;

pub const SBX_FIRST_DATA_SEQ_NUM: u32 = 1;

pub const SBX_LAST_SEQ_NUM: u32 = u32::max_value();

pub const SBX_METADATA_BLOCK_COUNT: usize = 1;

pub const SBX_SCAN_BLOCK_SIZE: usize = 128;

pub const SBX_FILE_UID_LEN: usize = common_params::FILE_UID_LEN;

pub const SBX_SIGNATURE: &[u8] = common_params::SIGNATURE;

pub const SBX_HEADER_SIZE: usize = common_params::HEADER_SIZE;

pub const SBX_MAX_DATA_BLOCK_COUNT: u32 = u32::max_value();

pub const SBX_MAX_BURST_ERR_RESISTANCE: usize = 1000;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Version {
    V1,
    V2,
    V3,
    V17,
    V18,
    V19,
}

mod common_params {
    use std::u32;

    pub const FILE_UID_LEN: usize = 6;
    pub const SIGNATURE: &[u8] = b"SBx";
    pub const HEADER_SIZE: usize = 16;
    pub const MAX_BLOCK_NUM: u64 = u32::MAX as u64;
}

mod params_for_v1 {
    use super::common_params;

    pub const BLOCK_SIZE: usize = 512;
    pub const DATA_SIZE: usize = BLOCK_SIZE - common_params::HEADER_SIZE;
}

mod params_for_v2 {
    use super::common_params;

    pub const BLOCK_SIZE: usize = 128;
    pub const DATA_SIZE: usize = BLOCK_SIZE - common_params::HEADER_SIZE;
}

mod params_for_v3 {
    use super::common_params;

    pub const BLOCK_SIZE: usize = 4096;
    pub const DATA_SIZE: usize = BLOCK_SIZE - common_params::HEADER_SIZE;
}

mod params_for_v17 {
    use super::params_for_v1;

    pub const BLOCK_SIZE: usize = params_for_v1::BLOCK_SIZE;
    pub const DATA_SIZE: usize = params_for_v1::DATA_SIZE;
}

mod params_for_v18 {
    use super::params_for_v2;

    pub const BLOCK_SIZE: usize = params_for_v2::BLOCK_SIZE;
    pub const DATA_SIZE: usize = params_for_v2::DATA_SIZE;
}

mod params_for_v19 {
    use super::params_for_v3;

    pub const BLOCK_SIZE: usize = params_for_v3::BLOCK_SIZE;
    pub const DATA_SIZE: usize = params_for_v3::DATA_SIZE;
}

pub fn ver_to_usize(version: Version) -> usize {
    use self::Version::*;
    match version {
        V1 => 1,
        V2 => 2,
        V3 => 3,
        V17 => 17,
        V18 => 18,
        V19 => 19,
    }
}

pub fn string_to_ver(string: &str) -> Result<Version, ()> {
    use self::Version::*;
    match string {
        "1" => Ok(V1),
        "2" => Ok(V2),
        "3" => Ok(V3),
        "17" => Ok(V17),
        "18" => Ok(V18),
        "19" => Ok(V19),
        _ => Err(()),
    }
}

pub fn ver_to_block_size(version: Version) -> usize {
    use self::Version::*;
    match version {
        V1 => params_for_v1::BLOCK_SIZE,
        V2 => params_for_v2::BLOCK_SIZE,
        V3 => params_for_v3::BLOCK_SIZE,
        V17 => params_for_v17::BLOCK_SIZE,
        V18 => params_for_v18::BLOCK_SIZE,
        V19 => params_for_v19::BLOCK_SIZE,
    }
}

pub fn ver_to_data_size(version: Version) -> usize {
    use self::Version::*;
    match version {
        V1 => params_for_v1::DATA_SIZE,
        V2 => params_for_v2::DATA_SIZE,
        V3 => params_for_v3::DATA_SIZE,
        V17 => params_for_v17::DATA_SIZE,
        V18 => params_for_v18::DATA_SIZE,
        V19 => params_for_v19::DATA_SIZE,
    }
}

pub fn ver_uses_rs(version: Version) -> bool {
    use self::Version::*;
    match version {
        V1 | V2 | V3 => false,
        V17 | V18 | V19 => true,
    }
}

pub fn ver_forces_meta_enabled(version: Version) -> bool {
    use self::Version::*;
    match version {
        V1 | V2 | V3 => false,
        V17 | V18 | V19 => true,
    }
}

pub fn ver_to_max_block_set_count(
    version: Version,
    data_par_burst: Option<(usize, usize, usize)>,
) -> Option<u32> {
    if ver_uses_rs(version) {
        let (data, parity, _) = data_par_burst.unwrap();

        let block_set_size = (data + parity) as u32;

        Some(SBX_MAX_DATA_BLOCK_COUNT / block_set_size)
    } else {
        assert!(data_par_burst == None);

        None
    }
}

pub fn ver_to_last_data_seq_num_exc_parity(
    version: Version,
    data_par_burst: Option<(usize, usize, usize)>,
) -> u32 {
    if ver_uses_rs(version) {
        let (data, parity, _) = data_par_burst.unwrap();

        let block_set_size = data + parity;
        let max_block_set_count = ver_to_max_block_set_count(version, data_par_burst).unwrap();

        max_block_set_count * block_set_size as u32 - parity as u32
    } else {
        assert!(data_par_burst == None);

        SBX_LAST_SEQ_NUM
    }
}

pub fn ver_to_max_data_file_size(
    version: Version,
    data_par_burst: Option<(usize, usize, usize)>,
) -> u64 {
    let data_size = ver_to_data_size(version) as u64;

    if ver_uses_rs(version) {
        let (data, _, _) = data_par_burst.unwrap();

        let max_block_set_count =
            ver_to_max_block_set_count(version, data_par_burst).unwrap() as u64;

        max_block_set_count * data as u64 * data_size
    } else {
        assert!(data_par_burst == None);

        SBX_MAX_DATA_BLOCK_COUNT as u64 * data_size
    }
}