use crate::format::Format;
use std::io::{self, Write};
pub fn offset(b: u64) -> String {
format!("{:#08x}", b)
}
pub fn print_offset(w: &mut impl Write, b: u64) -> io::Result<()> {
write!(w, "{}: ", offset(b))
}
pub fn print_byte(
w: &mut impl Write,
b: u8,
format: Format,
colorize: bool,
prefix: bool,
) -> io::Result<()> {
let fmt_string = format
.format(b, prefix)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
if colorize {
let color = byte_to_color(b);
write!(
w,
"{} ",
ansi_term::Style::new()
.fg(ansi_term::Color::Fixed(color))
.paint(fmt_string)
)
} else {
write!(w, "{} ", fmt_string)
}
}
pub fn byte_to_color(b: u8) -> u8 {
let mut color: u8 = b;
if color < 1 {
color = 0x16;
}
color
}
pub fn append_ascii(target: &mut Vec<u8>, b: u8, colorize: bool) {
let char = match b > 31 && b < 127 {
true => b as char,
false => '.',
};
if colorize {
let string = ansi_term::Style::new()
.fg(ansi_term::Color::Fixed(byte_to_color(b)))
.paint(char.to_string());
target.extend(format!("{}", string).as_bytes());
} else {
target.extend(format!("{}", char).as_bytes());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::format::Format;
use std::io;
#[test]
fn test_offset() {
let b: u64 = 0x6;
assert_eq!(offset(b), "0x000006");
assert_eq!(offset(b), format!("{:#08x}", b));
}
#[test]
fn test_offset_zero() {
assert_eq!(offset(0), "0x000000");
}
#[test]
fn test_offset_max() {
assert_eq!(offset(0xFFFFFFFF), "0xffffffff");
}
#[test]
fn test_print_offset() {
let mut buffer = Vec::new();
print_offset(&mut buffer, 0x42).unwrap();
let output = String::from_utf8(buffer).unwrap();
assert_eq!(output, "0x000042: ");
}
#[test]
fn test_print_byte_with_invalid_format() {
let mut buffer = Vec::new();
let result = print_byte(&mut buffer, 0x42, Format::Pointer, false, true);
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
}
#[test]
fn test_print_byte_with_valid_format() {
let mut buffer = Vec::new();
let result = print_byte(&mut buffer, 0x42, Format::LowerHex, false, true);
assert!(result.is_ok());
let output = String::from_utf8(buffer).unwrap();
assert!(output.contains("0x42"));
}
#[test]
fn test_print_byte_formats() {
let mut buffer = Vec::new();
print_byte(&mut buffer, 0xFF, Format::LowerHex, false, true).unwrap();
let output = String::from_utf8(buffer).unwrap();
assert!(output.contains("0xff"));
let mut buffer2 = Vec::new();
print_byte(&mut buffer2, 0xFF, Format::UpperHex, false, true).unwrap();
let output2 = String::from_utf8(buffer2).unwrap();
assert!(output2.contains("0xFF"));
let mut buffer3 = Vec::new();
print_byte(&mut buffer3, 0xFF, Format::Octal, false, true).unwrap();
let output3 = String::from_utf8(buffer3).unwrap();
assert!(output3.contains("0o0377"));
let mut buffer4 = Vec::new();
print_byte(&mut buffer4, 0xFF, Format::Binary, false, true).unwrap();
let output4 = String::from_utf8(buffer4).unwrap();
assert!(output4.contains("0b11111111"));
}
#[test]
fn test_print_byte_prefix() {
let mut buffer = Vec::new();
print_byte(&mut buffer, 0x42, Format::LowerHex, false, true).unwrap();
let with_prefix = String::from_utf8(buffer).unwrap();
assert!(with_prefix.contains("0x42"));
let mut buffer2 = Vec::new();
print_byte(&mut buffer2, 0x42, Format::LowerHex, false, false).unwrap();
let without_prefix = String::from_utf8(buffer2).unwrap();
assert!(without_prefix.contains("42"));
assert!(!without_prefix.contains("0x"));
}
#[test]
fn test_byte_to_color_zero() {
assert_eq!(byte_to_color(0), 0x16);
}
#[test]
fn test_byte_to_color_non_zero() {
assert_eq!(byte_to_color(1), 1);
assert_eq!(byte_to_color(42), 42);
assert_eq!(byte_to_color(255), 255);
}
#[test]
fn test_byte_to_color_edge_cases() {
assert_eq!(byte_to_color(0), 0x16);
assert_eq!(byte_to_color(1), 1);
assert_eq!(byte_to_color(255), 255);
}
#[test]
fn test_append_ascii_printable() {
let mut buffer = Vec::new();
append_ascii(&mut buffer, b'A', false);
assert_eq!(buffer, b"A");
}
#[test]
fn test_append_ascii_non_printable() {
let mut buffer = Vec::new();
append_ascii(&mut buffer, 0x00, false);
assert_eq!(buffer, b".");
let mut buffer2 = Vec::new();
append_ascii(&mut buffer2, 0x1F, false);
assert_eq!(buffer2, b".");
let mut buffer3 = Vec::new();
append_ascii(&mut buffer3, 0x7F, false);
assert_eq!(buffer3, b".");
}
#[test]
fn test_append_ascii_boundaries() {
let mut buffer = Vec::new();
append_ascii(&mut buffer, 31, false);
assert_eq!(buffer, b".");
let mut buffer = Vec::new();
append_ascii(&mut buffer, 32, false);
assert_eq!(buffer, b" ");
let mut buffer = Vec::new();
append_ascii(&mut buffer, 126, false);
assert_eq!(buffer, b"~");
let mut buffer = Vec::new();
append_ascii(&mut buffer, 127, false);
assert_eq!(buffer, b".");
}
#[test]
fn test_append_ascii_no_color() {
let mut buffer = Vec::new();
append_ascii(&mut buffer, b'X', false);
assert_eq!(buffer, b"X");
}
#[test]
fn test_append_ascii_multiple() {
let mut buffer = Vec::new();
append_ascii(&mut buffer, b'H', false);
append_ascii(&mut buffer, b'e', false);
append_ascii(&mut buffer, b'l', false);
append_ascii(&mut buffer, b'l', false);
append_ascii(&mut buffer, b'o', false);
assert_eq!(buffer, b"Hello");
}
}