xd 0.0.4

tool that dumps binary input in a variety of formats
Documentation
use core::convert::TryInto;
use core::fmt::{self, Display, Formatter, Write};

use owo_colors::OwoColorize;

pub struct Table {
    pub inner: [RichScalar; 256],
    pub requires_rich: bool,
}

#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct Scalar(pub u32);

#[derive(Debug, Clone, Copy)]
pub struct RichScalar {
    pub scalar: Scalar,
    pub reversed: bool,
    pub bold: bool,
    pub dimmed: bool,
}

impl Display for Scalar {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.write_char(self.0.try_into().or(Err(fmt::Error))?)
    }
}

impl RichScalar {
    pub const fn new(scalar: u32) -> Self {
        Self {
            scalar: Scalar(scalar),
            reversed: false,
            bold: false,
            dimmed: false,
        }
    }
    pub const fn reversed(self, reversed: bool) -> Self {
        Self { reversed, ..self }
    }
    pub const fn bold(self, bold: bool) -> Self {
        Self { bold, ..self }
    }
    pub const fn dimmed(self, dimmed: bool) -> Self {
        Self { dimmed, ..self }
    }
}

macro_rules! reversed {
    ($self:ident, $scalar:ident, $($inner:tt)*) => {
        if $self.reversed {
            let $scalar = $scalar.reversed();
            $($inner)*
        } else {
            $($inner)*
        }
    };
}

macro_rules! bold {
    ($self:ident, $scalar:ident, $($inner:tt)*) => {
        if $self.bold {
            let $scalar = $scalar.bold();
            $($inner)*
        } else {
            $($inner)*
        }
    };
}

macro_rules! dimmed {
    ($self:ident, $scalar:ident, $($inner:tt)*) => {
        if $self.dimmed {
            let $scalar = $scalar.dimmed();
            $($inner)*
        } else {
            $($inner)*
        }
    };
}

impl Display for RichScalar {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let scalar = self.scalar;

        reversed!(
            self,
            scalar,
            bold!(
                self,
                scalar,
                dimmed!(self, scalar, Display::fmt(&scalar, f))
            )
        )
    }
}

pub const DEFAULT: Table = {
    let mut result = [RichScalar::new(0); 256];
    let mut byte = 0;

    while byte < 0x100 {
        result[byte] = match (byte, printable(byte as u8), picture(byte as u8)) {
            (0x00, _, Some(x)) => RichScalar::new(x).dimmed(true),
            (_, Some(x), _) => RichScalar::new(x).bold(true),
            (x, _, _) => RichScalar::new(CP437[x] as u32).dimmed(true),
        };

        byte += 1;
    }

    Table {
        inner: result,
        requires_rich: false,
    }
};

pub const CLASSIC: Table = {
    let mut result = [RichScalar::new('.' as u32); 256];
    let mut byte = 0;

    while byte < 0x100 {
        if let Some(x) = printable(byte as u8) {
            result[byte] = RichScalar::new(x);
        }

        byte += 1;
    }

    Table {
        inner: result,
        requires_rich: false,
    }
};

pub const REVERSE: Table = {
    let mut result = [RichScalar::new(0); 256];
    let mut byte = 0;

    while byte < 0x100 {
        let low = byte as u8 & 0x7F;
        result[byte] = match (printable(low), picture(low)) {
            (Some(x), _) => RichScalar::new(x).reversed(byte > 0x7F),
            (_, Some(x)) => RichScalar::new(x).reversed(byte > 0x7F),
            _ => result[byte], // FIXME rust#51999
        };
        byte += 1;
    }

    Table {
        inner: result,
        requires_rich: true,
    }
};

const fn printable(byte: u8) -> Option<u32> {
    match byte {
        x if 0x20 <= x && x < 0x7F => Some(x as u32),
        _ => None,
    }
}

const fn picture(byte: u8) -> Option<u32> {
    match byte {
        x if x < 0x20 => Some('' as u32 + x as u32),
        0x7F => Some('' as u32),
        _ => None,
    }
}

//  (x => (console.log(x),copy(x)))([...document.querySelectorAll("tbody")].map(
//  x => [...x.querySelectorAll("td > small")]).find(x => x.length == 256).map((
//  x, i) => x && String.fromCodePoint(parseInt([...x.childNodes].find(x => x.
//  nodeType == 3).nodeValue, 16))).map(x => `'${{"\0":"\\0","'":"\\'","\\":
//  "\\\\"}[x]??x}',`).reduce(([p, ...q], x) => p.length < 16 ? [[...p, x], ...q
//  ] : [[x], p, ...q], [[]]).reverse().map(x => x.join("")).join("\n"))

#[rustfmt::skip]
const CP437: [char; 256] = [
    // use https://en.wikipedia.org/w/index.php?title=Code_page_437&oldid=978947122
    // not ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT
    // because we want the graphic versions of 01h–1Fh + 7Fh
    '\0','','','','','','','','','','','','','','','',
    '','','','','','§','','','','','','','','','','',
    ' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
    '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
    '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
    'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
    '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
    'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','',
    'Ç','ü','é','â','ä','à','å','ç','ê','ë','è','ï','î','ì','Ä','Å',
    'É','æ','Æ','ô','ö','ò','û','ù','ÿ','Ö','Ü','¢','£','¥','','ƒ',
    'á','í','ó','ú','ñ','Ñ','ª','º','¿','','¬','½','¼','¡','«','»',
    '','','','','','','','','','','','','','','','',
    '','','','','','','','','','','','','','','','',
    '','','','','','','','','','','','','','','','',
    'α','ß','Γ','π','Σ','σ','µ','τ','Φ','Θ','Ω','δ','','φ','ε','',
    '','±','','','','','÷','','°','','·','','','²','',' ',
];