use std::{ io::{self, stdin, stdout, Read, Write}, ops::{Index, IndexMut}, time::Instant, }; use vector::{UVec2, Vec2}; pub mod vector; #[derive(Clone)] pub struct CodecParams { pub width: usize, pub height: usize, pub debug: usize, pub mode: CodecMode, } #[derive(Clone)] pub enum CodecMode { Encode, Decode, } pub struct Framework { process_start: Instant, params: CodecParams, } impl Framework { pub fn init() -> (Self, CodecParams) { let width = std::env::var("V_WIDTH").unwrap().parse().unwrap(); let height = std::env::var("V_HEIGHT").unwrap().parse().unwrap(); let debug = std::env::var("V_DEBUG").unwrap().parse().unwrap(); let mode = match std::env::var("V_MODE").unwrap().as_str() { "encode" => CodecMode::Encode, "decode" => CodecMode::Decode, _ => panic!("invalid mode"), }; let params = CodecParams { height, width, debug, mode, }; ( Self { params: params.clone(), process_start: Instant::now(), }, params, ) } pub fn next_frame(&mut self) -> Option { self.process_start = Instant::now(); Some(Frame::read(self.params.width, self.params.height, stdin()).unwrap()) } pub fn encode_done(&mut self, output: &[u8]) { let el = self.process_start.elapsed(); eprintln!("size={}Kb t={el:?}", output.len() / 1000 * 8) } pub fn next_chunk(&mut self, buffer: &mut Vec) -> bool { true } pub fn decode_done(&mut self, output: &Frame) { output.write(stdout()).unwrap(); } } #[derive(Debug, Clone)] pub struct Frame { pub width: usize, pub height: usize, pub pixels: Vec>, } #[derive(Debug, Clone, Copy)] pub struct Pixel { pub r: T, pub g: T, pub b: T, } pub type EPixel = Pixel; impl Frame { pub fn new(width: usize, height: usize) -> Self { Self { height, width, pixels: vec![Pixel::BLACK; width * height], } } pub fn read(width: usize, height: usize, mut r: impl Read) -> io::Result { let mut f = Frame::new(width, height); let p = unsafe { std::slice::from_raw_parts_mut( f.pixels.as_mut_slice().as_mut_ptr() as *mut u8, width * height * 3, ) }; r.read_exact(p)?; Ok(f) } pub fn write(&self, mut w: impl Write) -> io::Result<()> { let p = unsafe { std::slice::from_raw_parts( self.pixels.as_slice().as_ptr() as *const u8, self.width * self.height * 3, ) }; w.write_all(p) } } impl Index<(usize, usize)> for Frame { type Output = Pixel; #[inline] fn index(&self, (x, y): (usize, usize)) -> &Self::Output { &self.pixels[x + y * self.width] } } impl IndexMut<(usize, usize)> for Frame { #[inline] fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output { &mut self.pixels[x + y * self.width] } } impl Index for Frame { type Output = Pixel; #[inline] fn index(&self, Vec2 { x, y }: UVec2) -> &Self::Output { &self.pixels[x + y * self.width] } } impl IndexMut for Frame { #[inline] fn index_mut(&mut self, Vec2 { x, y }: UVec2) -> &mut Self::Output { &mut self.pixels[x + y * self.width] } } impl Pixel { pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 }; }