//! Text conversion utilities. /// Dumps a slice of memory as text to stderr. pub fn dump_mem(b: &[u8]) { let mut p = 0; for &c in b { if p + 3 > 79 { eprintln!(""); p = 0; } if c.is_ascii_graphic() { eprint!(" {} ", c as char); } else { eprint!("{:02X} ", c); } p += 3; } eprintln!(""); } /// Formats a binary size string for any given number. pub fn to_binsize(n: u64) -> String { const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"]; // empty size if n == 0 { return String::from("empty"); } // terabytes, gigabytes, megabytes, kilobytes for i in (1..=4).rev() { if n >= 1000u64.pow(i) { let x = n as f64 / 1000f64.powi(i as i32); return format!("{:1}{}", x, NAMES[i as usize - 1]); } } // or, just bytes format!("{} {}", n, if n != 1 {"bytes"} else {"byte"}) } /// Encodes or decodes a string in the terminal encryption format. pub fn fuck_string(s: &[u8]) -> Vec { let mut v = s.to_vec(); let l = s.len(); let mut p = 0; for _ in 0..l / 4 { p += 2; v[p] ^= 0xfe; v[p + 1] ^= 0xed; p += 2; } for _ in 0..l % 4 { v[p] ^= 0xfe; p += 1; } v } /// Converts input from Mac Roman to a Unicode string. pub fn mac_roman_conv(s: &[u8]) -> String { let mut v = String::with_capacity(s.len()); for i in 0..s.len() { if s[i] == 0 { break; } else if s[i] & 0x80 != 0 { v.push(TR[s[i] as usize & 0x7f]); } else if s[i] == b'\r' { v.push('\n'); } else { v.push(s[i] as char); } } v } const TR: [char; 128] = ['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}', '\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}', '\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}', '\u{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}', '\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}', '\u{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}', '\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}', '\u{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}', '\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}', '\u{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}', '\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}', '\u{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}', '\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}', '\u{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}', '\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}', '\u{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}', '\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}', '\u{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}', '\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}', '\u{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}', '\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}', '\u{02db}', '\u{02c7}']; #[test] fn to_binsize_integrals() { assert_eq!(to_binsize(0), "empty"); assert_eq!(to_binsize(1), "1 byte"); assert_eq!(to_binsize(2), "2 bytes"); assert_eq!(to_binsize(999), "999 bytes"); assert_eq!(to_binsize(1000), "1kB"); assert_eq!(to_binsize(1000 * 7), "7kB"); assert_eq!(to_binsize(1000 * 1000), "1MB"); assert_eq!(to_binsize(1000 * 1000 * 7), "7MB"); assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB"); assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB"); assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000), "1TB"); assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB"); } #[test] fn mac_roman_conv_basic_marathon_stuff() { assert_eq!(mac_roman_conv(b"p\x8cth"), "påth"); assert_eq!(mac_roman_conv(b"I\xd5ve"), "I’ve"); } // EOF