pub(crate) mod input;
pub use input::*;
use std::io::{self, BufReader, Read, Write};
use anstyle::{AnsiColor, Reset};
pub enum Base {
Binary,
Octal,
Decimal,
Hexadecimal,
}
#[derive(PartialEq, Eq)]
#[repr(usize)]
enum ByteColor {
Null = 0,
Offset = 1,
AsciiPrintable = 2,
AsciiWhitespace = 3,
AsciiOther = 4,
NonAscii = 5,
Reset = 6,
}
const COLOR_NULL: AnsiColor = AnsiColor::BrightBlack;
const COLOR_OFFSET: AnsiColor = AnsiColor::BrightBlack;
const COLOR_ASCII_PRINTABLE: AnsiColor = AnsiColor::Cyan;
const COLOR_ASCII_WHITESPACE: AnsiColor = AnsiColor::Green;
const COLOR_ASCII_OTHER: AnsiColor = AnsiColor::Magenta;
const COLOR_NONASCII: AnsiColor = AnsiColor::Yellow;
pub enum ByteCategory {
Null,
AsciiPrintable,
AsciiWhitespace,
AsciiOther,
NonAscii,
}
#[derive(PartialEq)]
enum Squeezer {
Print,
Delete,
Ignore,
Disabled,
}
#[derive(Copy, Clone)]
struct Byte(u8);
impl Byte {
fn category(self) -> ByteCategory {
if self.0 == 0x00 {
ByteCategory::Null
} else if self.0.is_ascii_graphic() {
ByteCategory::AsciiPrintable
} else if self.0.is_ascii_whitespace() {
ByteCategory::AsciiWhitespace
} else if self.0.is_ascii() {
ByteCategory::AsciiOther
} else {
ByteCategory::NonAscii
}
}
fn color(self) -> ByteColor {
use crate::ByteCategory::*;
match self.category() {
Null => ByteColor::Null,
AsciiPrintable => ByteColor::AsciiPrintable,
AsciiWhitespace => ByteColor::AsciiWhitespace,
AsciiOther => ByteColor::AsciiOther,
NonAscii => ByteColor::NonAscii,
}
}
fn as_char(self) -> char {
use crate::ByteCategory::*;
match self.category() {
Null => '0',
AsciiPrintable => self.0 as char,
AsciiWhitespace if self.0 == 0x20 => ' ',
AsciiWhitespace => '_',
AsciiOther => '•',
NonAscii => '×',
}
}
}
struct BorderElements {
left_corner: char,
horizontal_line: char,
column_separator: char,
right_corner: char,
}
#[derive(Clone, Copy)]
pub enum BorderStyle {
Unicode,
Ascii,
None,
}
impl BorderStyle {
fn header_elems(&self) -> Option<BorderElements> {
match self {
BorderStyle::Unicode => Some(BorderElements {
left_corner: '┌',
horizontal_line: '─',
column_separator: '┬',
right_corner: '┐',
}),
BorderStyle::Ascii => Some(BorderElements {
left_corner: '+',
horizontal_line: '-',
column_separator: '+',
right_corner: '+',
}),
BorderStyle::None => None,
}
}
fn footer_elems(&self) -> Option<BorderElements> {
match self {
BorderStyle::Unicode => Some(BorderElements {
left_corner: '└',
horizontal_line: '─',
column_separator: '┴',
right_corner: '┘',
}),
BorderStyle::Ascii => Some(BorderElements {
left_corner: '+',
horizontal_line: '-',
column_separator: '+',
right_corner: '+',
}),
BorderStyle::None => None,
}
}
fn outer_sep(&self) -> char {
match self {
BorderStyle::Unicode => '│',
BorderStyle::Ascii => '|',
BorderStyle::None => ' ',
}
}
fn inner_sep(&self) -> char {
match self {
BorderStyle::Unicode => '┊',
BorderStyle::Ascii => '|',
BorderStyle::None => ' ',
}
}
}
pub struct PrinterBuilder<'a, Writer: Write> {
writer: &'a mut Writer,
show_color: bool,
show_char_panel: bool,
show_position_panel: bool,
border_style: BorderStyle,
use_squeeze: bool,
panels: u64,
group_bytes: u8,
base: Base,
}
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
pub fn new(writer: &'a mut Writer) -> Self {
PrinterBuilder {
writer,
show_color: true,
show_char_panel: true,
show_position_panel: true,
border_style: BorderStyle::Unicode,
use_squeeze: true,
panels: 2,
group_bytes: 1,
base: Base::Hexadecimal,
}
}
pub fn show_color(mut self, show_color: bool) -> Self {
self.show_color = show_color;