aboutsummaryrefslogtreecommitdiff
path: root/framework/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/lib.rs')
-rw-r--r--framework/src/lib.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/framework/src/lib.rs b/framework/src/lib.rs
index 139597f..89fcc10 100644
--- a/framework/src/lib.rs
+++ b/framework/src/lib.rs
@@ -1,2 +1,144 @@
+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<Frame> {
+ 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<u8>) -> 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<Pixel<u8>>,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Pixel<T> {
+ pub r: T,
+ pub g: T,
+ pub b: T,
+}
+pub type EPixel = Pixel<u8>;
+
+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<Self> {
+ 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<u8>;
+ #[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<UVec2> for Frame {
+ type Output = Pixel<u8>;
+ #[inline]
+ fn index(&self, Vec2 { x, y }: UVec2) -> &Self::Output {
+ &self.pixels[x + y * self.width]
+ }
+}
+impl IndexMut<UVec2> for Frame {
+ #[inline]
+ fn index_mut(&mut self, Vec2 { x, y }: UVec2) -> &mut Self::Output {
+ &mut self.pixels[x + y * self.width]
+ }
+}
+
+impl Pixel<u8> {
+ pub const BLACK: Pixel<u8> = Pixel { r: 0, g: 0, b: 0 };
+}