use crate::{ pixel::Pixel, ser::{Ser, Sink, Source}, }; #[derive(Clone, Debug)] pub struct Block { pub size: (usize, usize), pub inner: BlockInner, } #[derive(Clone, Debug)] pub enum BlockInner { Literal(Vec), Split(Box<[Block; 2]>), Reference { translation: (usize, usize) }, } impl Block { pub fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { match &self.inner { BlockInner::Literal(pixels) => { sink.put(0u8)?; pixels.write(sink)?; } BlockInner::Split(box [a, b]) => { sink.put(1u8)?; a.write(sink)?; b.write(sink)?; } BlockInner::Reference { translation: _ } => { sink.put(2u8)?; } } Ok(()) } pub fn read(source: &mut impl std::io::Read, size: (usize, usize)) -> anyhow::Result { let inner = match source.get::()? { 0 => BlockInner::Literal(source.get()?), 1 => BlockInner::Split(Box::new({ let subsize = if size.0 > size.1 { (size.0 / 2, size.1) } else { (size.0, size.1 / 2) }; [Block::read(source, subsize)?, Block::read(source, subsize)?] })), 2 => todo!(), _ => panic!("file corrupt"), }; Ok(Self { size, inner }) } }