add from brailie conversion

This commit is contained in:
Wroclaw 2024-07-31 15:53:22 +02:00
parent 332fc79a18
commit 9b6d645b70
2 changed files with 222 additions and 1 deletions

View file

@ -0,0 +1,105 @@
use std::{env, process::exit};
use binary_braillie::binary_braillie_to_bytes;
mod common;
use common::argument_parsing;
fn main() {
let args = parse_args();
if args.value_to_convert.len() <= 0 {
print!("{}: No input specified!", args.program_name)
}
let decoded_ = binary_braillie_to_bytes(
if !args.reverse_characters {
args.value_to_convert
} else {
args.value_to_convert.chars().rev().collect()
},
args.mode.try_into().unwrap()
);
let decoded = match decoded_ {
Ok(e) => e,
Err(()) => {
print!("{}: Invalid input provided", args.program_name);
exit(128);
}
};
if args.hexadecimal {
print!("{}", hex::encode(decoded));
} else {
print!("{}", match String::from_utf8(decoded) {
Ok(e) => e,
Err(e) => {
print!("{}: decoded string is invalid: {}", args.program_name, e.utf8_error());
exit(130);
}
});
}
}
fn parse_args() -> argument_parsing::Arguments {
let mut args = env::args().peekable();
let mut rvalue = argument_parsing::Arguments {
hexadecimal: false,
mode: 0,
program_name: args.next().unwrap_or(String::from("t2br")),
reverse_characters: false,
value_to_convert: String::new()
};
let program_name = &rvalue.program_name;
while args.peek() != None {
let arg = args.next().unwrap();
if arg == "--help"
|| arg == "-h"
|| arg == "-?"
{
print_help(rvalue.program_name);
exit(1);
}
else if arg == "--hex" {
rvalue.hexadecimal = true;
}
else if arg == "--direction" {
match argument_parsing::parse_direction(&mut args, &rvalue, arg) {
Ok(e) => rvalue.mode = e,
Err(e) => {
print!("{}: {}", program_name, e);
exit(64);
}
}
}
else if arg == "--wrap" {
match argument_parsing::parse_wrap(&mut args, &rvalue, arg) {
Ok(e) => rvalue.mode = e,
Err(e) => {
print!("{}: {}", program_name, e);
exit(65);
}
}
}
else if arg == "-r"
|| arg == "--reverse" {
rvalue.reverse_characters = true;
}
else {
rvalue.value_to_convert.push_str(&arg);
}
}
return rvalue;
}
fn print_help(program_name: String) {
print!("Usage: {program_name} [options] <input>\n");
print!("Convert binary represented in braillie characters to readable text\n\n");
print!(" --hex convert to hexadecimal instead of text\n\n");
print!(" --direction [mode] direction of bits per character\n");
print!(" possible values: row, row-reverse, column, column-reverse\n\n");
print!(" --wrap [mode] direction of bits wrapping per character\n");
print!(" possible values: normal, reverse\n\n");
print!(" -r, --reverse reverse outputted characters\n\n");
print!(" -h, -?, --help display this help and exit");
}

View file

@ -81,9 +81,49 @@ pub fn to_binary_braillie_str(input: impl AsRef<str>, mode: EncodeOrientation) -
return to_binary_braillie(input.as_ref().as_bytes(), input.as_ref().len(), mode);
}
pub fn binary_braillie_char_to_index(input: char, mode: EncodeOrientation) -> Result<u8, ()>{
if !(0x2800 <= input as u32 && input as u32 <= 0x28ff) { return Err(()) }
let mapping = MAPPINGS[mode as usize];
let _index: u8 = (input as u32 - 0x2800) as u8;
return Ok(
((_index >> mapping[7]) & 1) << 0
| ((_index >> mapping[6]) & 1) << 1
| ((_index >> mapping[5]) & 1) << 2
| ((_index >> mapping[4]) & 1) << 3
| ((_index >> mapping[3]) & 1) << 4
| ((_index >> mapping[2]) & 1) << 5
| ((_index >> mapping[1]) & 1) << 6
| ((_index >> mapping[0]) & 1) << 7
);
}
pub fn binary_braillie_to_bytes(
input: impl AsRef<str>,
mode: EncodeOrientation
) -> Result<Vec<u8>, ()> {
let mut rvalue: Vec<u8> = Vec::with_capacity(input.as_ref().chars().count());
for char in input.as_ref().chars() {
rvalue.push(match binary_braillie_char_to_index(char, mode) {
Ok(e) => e,
Err(e) => return Err(e),
})
}
return Ok(rvalue);
}
pub fn binary_braillie_to_str(input: impl AsRef<str>, mode: EncodeOrientation) -> Result<String, ()> {
let bytes = match binary_braillie_to_bytes(input, mode) {
Ok(e) => e,
Err(e) => return Err(e)
};
return match String::from_utf8(bytes) {
Ok(e) => Ok(e),
Err(_e) => Err(())
}
}
#[cfg(test)]
mod test_lib {
mod test_lib_to_braillie {
use crate::{index_to_braillie_char, to_binary_braillie_str, EncodeOrientation};
#[test]
@ -146,3 +186,79 @@ mod test_lib {
);
}
}
#[cfg(test)]
mod test_lib_from_braillie {
use crate::{binary_braillie_char_to_index, EncodeOrientation};
#[test]
fn check_characters_out_of_range() {
for i in 0..0x10ffff {
if 0x2800 <= i && i <= 0x28ff { continue; };
let char = match char::from_u32(i) {
Some(c) => c,
// Continue for invalid characters
None => continue,
};
binary_braillie_char_to_index(char, EncodeOrientation::Rows)
.expect_err("Expected error for invalid char");
}
}
#[test]
fn check_characters_in_range() {
for _char in 0x2800..0x28ff {
let char = char::from_u32(_char).unwrap();
binary_braillie_char_to_index(char, EncodeOrientation::Rows)
.expect("Expected no error");
}
}
}
#[cfg(test)]
mod test_lib_all {
use crate::{
binary_braillie_char_to_index,
binary_braillie_to_bytes,
index_to_braillie_char,
to_binary_braillie,
EncodeOrientation
};
#[test]
fn check_coding_multiple() {
for i in 0x00..0xff {
let mut as_char = index_to_braillie_char(
i,
EncodeOrientation::Rows
);
for _ in 0..10 {
let as_index = binary_braillie_char_to_index(
as_char,
EncodeOrientation::Rows
).unwrap();
assert_eq!(as_index, i);
as_char = index_to_braillie_char(as_index, EncodeOrientation::Rows)
}
}
}
#[test]
fn check_coding_multiple_bytes() {
for i in 0x00..0xff {
let mut as_str = index_to_braillie_char(i, EncodeOrientation::Rows).to_string();
for _ in 0..10 {
let as_bytes = binary_braillie_to_bytes(
as_str,
EncodeOrientation::Rows
).unwrap();
assert_eq!(i, as_bytes[0]);
as_str = to_binary_braillie(
&as_bytes,
as_bytes.len(),
EncodeOrientation::Rows
).to_string()
}
}
}
}