diff options
-rw-r--r-- | evc/Cargo.lock | 7 | ||||
-rw-r--r-- | evc/Cargo.toml | 1 | ||||
-rw-r--r-- | evc/src/bin/decode.rs | 19 | ||||
-rw-r--r-- | evc/src/bin/encode.rs | 25 | ||||
-rw-r--r-- | evc/src/block.rs | 4 | ||||
-rw-r--r-- | evc/src/frame.rs | 4 | ||||
-rw-r--r-- | evc/src/header.rs | 12 | ||||
-rw-r--r-- | evc/src/pixel.rs | 4 | ||||
-rw-r--r-- | evc/src/ser.rs | 116 |
9 files changed, 119 insertions, 73 deletions
diff --git a/evc/Cargo.lock b/evc/Cargo.lock index 06f5cb2..84e5513 100644 --- a/evc/Cargo.lock +++ b/evc/Cargo.lock @@ -3,6 +3,12 @@ version = 3 [[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + +[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -76,6 +82,7 @@ dependencies = [ name = "evc" version = "0.1.0" dependencies = [ + "anyhow", "clap", ] diff --git a/evc/Cargo.toml b/evc/Cargo.toml index d86ebef..43818ee 100644 --- a/evc/Cargo.toml +++ b/evc/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] clap = { version = "*", features = ["derive"] } +anyhow = "1.0.66" diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs index 293181a..0a00426 100644 --- a/evc/src/bin/decode.rs +++ b/evc/src/bin/decode.rs @@ -1,6 +1,5 @@ #![feature(box_patterns)] -use std::io::{self, BufReader, BufWriter}; - +use anyhow::Context; use clap::Parser; use evc::{ block::{Block, BlockInner}, @@ -9,24 +8,26 @@ use evc::{ ser::Source, view::View, }; +use std::io::{BufReader, BufWriter}; #[derive(Parser)] #[clap(about, version)] pub struct DecodeArgs {} -fn main() -> io::Result<()> { +fn main() -> anyhow::Result<()> { let _args = DecodeArgs::parse(); let mut input = BufReader::new(std::io::stdin()); let mut output = BufWriter::new(std::io::stdout()); - let header = input.get::<Header>()?; + let header = input.get::<Header>().context("reading header")?; eprintln!("{header:?}"); let size = header.resolution; - + let mut prev = Frame::new(size); - loop { - let block = Block::read(&mut input, size)?; + for i in 0.. { + eprintln!("decode frame {i}"); + let block = Block::read(&mut input, size).context("reading encoded frame")?; let mut frame = Frame::new(size); blit_block( @@ -35,9 +36,11 @@ fn main() -> io::Result<()> { prev.view((0, 0), size), ); - frame.write(&mut output)?; + frame.write(&mut output).context("writing raw frame")?; prev = frame; } + drop(input); + Ok(()) } fn blit_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Frame>) { diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs index c426aba..1934e26 100644 --- a/evc/src/bin/encode.rs +++ b/evc/src/bin/encode.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use clap::Parser; use evc::{ block::{Block, BlockInner}, @@ -6,7 +7,7 @@ use evc::{ ser::Sink, view::View, }; -use std::io::{self, BufReader, BufWriter}; +use std::io::{BufReader, BufWriter}; #[derive(Parser)] #[clap(about, version)] @@ -17,28 +18,32 @@ pub struct EncodeArgs { height: usize, } -fn main() -> io::Result<()> { +fn main() -> anyhow::Result<()> { let args = EncodeArgs::parse(); let mut input = BufReader::new(std::io::stdin()); let mut output = BufWriter::new(std::io::stdout()); let size = (args.width, args.height); - output.put(Header { - resolution: size, - frame_count: 0, - })?; + output + .put(Header { + resolution: size, + frame_count: 0, + }) + .context("writing header")?; let mut prev_frame = Frame::new(size); for i in 0.. { - println!("frame {i}"); - let frame = Frame::read(&mut input, size)?; + eprintln!("encode frame {i}"); + let frame = Frame::read(&mut input, size) + .context("reading raw frame") + .unwrap(); let v1 = frame.view((0, 0), size); let v2 = prev_frame.view((0, 0), size); let root = encode_block(v1, v2); - root.write(&mut output)?; + root.write(&mut output).context("writing encoded frame")?; prev_frame = frame; } @@ -48,7 +53,7 @@ fn main() -> io::Result<()> { fn encode_block(view: View<&Frame>, prev: View<&Frame>) -> Block { let diff = View::diff(&view, &prev) / view.area() as f64; - eprintln!("{:?} {diff}", view.size); + // eprintln!("{:?} {diff}", view.size); let inner = if diff < 0.5 { BlockInner::Reference { translation: (0, 0), diff --git a/evc/src/block.rs b/evc/src/block.rs index 261882a..f58bcb3 100644 --- a/evc/src/block.rs +++ b/evc/src/block.rs @@ -17,7 +17,7 @@ pub enum BlockInner { } impl Block { - pub fn write(&self, sink: &mut impl std::io::Write) -> std::io::Result<()> { + pub fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { match &self.inner { BlockInner::Literal(pixels) => { sink.put(0u8)?; @@ -35,7 +35,7 @@ impl Block { Ok(()) } - pub fn read(source: &mut impl std::io::Read, size: (usize, usize)) -> std::io::Result<Self> { + pub fn read(source: &mut impl std::io::Read, size: (usize, usize)) -> anyhow::Result<Self> { let inner = match source.get::<u8>()? { 0 => BlockInner::Literal(source.get()?), 1 => BlockInner::Split(Box::new({ diff --git a/evc/src/frame.rs b/evc/src/frame.rs index 1269bf2..c36abf3 100644 --- a/evc/src/frame.rs +++ b/evc/src/frame.rs @@ -22,7 +22,7 @@ impl Frame { .collect(), } } - pub fn read(source: &mut impl Source, size: (usize, usize)) -> io::Result<Self> { + pub fn read(source: &mut impl Source, size: (usize, usize)) -> anyhow::Result<Self> { let mut frame = Frame::new(size); for y in 0..size.1 { for x in 0..size.0 { @@ -32,7 +32,7 @@ impl Frame { } Ok(frame) } - pub fn write(&self, sink: &mut impl Sink) -> io::Result<()> { + pub fn write(&self, sink: &mut impl Sink) -> anyhow::Result<()> { for y in 0..self.size.1 { for x in 0..self.size.0 { sink.put(self[(x, y)])?; diff --git a/evc/src/header.rs b/evc/src/header.rs index 923e8ff..5244ce5 100644 --- a/evc/src/header.rs +++ b/evc/src/header.rs @@ -1,20 +1,22 @@ use crate::ser::{Ser, Sink, Source}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct Header { pub resolution: (usize, usize), pub frame_count: usize, } +pub const MAGIC: [u8; 4] = [0x5eu8, 0xb1u8, 0xc3u8, 0x08u8]; + impl Ser for Header { - fn write(&self, sink: &mut impl std::io::Write) -> std::io::Result<()> { - sink.put([0x5eu8, 0xb1u8, 0xc3u8, 0x08u8])?; + fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { + sink.put(MAGIC)?; sink.put((self.resolution, self.frame_count))?; Ok(()) } - fn read(source: &mut impl std::io::Read) -> std::io::Result<Self> { - source.get::<[u8; 4]>()?; + fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> { + assert_eq!(source.get::<[u8; 4]>()?, MAGIC); let (resolution, frame_count) = source.get()?; Ok(Self { resolution, diff --git a/evc/src/pixel.rs b/evc/src/pixel.rs index 442c1b5..aaf8d83 100644 --- a/evc/src/pixel.rs +++ b/evc/src/pixel.rs @@ -8,11 +8,11 @@ pub struct Pixel { } impl Ser for Pixel { - fn write(&self, sink: &mut impl std::io::Write) -> std::io::Result<()> { + fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { sink.put((self.r, self.g, self.b)) } - fn read(source: &mut impl std::io::Read) -> std::io::Result<Self> { + fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> { let (r, g, b) = source.get()?; Ok(Self { r, g, b }) } diff --git a/evc/src/ser.rs b/evc/src/ser.rs index 2d0bc82..6e1ef98 100644 --- a/evc/src/ser.rs +++ b/evc/src/ser.rs @@ -1,61 +1,62 @@ -use std::io::{self, Read, Write}; +use anyhow::Context; +use std::io::{Read, Write}; pub trait Sink { - fn put<V: Ser>(&mut self, value: V) -> io::Result<()>; + fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()>; } pub trait Source { - fn get<V: Ser>(&mut self) -> io::Result<V>; + fn get<V: Ser>(&mut self) -> anyhow::Result<V>; } impl<T: Write> Sink for T { - fn put<V: Ser>(&mut self, value: V) -> io::Result<()> { + fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()> { value.write(self) } } impl<T: Read> Source for T { - fn get<V: Ser>(&mut self) -> io::Result<V> { + fn get<V: Ser>(&mut self) -> anyhow::Result<V> { V::read(self) } } pub trait Ser: Sized { - fn write(&self, sink: &mut impl Write) -> io::Result<()>; - fn read(source: &mut impl Read) -> io::Result<Self>; + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()>; + fn read(source: &mut impl Read) -> anyhow::Result<Self>; } impl<A: Ser, B: Ser> Ser for (A, B) { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - self.0.write(sink)?; - self.1.write(sink)?; + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + self.0.write(sink).context("first tuple field")?; + self.1.write(sink).context("second tuple field")?; Ok(()) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { Ok((A::read(source)?, B::read(source)?)) } } impl<A: Ser, B: Ser, C: Ser> Ser for (A, B, C) { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - self.0.write(sink)?; - self.1.write(sink)?; - self.2.write(sink)?; + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + self.0.write(sink).context("first tuple field")?; + self.1.write(sink).context("second tuple field")?; + self.2.write(sink).context("third tuple field")?; Ok(()) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { Ok((A::read(source)?, B::read(source)?, C::read(source)?)) } } impl<A: Ser, const N: usize> Ser for [A; N] { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { for e in self { - e.write(sink)?; + e.write(sink).context("some array")?; } Ok(()) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut k: [A; N] = unsafe { std::mem::zeroed() }; for i in 0..N { k[i] = A::read(source)?; @@ -65,15 +66,15 @@ impl<A: Ser, const N: usize> Ser for [A; N] { } impl<T: Ser> Ser for Vec<T> { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { self.len().write(sink)?; for e in self { - e.write(sink)?; + e.write(sink).context("some vec")?; } Ok(()) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut v = vec![]; for _ in 0..usize::read(source)? { v.push(T::read(source)?) @@ -83,70 +84,82 @@ impl<T: Ser> Ser for Vec<T> { } impl Ser for u8 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&[*self]) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink.write_all(&[*self]).context("write u8")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 1]; source.read_exact(&mut buf)?; Ok(buf[0]) } } impl Ser for u16 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 2]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 2]>(self) }) + .context("write 16")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 2]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for u32 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) + .context("write u32")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 4]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for u64 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + .context("write u64")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for usize { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + .context("write usize")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for f32 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) }) + .context("write f32")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 4]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) } } impl Ser for f64 { - fn write(&self, sink: &mut impl Write) -> io::Result<()> { - sink.write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> { + Ok(sink + .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) }) + .context("write f64")?) } - fn read(source: &mut impl Read) -> io::Result<Self> { + fn read(source: &mut impl Read) -> anyhow::Result<Self> { let mut buf = [0u8; 8]; source.read_exact(&mut buf)?; Ok(unsafe { std::mem::transmute_copy(&buf) }) @@ -155,10 +168,18 @@ impl Ser for f64 { #[cfg(test)] mod test { - use super::Sink; + use super::{Ser, Sink}; + use crate::header::Header; use crate::ser::Source; + use std::fmt::Debug; use std::io::Cursor; + fn test_ser<T: PartialEq + Ser + Debug + Copy>(value: T) { + let mut buf = vec![]; + Cursor::new(&mut buf).put(value).unwrap(); + assert_eq!(value, Cursor::new(&mut buf).get().unwrap()); + } + #[test] fn simple() { let mut buf = vec![]; @@ -171,4 +192,11 @@ mod test { Cursor::new(&mut buf).put((10usize, 5u8, 3u16)).unwrap(); assert_eq!((10usize, 5u8, 3u16), Cursor::new(&mut buf).get().unwrap()); } + #[test] + fn header() { + test_ser(Header { + frame_count: 123, + resolution: (13, 37), + }); + } } |