From 689b732184c227b4f49e2b509fad06c1f31c4e4b Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Tue, 16 Nov 2021 19:12:36 +0100 Subject: switch RawPalette to integer representation Introducing a simple type for RGB colors. That awkward string representation for RawPalette got unwieldy quick. --- src/lib.rs | 141 +++++++++++++++++++++++++++++++++++++++-------------------- src/vtcol.rs | 6 +-- 2 files changed, 96 insertions(+), 51 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 699b462..18e554d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,7 +127,7 @@ const PALETTE_SIZE: usize = 16; const PALETTE_BYTES: usize = PALETTE_SIZE * 3; /* 16 * sizeof(int) */ const RAW_COLEXPR_SIZE: usize = 6; /* e. g. 0xBADF00 */ -pub type RawPalette<'a> = [&'a str; PALETTE_SIZE]; +pub type RawPalette<'a> = [u32; PALETTE_SIZE]; #[derive(Debug)] pub enum Color @@ -216,36 +216,36 @@ pub struct Builtin /** Vanilla Linux colors. */ const DEFAULT_COLORS: RawPalette = [ - "000000", "aa0000", "00aa00", "aa5500", "0000aa", "aa00aa", "00aaaa", - "aaaaaa", "555555", "ff5555", "55ff55", "ffff55", "5555ff", "ff55ff", - "55ffff", "ffffff", + 0x000000, 0xaa0000, 0x00aa00, 0xaa5500, 0x0000aa, 0xaa00aa, 0x00aaaa, + 0xaaaaaa, 0x555555, 0xff5555, 0x55ff55, 0xffff55, 0x5555ff, 0xff55ff, + 0x55ffff, 0xffffff, ]; /** The dark (default) version of the Solarized scheme. */ const SOLARIZED_COLORS_DARK: RawPalette = [ - "002b36", "dc322f", "859900", "b58900", "268bd2", "d33682", "2aa198", - "eee8d5", "002b36", "cb4b16", "586e75", "657b83", "839496", "6c71c4", - "93a1a1", "fdf6e3", + 0x002b36, 0xdc322f, 0x859900, 0xb58900, 0x268bd2, 0xd33682, 0x2aa198, + 0xeee8d5, 0x002b36, 0xcb4b16, 0x586e75, 0x657b83, 0x839496, 0x6c71c4, + 0x93a1a1, 0xfdf6e3, ]; /** The light version of the Solarized theme. */ const SOLARIZED_COLORS_LIGHT: RawPalette = [ - "eee8d5", "dc322f", "859900", "b58900", "268bd2", "d33682", "2aa198", - "073642", "fdf6e3", "cb4b16", "93a1a1", "839496", "657b83", "6c71c4", - "586e75", "002b36", + 0xeee8d5, 0xdc322f, 0x859900, 0xb58900, 0x268bd2, 0xd33682, 0x2aa198, + 0x073642, 0xfdf6e3, 0xcb4b16, 0x93a1a1, 0x839496, 0x657b83, 0x6c71c4, + 0x586e75, 0x002b36, ]; /** Bright green monochrome terminal. */ const MONOCHROME_PHOSPHOR: RawPalette = [ - "000000", "68fc68", "68fc68", "68fc68", "68fc68", "68fc68", "68fc68", - "68fc68", "68fc68", "68fc68", "68fc68", "68fc68", "68fc68", "68fc68", - "68fc68", "68fc68", + 0x000000, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, + 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, 0x68fc68, + 0x68fc68, 0x68fc68, ]; const DUMMY_COLORS: RawPalette = [ - "000000", "ffffff", "000000", "ffffff", "000000", "ffffff", "000000", - "ffffff", "000000", "ffffff", "000000", "ffffff", "000000", "ffffff", - "000000", "ffffff", + 0x000000, 0xffffff, 0x000000, 0xffffff, 0x000000, 0xffffff, 0x000000, + 0xffffff, 0x000000, 0xffffff, 0x000000, 0xffffff, 0x000000, 0xffffff, + 0x000000, 0xffffff, ]; pub const BUILTIN_SCHEMES: &[Builtin] = &[ @@ -386,29 +386,62 @@ impl From for Scheme } } -fn nibble_of_char(chr: u8) -> u8 +#[inline] +fn nibble_of_char(chr: u8) -> io::Result { match chr { - b'0'..=b'9' => chr - b'0', - b'a'..=b'f' => chr - b'a' + 10, - b'A'..=b'F' => chr - b'A' + 10, - _ => 0, + b'0'..=b'9' => Ok(chr - b'0'), + b'a'..=b'f' => Ok(chr - b'a' + 10), + b'A'..=b'F' => Ok(chr - b'A' + 10), + _ => + Err(io::Error::new( + io::ErrorKind::Other, + format!("junk input ‘{}’ does not represent a hex digit", chr,), + )), } } macro_rules! byte_of_hex { ($ar:ident, $off:expr) => { - (nibble_of_char($ar[$off])) << 4 | nibble_of_char($ar[$off + 1]) as u8 + (nibble_of_char($ar[$off])? << 4 | nibble_of_char($ar[$off + 1])?) as u8 }; } -fn rgb_of_hex_triplet(def: &str) -> (u8, u8, u8) +struct Rgb(u8, u8, u8); + +impl Rgb +{ + fn r(&self) -> u8 { self.0 } + + fn g(&self) -> u8 { self.1 } + + fn b(&self) -> u8 { self.2 } +} + +impl TryFrom<&[u8; 6]> for Rgb +{ + type Error = io::Error; + + fn try_from(hex: &[u8; RAW_COLEXPR_SIZE]) -> io::Result + { + let r: u8 = byte_of_hex!(hex, 0); + let g: u8 = byte_of_hex!(hex, 2); + let b: u8 = byte_of_hex!(hex, 4); + + Ok(Self(r, g, b)) + } +} + +impl From for Rgb { - let bytes = def.as_bytes(); - let r: u8 = byte_of_hex!(bytes, 0); - let g: u8 = byte_of_hex!(bytes, 2); - let b: u8 = byte_of_hex!(bytes, 4); - (r, g, b) + fn from(rgb: u32) -> Self + { + let b: u8 = (rgb & 0xff) as u8; + let g: u8 = ((rgb >> 8) & 0xff) as u8; + let r: u8 = ((rgb >> 16) & 0xff) as u8; + + Self(r, g, b) + } } #[derive(Eq, PartialEq, Clone)] @@ -421,12 +454,15 @@ impl Palette pub fn dummy() -> Self { Self::from(&DUMMY_COLORS) } - pub fn from_buffered_reader(reader: &mut dyn std::io::BufRead) -> Self + pub fn from_buffered_reader( + reader: &mut dyn std::io::BufRead, + ) -> io::Result { let mut pal_idx: usize = 0; let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES]; let mut line: String = String::new(); + let mut col: [u8; RAW_COLEXPR_SIZE] = [0; RAW_COLEXPR_SIZE]; while reader.read_line(&mut line).is_ok() { let len = line.len(); if len == 0 { @@ -446,21 +482,27 @@ impl Palette let off = off + 1; if off > len - 6 { /* no room left for color definition after '#' char */ - panic!("invalid color definition: {}", line); + return Err(io::Error::new( + io::ErrorKind::Other, + format!("invalid color definition: {}", line), + )); } - let col = &line[off..(off + RAW_COLEXPR_SIZE)]; - let (r, g, b) = rgb_of_hex_triplet(col); - pal[pal_idx] = r; - pal[pal_idx + 1] = g; - pal[pal_idx + 2] = b; + col.copy_from_slice( + &line.as_bytes()[off..(off + RAW_COLEXPR_SIZE)], + ); + + let rgb = Rgb::try_from(&col)?; + pal[pal_idx] = rgb.r(); + pal[pal_idx + 1] = rgb.g(); + pal[pal_idx + 2] = rgb.b(); pal_idx = (pal_idx + 3) % PALETTE_BYTES; } } line.truncate(0); } - Self(pal) + Ok(Self(pal)) } #[allow(rustdoc::invalid_rust_codeblocks)] @@ -500,7 +542,7 @@ impl Palette Ok(()) } - pub fn from_file(fname: &Path) -> Self + pub fn from_file(fname: &Path) -> io::Result { /* Check if file exists */ @@ -519,7 +561,7 @@ impl Palette /* [Palette::from_file] */ - pub fn from_stdin() -> Self + pub fn from_stdin() -> io::Result { let mut reader = std::io::BufReader::new(std::io::stdin()); @@ -570,15 +612,18 @@ impl fmt::Debug for Palette } /* [impl fmt::Debug for Palette] */ /** Obtain a ``Palette`` from a ``Scheme``. */ -impl From<&Scheme> for Palette +impl TryFrom<&Scheme> for Palette { - fn from(scm: &Scheme) -> Self + type Error = io::Error; + + fn try_from(scm: &Scheme) -> io::Result { match scm { - Scheme::Builtin(Builtin { palette, .. }) => Self::from(*palette), + Scheme::Builtin(Builtin { palette, .. }) => + Ok(Self::from(*palette)), Scheme::Custom(None) => Self::from_stdin(), Scheme::Custom(Some(ref fname)) => Self::from_file(fname), - Scheme::Palette(pal) => pal.clone(), + Scheme::Palette(pal) => Ok(pal.clone()), } } } @@ -591,11 +636,11 @@ impl From<&RawPalette<'_>> for Palette let mut idx: usize = 0; let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES]; - for def in colors.iter() { - let (r, g, b) = rgb_of_hex_triplet(*def); - pal[idx] = r; - pal[idx + 1] = g; - pal[idx + 2] = b; + for &def in colors.iter() { + let rgb = Rgb::from(def); + pal[idx] = rgb.r(); + pal[idx + 1] = rgb.g(); + pal[idx + 2] = rgb.b(); //println!(">> {} -> {:X} {:X} {:X}", def, r, g, b); idx += 3; } @@ -715,7 +760,7 @@ impl Console #[inline] pub fn apply_scheme(&self, scm: &Scheme) -> io::Result<()> { - self.apply_palette(&Palette::from(scm)) + self.apply_palette(&Palette::try_from(scm)?) } } diff --git a/src/vtcol.rs b/src/vtcol.rs index d3399fc..b0c4b85 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -187,11 +187,11 @@ impl<'a> Job ) }), Scheme::Custom(None) => - Palette::from_stdin().dump(&mut out).map_err(|e| { + Palette::from_stdin()?.dump(&mut out).map_err(|e| { anyhow!("error loading palette from stdin: {}", e) }), Scheme::Custom(Some(fname)) => - Palette::from_file(&fname).dump(&mut out).map_err(|e| { + Palette::from_file(&fname)?.dump(&mut out).map_err(|e| { anyhow!( "error loading palette from file [{}]: {}", fname.display(), @@ -251,7 +251,7 @@ impl<'a> Job let fd = Console::current()?; vrb!("console fd: {}", fd); - if fd.current_palette()? == Palette::from(&one) { + if fd.current_palette()? == Palette::try_from(&one)? { Self::set_scheme(two) } else { Self::set_scheme(one) -- cgit v1.2.3