diff --git a/src/bin/convert_from_baillie.rs b/src/bin/convert_from_baillie.rs
new file mode 100644
index 0000000..5e9d353
--- /dev/null
+++ b/src/bin/convert_from_baillie.rs
@@ -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] \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");
+}
diff --git a/src/lib.rs b/src/lib.rs
index 25149a1..23c9c9f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -81,9 +81,49 @@ pub fn to_binary_braillie_str(input: impl AsRef, 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{
+ 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,
+ mode: EncodeOrientation
+) -> Result, ()> {
+ let mut rvalue: Vec = 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, mode: EncodeOrientation) -> Result {
+ 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()
+ }
+ }
+ }
+}