From 0978664188a3b9c8e6ee7f2082a6c53584fb3762 Mon Sep 17 00:00:00 2001 From: Noa Aarts Date: Sun, 6 Oct 2024 23:11:26 +0200 Subject: [PATCH] improve hex parser for text protocol --- Cargo.lock | 7 ------ Cargo.toml | 1 - src/main.rs | 1 + src/text_protocol.rs | 52 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24b0829..93a6076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,7 +108,6 @@ dependencies = [ "async-trait", "atoi_radix10", "bytes", - "hex", "tokio", "tokio-test", ] @@ -131,12 +130,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "libc" version = "0.2.155" diff --git a/Cargo.toml b/Cargo.toml index dadd75d..7e2550b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" async-trait = "0.1.83" atoi_radix10 = "0.0.1" bytes = "1.6.0" -hex = "0.4.3" tokio = { version = "1.38", features = ["full"] } tokio-test = "*" diff --git a/src/main.rs b/src/main.rs index 1a02b2f..fec16ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![feature(test)] #![feature(sync_unsafe_cell)] +#![feature(if_let_guard)] mod binary_protocol; mod grid; diff --git a/src/text_protocol.rs b/src/text_protocol.rs index 4e10d6e..b7911ea 100644 --- a/src/text_protocol.rs +++ b/src/text_protocol.rs @@ -20,16 +20,46 @@ fn parse_coordinate(string: &str) -> io::Result { } } -fn parse_color(color: &str) -> io::Result { - if let Ok(bytes) = hex::decode(color) { - match bytes.len() { - 1 => return Ok(Color::W8(bytes[0])), - 3 => return Ok(Color::RGB24(bytes[0], bytes[1], bytes[2])), - 4 => return Ok(Color::RGBA32(bytes[0], bytes[1], bytes[2], bytes[3])), +type HexChar = u8; + +fn val(c1: u8, c2: u8) -> io::Result { + Ok((match c1 { + b'A'..=b'F' => c1 - b'A' + 10, + b'a'..=b'f' => c1 - b'a' + 10, + b'0'..=b'9' => c1 - b'0', + _ => return Err(Error::from(ErrorKind::InvalidInput)), + }) << 4 + | (match c2 { + b'A'..=b'F' => c2 - b'A' + 10, + b'a'..=b'f' => c2 - b'a' + 10, + b'0'..=b'9' => c2 - b'0', _ => return Err(Error::from(ErrorKind::InvalidInput)), + })) +} + +fn parse_color(color: &str) -> io::Result { + let color = color.as_bytes(); + match color.len() { + 2 if let Ok(w) = val(color[0], color[1]) => Ok(Color::W8(w)), + 6 if let (Ok(r), Ok(g), Ok(b)) = ( + val(color[0], color[1]), + val(color[2], color[3]), + val(color[4], color[5]), + ) => + { + Ok(Color::RGB24(r, g, b)) } + 8 if let (Ok(r), Ok(g), Ok(b), Ok(a)) = ( + val(color[0], color[1]), + val(color[2], color[3]), + val(color[4], color[5]), + val(color[6], color[7]), + ) => + { + Ok(Color::RGBA32(r, g, b, a)) + } + _ => Err(Error::from(ErrorKind::InvalidInput)), } - Err(Error::from(ErrorKind::InvalidInput)) } impl TextParser { @@ -117,7 +147,13 @@ impl Responder for TextParser { Response::Size(x, y) => writer.write_all(format!("SIZE {x} {y}\n").as_bytes()).await, Response::GetPixel(x, y, color) => { writer - .write_all(format!("PX {x} {y} {}\n", hex::encode_upper(color)).as_bytes()) + .write_all( + format!( + "PX {x} {y} {:02X}{:02X}{:02X}\n", + color[0], color[1], color[2] + ) + .as_bytes(), + ) .await } }