diff options
| author | Philipp Gesang <phg@phi-gamma.net> | 2021-11-16 19:12:36 +0100 | 
|---|---|---|
| committer | Philipp Gesang <phg@phi-gamma.net> | 2021-11-16 19:14:36 +0100 | 
| commit | 689b732184c227b4f49e2b509fad06c1f31c4e4b (patch) | |
| tree | 9fc5657e20f761333b3df071076175477d76af2e | |
| parent | e1755da9f1c2755f72cbf843dd653c3f6f71c7e8 (diff) | |
| download | vtcol-689b732184c227b4f49e2b509fad06c1f31c4e4b.tar.gz | |
switch RawPalette to integer representation
Introducing a simple type for RGB colors. That awkward string
representation for RawPalette got unwieldy quick.
| -rw-r--r-- | src/lib.rs | 141 | ||||
| -rw-r--r-- | src/vtcol.rs | 6 | 
2 files changed, 96 insertions, 51 deletions
| @@ -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<Palette> for Scheme      }  } -fn nibble_of_char(chr: u8) -> u8 +#[inline] +fn nibble_of_char(chr: u8) -> io::Result<u8>  {      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<Self> +    { +        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<u32> 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<Self>      {          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<Self>      {          /* Check if file exists           */ @@ -519,7 +561,7 @@ impl Palette      /* [Palette::from_file] */ -    pub fn from_stdin() -> Self +    pub fn from_stdin() -> io::Result<Self>      {          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<Self>      {          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) | 
