diff --git a/src/flutclient.rs b/src/flutclient.rs index 95eab47..b7240b2 100644 --- a/src/flutclient.rs +++ b/src/flutclient.rs @@ -7,7 +7,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}; use crate::{ get_pixel, - grid::{self, Flut}, + grid::{self, FlutGrid}, increment_counter, protocols::{BinaryParser, IOProtocol, Parser, Responder, TextParser}, set_pixel_rgba, Canvas, Color, Command, Coordinate, Protocol, Response, @@ -45,7 +45,7 @@ where { reader: BufReader, writer: BufWriter, - grids: Arc<[Flut]>, + grids: Arc<[FlutGrid]>, parser: ParserTypes, counter: u64, } @@ -111,7 +111,7 @@ where } } - pub fn new(reader: R, writer: W, grids: Arc<[grid::Flut]>) -> Self { + pub fn new(reader: R, writer: W, grids: Arc<[grid::FlutGrid]>) -> Self { FlutClient { reader: BufReader::new(reader), writer: BufWriter::new(writer), diff --git a/src/grid.rs b/src/grid.rs index da2019d..81fb466 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -1,6 +1,7 @@ -use std::cell::SyncUnsafeCell; +use std::{cell::SyncUnsafeCell}; use image::{GenericImageView, Rgb}; +use tokio::sync::{RwLock, RwLockReadGuard}; use crate::Coordinate; @@ -11,22 +12,24 @@ pub trait Grid { fn set(&self, x: I, y: I, value: V); } -pub struct Flut { +pub struct FlutGrid { size_x: usize, size_y: usize, cells: SyncUnsafeCell>, + jpgbuf: RwLock> } -impl Flut { - pub fn init(size_x: usize, size_y: usize, value: T) -> Flut { +impl FlutGrid { + pub fn init(size_x: usize, size_y: usize, value: T) -> FlutGrid { let mut vec = Vec::with_capacity(size_x * size_y); for _ in 0..(size_x * size_y) { vec.push(value.clone()); } - Flut { + FlutGrid { size_x, size_y, cells: vec.into(), + jpgbuf: RwLock::new(Vec::new()) } } @@ -35,7 +38,7 @@ impl Flut { } } -impl Flut { +impl FlutGrid { fn index(&self, x: Coordinate, y: Coordinate) -> Option { let x = x as usize; let y = y as usize; @@ -44,9 +47,12 @@ impl Flut { } Some((y * self.size_x) + x) } + pub async fn read_jpg_buffer(&self) -> RwLockReadGuard<'_, Vec> { + self.jpgbuf.read().await + } } -impl Grid for Flut { +impl Grid for FlutGrid { fn get(&self, x: Coordinate, y: Coordinate) -> Option<&T> { self.index(x, y) .map(|idx| unsafe { &(*self.cells.get())[idx] }) @@ -65,7 +71,7 @@ impl Grid for Flut { } } -impl GenericImageView for Flut { +impl GenericImageView for FlutGrid { type Pixel = Rgb; fn dimensions(&self) -> (u32, u32) { @@ -78,24 +84,38 @@ impl GenericImageView for Flut { let [r, g, b, _a] = pixel.to_be_bytes(); Rgb::from([r, g, b]) } + +} + +impl FlutGrid { + pub async fn update_jpg_buffer(&self) { + let mut jpgbuf = self.jpgbuf.write().await; + jpgbuf.clear(); + let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut *jpgbuf, 50); + let subimage = self.view(0, 0, self.width(), self.height()).to_image(); + match subimage.write_with_encoder(encoder) { + Ok(_) => {} + Err(err) => eprintln!("{}", err), + } + } } #[cfg(test)] #[allow(clippy::needless_return)] mod tests { - use super::Flut; + use super::FlutGrid; use super::Grid; #[tokio::test] async fn test_grid_init_values() { - let grid = Flut::init(3, 3, 0); + let grid = FlutGrid::init(3, 3, 0); assert_eq!(grid.cells.into_inner(), vec![0, 0, 0, 0, 0, 0, 0, 0, 0]); } #[tokio::test] async fn test_grid_init_size() { - let grid = Flut::init(800, 600, 0); + let grid = FlutGrid::init(800, 600, 0); assert_eq!(grid.size_x, 800); assert_eq!(grid.size_y, 600); @@ -103,7 +123,7 @@ mod tests { #[tokio::test] async fn test_grid_set() { - let grid = Flut::init(3, 3, 0); + let grid = FlutGrid::init(3, 3, 0); grid.set(1, 1, 255); grid.set(2, 1, 256); assert_eq!(grid.cells.into_inner(), vec![0, 0, 0, 0, 255, 256, 0, 0, 0]); @@ -111,7 +131,7 @@ mod tests { #[tokio::test] async fn test_grid_set_out_of_range() { - let grid = Flut::init(3, 3, 0); + let grid = FlutGrid::init(3, 3, 0); grid.set(1, 1, 255); grid.set(3, 1, 256); assert_eq!(grid.cells.into_inner(), vec![0, 0, 0, 0, 255, 0, 0, 0, 0]); @@ -119,14 +139,14 @@ mod tests { #[tokio::test] async fn test_grid_get() { - let grid = Flut::init(3, 3, 0); + let grid = FlutGrid::init(3, 3, 0); grid.set(1, 2, 222); assert_eq!(grid.get(1, 2), Some(&222)); } #[tokio::test] async fn test_grid_get_out_of_range() { - let grid = Flut::init(3, 3, 0); + let grid = FlutGrid::init(3, 3, 0); grid.set(3, 1, 256); assert_eq!(grid.get(3, 1), None); assert_eq!(grid.get(1, 2), Some(&0)); diff --git a/src/lib.rs b/src/lib.rs index 0d5e5f7..b782e20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ pub type Coordinate = u16; pub static COUNTER: AtomicU64 = AtomicU64::new(0); fn set_pixel_rgba( - grids: &[grid::Flut], + grids: &[grid::FlutGrid], canvas: Canvas, x: Coordinate, y: Coordinate, @@ -34,7 +34,7 @@ fn set_pixel_rgba( } fn get_pixel( - grids: &[grid::Flut], + grids: &[grid::FlutGrid], canvas: Canvas, x: Coordinate, y: Coordinate, diff --git a/src/main.rs b/src/main.rs index 6470112..855d731 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use debug_print::{debug_eprintln, debug_println}; use flurry::{ config::{GRID_LENGTH, HOST, IMAGE_SAVE_INTERVAL}, flutclient::FlutClient, - grid::{self, Flut}, + grid::{self, FlutGrid}, COUNTER, }; use image::{codecs::jpeg::JpegEncoder, GenericImageView, SubImage}; @@ -84,8 +84,8 @@ async fn handle_flut(flut_listener: TcpListener, grids: Arc<[grid::Flut]>) #[tokio::main] #[allow(clippy::needless_return)] async fn main() { + let grids: Arc<[FlutGrid; GRID_LENGTH]> = [grid::FlutGrid::init(800, 600, 0xff_00_ff_ff)].into(); println!("created grids"); - let grids: Arc<[Flut; GRID_LENGTH]> = [grid::Flut::init(800, 600, 0xff_00_ff_ff)].into(); let Ok(flut_listener) = TcpListener::bind(HOST).await else { eprintln!("Was unable to bind to {HOST}, please check if a different process is bound");