diff --git a/src/flutclient.rs b/src/flutclient.rs index fcda60c..69c27da 100644 --- a/src/flutclient.rs +++ b/src/flutclient.rs @@ -10,7 +10,7 @@ use crate::{ grid::{self, Flut}, increment_counter, protocols::{BinaryParser, IOProtocol, Parser, Responder, TextParser}, - set_pixel_rgba, Canvas, Color, Command, Coordinate, Protocol, Response, + set_pixel_rgba, Canvas, Color, Command, Coordinate, Protocol, ProtocolStatus, Response, }; macro_rules! build_parser_type_enum { @@ -36,6 +36,17 @@ macro_rules! build_parser_type_enum { } impl ParserTypes { + pub fn get_status() -> Vec { + vec![ + $( + #[cfg(feature = $feat)] + ProtocolStatus::Enabled($feat), + #[cfg(not(feature = $feat))] + ProtocolStatus::Disabled($feat), + )* + ] + } + pub fn announce() { $( #[cfg(feature = $feat)] @@ -88,6 +99,14 @@ where Ok(()) } + async fn protocols_command(&mut self) -> io::Result<()> { + match_parser! { + parser: self.parser => parser.unparse(Response::Protocols(ParserTypes::get_status()), &mut self.writer).await? + }; + self.writer.flush().await?; + Ok(()) + } + async fn size_command(&mut self, canvas: Canvas) -> io::Result<()> { let (x, y) = self.grids[canvas as usize].get_size(); match_parser!(parser: self.parser => parser.unparse( @@ -166,6 +185,7 @@ where match parsed { Ok(Command::Help) => self.help_command().await?, Ok(Command::Size(canvas)) => self.size_command(canvas).await?, + Ok(Command::Protocols) => self.protocols_command().await?, Ok(Command::GetPixel(canvas, x, y)) => self.get_pixel_command(canvas, x, y).await?, Ok(Command::SetPixel(canvas, x, y, color)) => self.set_pixel_command(canvas, x, y, &color), Ok(Command::ChangeCanvas(canvas)) => { diff --git a/src/lib.rs b/src/lib.rs index 4b35c6f..ca49c1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,12 @@ fn increment_counter(amount: u64) { COUNTER.fetch_add(amount, std::sync::atomic::Ordering::Relaxed); } +#[derive(Debug, PartialEq)] +pub enum ProtocolStatus { + Enabled(&'static str), + Disabled(&'static str), +} + #[derive(Debug, PartialEq)] pub enum Protocol { Text, @@ -62,6 +68,7 @@ pub enum Protocol { #[derive(Debug, PartialEq)] pub enum Command { Help, + Protocols, Size(Canvas), GetPixel(Canvas, Coordinate, Coordinate), SetPixel(Canvas, Coordinate, Coordinate, Color), @@ -72,6 +79,7 @@ pub enum Command { #[derive(Debug, PartialEq)] pub enum Response { Help, + Protocols(Vec), Size(Coordinate, Coordinate), GetPixel(Coordinate, Coordinate, [u8; 3]), } diff --git a/src/protocols/binary_protocol.rs b/src/protocols/binary_protocol.rs index e505112..5bb0a13 100644 --- a/src/protocols/binary_protocol.rs +++ b/src/protocols/binary_protocol.rs @@ -7,6 +7,7 @@ use crate::{Canvas, Color, Command, Response}; use super::{IOProtocol, Parser, Responder}; const SIZE_BIN: u8 = 115; +const PROTOCOLS_BIN: u8 = 116; const HELP_BIN: u8 = 104; const GET_PX_BIN: u8 = 32; const SET_PX_RGB_BIN: u8 = 128; @@ -22,6 +23,7 @@ impl Parser for Binar match fst { Ok(command) => match command { HELP_BIN => Ok(Command::Help), + PROTOCOLS_BIN => Ok(Command::Protocols), SIZE_BIN => { let canvas = reader.read_u8().await?; Ok(Command::Size(canvas)) @@ -106,6 +108,23 @@ To set a pixel using RGB, use ({SET_PX_RGB_BIN:02X}) (u8 canvas) (x as u16_le) ( ); writer.write_all(help_text.as_bytes()).await } + Response::Protocols(protos) => { + for protocol in protos { + match protocol { + crate::ProtocolStatus::Enabled(proto) => { + writer + .write_all(format!("Enabled: {}\n", proto).as_bytes()) + .await?; + } + crate::ProtocolStatus::Disabled(proto) => { + writer + .write_all(format!("Disabled: {}\n", proto).as_bytes()) + .await?; + } + } + } + Ok(()) + } Response::Size(x, y) => { writer.write_u16(x).await?; writer.write_u16(y).await diff --git a/src/protocols/text_protocol.rs b/src/protocols/text_protocol.rs index 160ec75..a63ff93 100644 --- a/src/protocols/text_protocol.rs +++ b/src/protocols/text_protocol.rs @@ -117,6 +117,8 @@ impl Parser for TextP if reader.read_line(&mut line).await.is_ok() { if line.starts_with("HELP") { return Ok(Command::Help); + } else if line.starts_with("PROTOCOLS") { + return Ok(Command::Protocols); } else if line.starts_with("SIZE") { return Ok(Command::Size(self.canvas)); } else if line.starts_with("PX ") { @@ -146,6 +148,23 @@ impl Responder for TextParser { async fn unparse(&self, response: Response, writer: &mut W) -> io::Result<()> { match response { Response::Help => writer.write_all(HELP_TEXT).await, + Response::Protocols(protos) => { + for protocol in protos { + match protocol { + crate::ProtocolStatus::Enabled(proto) => { + writer + .write_all(format!("Enabled: {}\n", proto).as_bytes()) + .await?; + } + crate::ProtocolStatus::Disabled(proto) => { + writer + .write_all(format!("Disabled: {}\n", proto).as_bytes()) + .await?; + } + } + } + Ok(()) + } Response::Size(x, y) => writer.write_all(format!("SIZE {x} {y}\n").as_bytes()).await, Response::GetPixel(x, y, color) => { writer