use crate::Byte;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AsciiChar {
binary_value: Byte,
character_code: String,
character_description: String,
character_value: String,
}
impl AsciiChar {
#[must_use]
pub fn new(
byte: Byte,
character_code: &str,
character_description: &str,
character_value: &str,
) -> Self {
let binary_value: Byte = byte;
let character_code: String = character_code.to_string().to_uppercase();
let character_description: String = character_description.to_string();
let character_value: String = character_value.to_string();
Self {
binary_value,
character_code,
character_description,
character_value,
}
}
#[must_use]
pub fn is_control(&self) -> bool {
self.decimal_value() < 32 || self.decimal_value() == 127
}
#[must_use]
pub fn is_printable(&self) -> bool {
self.decimal_value() > 31 && self.decimal_value() < 127
}
#[must_use]
pub fn is_whitespace(&self) -> bool {
self.decimal_value() == 9
|| self.decimal_value() == 10
|| self.decimal_value() == 11
|| self.decimal_value() == 12
|| self.decimal_value() == 13
|| self.decimal_value() == 32
}
#[must_use]
pub fn is_digit(&self) -> bool {
self.decimal_value() > 47 && self.decimal_value() < 58
}
#[must_use]
pub fn is_letter(&self) -> bool {
self.is_lowercase() || self.is_uppercase()
}
#[must_use]
pub fn is_uppercase(&self) -> bool {
self.decimal_value() > 64 && self.decimal_value() < 91
}
#[must_use]
pub fn is_lowercase(&self) -> bool {
self.decimal_value() > 96 && self.decimal_value() < 123
}
#[must_use]
#[allow(clippy::doc_markdown)]
pub fn is_symbol(&self) -> bool {
self.decimal_value() > 32 && self.decimal_value() < 48
|| self.decimal_value() > 57 && self.decimal_value() < 65
|| self.decimal_value() > 90 && self.decimal_value() < 97
|| self.decimal_value() > 122 && self.decimal_value() < 127
}
#[must_use]
pub const fn binary_value(&self) -> Byte {
self.binary_value
}
#[must_use]
pub fn decimal_value(&self) -> u8 {
u8::from(&self.binary_value)
}
#[must_use]
pub fn hexadecimal_value(&self) -> String {
format!("{:#04X}", self.decimal_value())
}
#[must_use]
pub fn character_code(&self) -> String {
self.character_code.clone()
}
#[must_use]
pub fn character_description(&self) -> String {
self.character_description.clone()
}
#[must_use]
pub fn character_value(&self) -> String {
self.character_value.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ascii_char() {
let ascii_char: AsciiChar =
AsciiChar::new(Byte::from(97), "LCA", "Lowercase letter a", "a");
assert_eq!(ascii_char.binary_value(), Byte::from(97));
assert_eq!(ascii_char.decimal_value(), 97);
assert_eq!(ascii_char.hexadecimal_value(), "0x61");
assert_eq!(ascii_char.character_code(), "LCA");
assert_eq!(ascii_char.character_description(), "Lowercase letter a");
assert_eq!(ascii_char.character_value(), "a");
}
#[test]
fn test_ascii_char_is_control() {
let ascii_char: AsciiChar = AsciiChar::new(Byte::from(0), "NUL", "Null character", "\0");
assert!(ascii_char.is_control());
}
#[test]
fn test_ascii_char_is_printable() {
let lca: AsciiChar = AsciiChar::new(Byte::from(97), "LCA", "Lowercase letter a", "a");
let uca: AsciiChar = AsciiChar::new(Byte::from(65), "UCA", "Uppercase letter a", "A");
let symat: AsciiChar = AsciiChar::new(Byte::from(64), "SYMAT", "Symbol At", "@");
let dig1: AsciiChar = AsciiChar::new(Byte::from(49), "DIG1", "Digit one", "1");
let sp: AsciiChar = AsciiChar::new(Byte::from(32), "SP", "Space", " ");
assert!(lca.is_printable());
assert!(uca.is_printable());
assert!(symat.is_printable());
assert!(dig1.is_printable());
assert!(sp.is_printable());
}
#[test]
fn test_ascii_char_is_letter() {
let lca: AsciiChar = AsciiChar::new(Byte::from(97), "LCA", "Lowercase letter a", "a");
let uca: AsciiChar = AsciiChar::new(Byte::from(65), "UCA", "Uppercase letter a", "A");
assert!(lca.is_letter());
assert!(uca.is_letter());
}
#[test]
fn test_ascii_char_is_uppercase() {
let ascii_char: AsciiChar =
AsciiChar::new(Byte::from(65), "UCA", "Uppercase letter a", "A");
assert!(ascii_char.is_uppercase());
assert!(!ascii_char.is_lowercase());
assert!(ascii_char.is_letter());
}
#[test]
fn test_ascii_char_is_lowercase() {
let ascii_char: AsciiChar =
AsciiChar::new(Byte::from(97), "LCA", "Lowercase letter a", "a");
assert!(ascii_char.is_lowercase());
assert!(!ascii_char.is_uppercase());
assert!(ascii_char.is_letter());
}
#[test]
fn test_ascii_char_is_whitespace() {
let whitespace_chars = vec![9, 10, 11, 12, 13, 32];
for &val in &whitespace_chars {
let ascii_char = AsciiChar::new(Byte::from(val), "", "", "");
assert!(
ascii_char.is_whitespace(),
"Character with decimal value {} should be identified as whitespace",
val
);
}
let non_whitespace_char = AsciiChar::new(Byte::from(65), "", "", "");
assert!(
!non_whitespace_char.is_whitespace(),
"Character with decimal value 65 should not be identified as whitespace"
);
}
#[test]
fn test_ascii_char_is_digit() {
let digit_chars = vec![48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
for &val in &digit_chars {
let ascii_char = AsciiChar::new(Byte::from(val), "", "", "");
assert!(
ascii_char.is_digit(),
"Character with decimal value {} should be identified as a digit",
val
);
}
let non_digit_char = AsciiChar::new(Byte::from(65), "", "", "");
assert!(
!non_digit_char.is_digit(),
"Character with decimal value 65 should not be identified as a digit"
);
}
#[test]
fn test_ascii_char_is_symbol() {
let symbol_chars = vec![
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64,
91, 92, 93, 94, 95, 96, 123, 124, 125, 126,
];
for &val in &symbol_chars {
let ascii_char = AsciiChar::new(Byte::from(val), "", "", "");
assert!(
ascii_char.is_symbol(),
"Character with decimal value {} should be identified as a symbol",
val
);
}
let non_symbol_char = AsciiChar::new(Byte::from(65), "", "", "");
assert!(
!non_symbol_char.is_symbol(),
"Character with decimal value 65 should not be identified as a symbol"
);
}
#[test]
fn test_ascii_char_binary_value() {
let ascii_char = AsciiChar::new(Byte::from(97), "", "", "");
assert_eq!(
ascii_char.binary_value(),
Byte::from(97),
"Binary value should be equal to the input value"
);
}
}