enc/src/main.rs
2023-10-07 19:33:16 +05:30

105 lines
2.5 KiB
Rust

use std::env;
use tabled::{
builder::Builder,
settings::{Modify, object::Rows, Alignment, Style}
};
struct StringDetail {
characters: Vec<CharacterDetail>,
len: usize,
}
struct CharacterDetail {
byte_index: usize,
character: Option<char>,
byte: u8,
}
impl StringDetail{
fn parse_utf8(query: &String) -> Self {
let mut details:StringDetail = StringDetail::default();
for i in query.chars() {
let mut bytes = [0; 4];
i.encode_utf8(&mut bytes);
details.push(Some(i), bytes[0]);
for b in 1..i.len_utf8() {
details.push(None, bytes[b]);
}
}
details
}
fn default() -> Self {
Self { characters: Vec::new(), len: 0 }
}
fn push(&mut self, character:Option<char>, byte:u8){
self.characters
.push(CharacterDetail {
byte_index: self.len,
character,
byte,
});
self.len += 1;
}
fn print_table(&self) {
let mut table_builder = Builder::default();
table_builder.set_header(StringDetail::table_header());
for i in self.table_rows() {
table_builder.push_record(i);
}
let table = table_builder.build()
.with(Style::sharp())
.with(Modify::new(Rows::new(1..)).with(Alignment::left()))
.to_string();
print!("{}", table);
}
fn table_rows(&self) -> Vec<Vec<String>> {
self.characters.iter()
.map(StringDetail::to_table_row)
.collect::<Vec<Vec<_>>>()
}
fn to_table_row(char_detail: &CharacterDetail) -> Vec<String> {
let character: String = match char_detail.character {
Some(x) => String::from(format!("{}", x)),
None => String::from("<..>"),
};
vec![
character,
format!("{}", char_detail.byte_index),
format!("{:02x}", char_detail.byte),
format!("{}", char_detail.byte),
format!("{:08b}", char_detail.byte)]
}
fn table_header() -> Vec<String> {
vec![
String::from("character"),
String::from("byte"),
String::from("hex"),
String::from("dec"),
String::from("bin"),
]
}
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
print!("Usage: enc <string>");
return;
}
let utf8 = StringDetail::parse_utf8(&args[1]);
utf8.print_table();
}