blockset 0.2.1

Data Block Set
Documentation
use std::io::{self, Write};

use crate::{sha224::compress_one, u224::U224, u32::from_u8x4};

#[derive(Debug, Clone, Copy)]
pub enum Type {
    Main = 0,
    Parts = 1,
}

const EMPTY: U224 = compress_one(&[0, 0]);

pub trait Table {
    fn has_block(&self, t: Type, key: &U224) -> bool;
    fn get_block(&self, t: Type, key: &U224) -> io::Result<Vec<u8>>;
    fn set_block(&mut self, t: Type, key: &U224, value: impl Iterator<Item = u8>)
        -> io::Result<()>;
    fn check_set_block(
        &mut self,
        t: Type,
        key: &U224,
        value: impl Iterator<Item = u8>,
    ) -> io::Result<()> {
        if !self.has_block(t, key) {
            self.set_block(t, key, value)?;
        }
        Ok(())
    }
    fn restore(&self, mut t: Type, k: &U224, w: &mut impl Write) -> io::Result<()> {
        if *k == EMPTY {
            return Ok(());
        }
        let mut tail = Vec::default();
        let mut keys = [*k].to_vec();
        while let Some(key) = keys.pop() {
            let v = self.get_block(t, &key)?;
            let mut len = *v.first().unwrap() as usize;
            if len == 0x20 {
                w.write_all(&v[1..])?;
            } else {
                len += 1;
                if len > 1 {
                    assert!(tail.is_empty());
                    tail = v[1..len].to_vec();
                }
                let mut i = v.len();
                while len + 28 <= i {
                    let mut kn = U224::default();
                    i -= 28;
                    let mut j = i;
                    for ki in &mut kn {
                        let n = j + 4;
                        let slice = &v[j..n];
                        *ki = from_u8x4(slice.try_into().unwrap());
                        j = n;
                    }
                    keys.push(kn);
                }
            }
            t = Type::Parts;
        }
        w.write_all(&tail)
    }
}