Skip to content

Commit

Permalink
Add bytestr, charset and unicode modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
vikpe committed May 3, 2024
1 parent 7c71e2e commit 7322502
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 7 deletions.
8 changes: 1 addition & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ license = "MIT"
include = [
"/Cargo.toml",
"/README.md",
"/benches/**",
"/src/**",
"/tests/**",
]
Expand All @@ -19,12 +18,7 @@ include = [
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.82"
lazy_static = "1.4.0"

[dev-dependencies]
criterion = { version = "0.5.1", default-features = false }
pretty_assertions = "1.4.0"

[[bench]]
name = "bench_lib"
harness = false
46 changes: 46 additions & 0 deletions src/bytestr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::charset::ASCII_TABLE;
use crate::unicode;

pub fn to_ascii(bytes: &[u8]) -> String {
bytes
.iter()
.cloned()
.map(|b| char::from(ASCII_TABLE[b as usize]))
.collect::<String>()
.to_string()
}

pub fn to_unicode(bytes: &[u8]) -> String {
bytes
.iter()
.cloned()
.map(char::from)
.collect::<String>()
.to_string()
}

pub fn to_utf8(bytes: &[u8]) -> String {
unicode::to_utf8(&to_unicode(bytes))
}

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;

use super::*;

#[test]
fn test_to_ascii() {
assert_eq!(to_ascii(&[5, 225, 248, 229]), "_axe");
}

#[test]
fn test_to_unicode() {
assert_eq!(to_unicode(&[225, 248, 229]), "áøå");
}

#[test]
fn test_to_utf8() {
assert_eq!(to_utf8(&[5, 225, 248, 229]), "•axe");
}
}
163 changes: 163 additions & 0 deletions src/charset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use lazy_static::lazy_static;

lazy_static! {
pub static ref ASCII_TABLE: Vec<u8> = {
const ASCII_TABLE: &str = "________________[]0123456789____ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~_________________[]0123456789____ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~_";
ASCII_TABLE.as_bytes().to_vec()
};
}

#[derive(Debug, PartialEq)]
pub enum CharColor {
Brown,
Green,
White,
}

impl CharColor {
pub fn from_char(c: char) -> Option<Self> {
Self::from_byte(c as u8)
}

fn from_byte(b: u8) -> Option<Self> {
let row_index = b / 16;
let col_index = b % 16;

// ascii
match row_index {
2..=7 => return Some(CharColor::White),
10..=15 => return Some(CharColor::Brown),
1 | 9 if (2..=11).contains(&col_index) => return Some(CharColor::Green),
_ => {}
}

// chars
match row_index {
// white
0 if [0, 5, 11, 14, 15].contains(&col_index) => Some(CharColor::White),
1 if col_index == 12 => Some(CharColor::White),

// brown
0 if col_index == 13 => Some(CharColor::Brown),
1 | 9 if (0..=1).contains(&col_index) => Some(CharColor::Brown),
8 if [11, 13].contains(&col_index) => Some(CharColor::Brown),

// green
8 if [5, 14, 15].contains(&col_index) => Some(CharColor::Green),
9 if col_index == 12 => Some(CharColor::Green),
_ => None,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_char_color() {
let mut test_cases = vec![];

// row 1
test_cases.extend([
Some(CharColor::White),
None,
None,
None,
None,
Some(CharColor::White),
None,
None,
None,
None,
None,
Some(CharColor::White),
None,
Some(CharColor::Brown),
Some(CharColor::White),
Some(CharColor::White),
]);

// row 2
test_cases.extend([
Some(CharColor::Brown),
Some(CharColor::Brown),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::White),
None,
None,
None,
]);

// row 3-8
for _ in 0..6 * 16 {
test_cases.push(Some(CharColor::White));
}

// row 9
test_cases.extend([
None,
None,
None,
None,
None,
Some(CharColor::Green),
None,
None,
None,
None,
None,
Some(CharColor::Brown),
None,
Some(CharColor::Brown),
Some(CharColor::Green),
Some(CharColor::Green),
]);

// row 10
test_cases.extend([
Some(CharColor::Brown),
Some(CharColor::Brown),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
Some(CharColor::Green),
None,
None,
None,
]);

// row 1-16
for _ in 0..6 * 16 {
test_cases.push(Some(CharColor::Brown));
}

for (byte, expected) in test_cases.iter().enumerate() {
assert_eq!(
CharColor::from_byte(byte as u8),
*expected,
"{} [{},{}] = {:?}",
byte,
byte as u8 % 16,
byte as u8 / 16,
expected,
);
}
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod bytestr;
pub mod charset;
pub mod unicode;
49 changes: 49 additions & 0 deletions src/unicode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::bytestr;

pub fn to_ascii(ustr: &str) -> String {
bytestr::to_ascii(&to_bytestr(ustr))
}

pub fn to_utf8(ustr: &str) -> String {
to_bytestr(ustr)
.iter()
.map(|c| c & 127) // strip color
.map(|c| match c {
32..=126 => char::from(c),
0 | 5 | 14 | 15 | 28 => '•',
_ => ' ',
})
.collect()
}

pub fn to_bytestr(value: &str) -> Vec<u8> {
value.chars().map(|c| c as u8).collect::<Vec<u8>>()
}

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;

use super::*;

#[test]
fn test_to_ascii() {
assert_eq!(to_ascii("áøå"), "axe");
}

#[test]
fn test_to_utf8() {
assert_eq!(to_utf8("áøå"), "axe");

let ascii_chars = (32..=126).map(char::from).collect::<String>();
assert_eq!(to_utf8(&ascii_chars), ascii_chars);

let mixed_chars = (28..=40).map(char::from).collect::<String>();
assert_eq!(to_utf8(&mixed_chars), "• !\"#$%&'(");
}

#[test]
fn test_to_bstr() {
assert_eq!(to_bytestr("áøå"), vec![225, 248, 229]);
}
}

0 comments on commit 7322502

Please sign in to comment.