Compare commits
3 commits
b5906e1b06
...
7f48d09def
Author | SHA1 | Date | |
---|---|---|---|
7f48d09def | |||
9b6d645b70 | |||
332fc79a18 |
6 changed files with 280 additions and 31 deletions
|
@ -5,6 +5,7 @@ pkgs.mkShell {
|
||||||
cargo
|
cargo
|
||||||
rustc
|
rustc
|
||||||
rustfmt
|
rustfmt
|
||||||
|
gdb
|
||||||
];
|
];
|
||||||
|
|
||||||
RUST_BACKTRACE = 1;
|
RUST_BACKTRACE = 1;
|
||||||
|
|
41
src/bin/common/argument_parsing.rs
Normal file
41
src/bin/common/argument_parsing.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
pub struct Arguments {
|
||||||
|
pub hexadecimal: bool,
|
||||||
|
pub mode: u8,
|
||||||
|
pub program_name: String,
|
||||||
|
pub reverse_characters: bool,
|
||||||
|
pub value_to_convert: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_direction(args: &mut impl Iterator<Item = String>, opts: &Arguments, current_arg: String) -> Result<u8, String>{
|
||||||
|
let mut rvalue = opts.mode;
|
||||||
|
let direction = match args.next() {
|
||||||
|
None => return Err(format!("argument for {} was not provided", current_arg)),
|
||||||
|
Some(e) => e,
|
||||||
|
};
|
||||||
|
match direction.as_str() {
|
||||||
|
"row" => { rvalue &= !(1 << 1) ; rvalue &= !(1 << 2); }
|
||||||
|
"row-reverse" => { rvalue |= 1 << 1 ; rvalue &= !(1 << 2); }
|
||||||
|
"column" => { rvalue &= !(1 << 1) ; rvalue |= 1 << 2 ; }
|
||||||
|
"column-reverse" => { rvalue |= 1 << 1 ; rvalue |= 1 << 2 ; }
|
||||||
|
_ => return Err(
|
||||||
|
format!("invalid direction \"{}\" provided for {}", direction, current_arg)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
return Ok(rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_wrap(args: &mut impl Iterator<Item = String>, opts: &Arguments, current_arg: String) -> Result<u8, String>{
|
||||||
|
let mut rvalue = opts.mode;
|
||||||
|
let wrap = match args.next() {
|
||||||
|
None => return Err(format!("argument for {} was not provided", current_arg)),
|
||||||
|
Some(e) => e,
|
||||||
|
};
|
||||||
|
match wrap.as_str() {
|
||||||
|
"normal" => rvalue &= !(1 << 0),
|
||||||
|
"reverse" => rvalue |= 1 << 0,
|
||||||
|
_ => return Err(
|
||||||
|
format!("invalid wrap \"{}\" provided for {}", wrap, current_arg)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
return Ok(rvalue);
|
||||||
|
}
|
1
src/bin/common/mod.rs
Normal file
1
src/bin/common/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod argument_parsing;
|
105
src/bin/convert_from_baillie.rs
Normal file
105
src/bin/convert_from_baillie.rs
Normal 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");
|
||||||
|
}
|
|
@ -3,6 +3,9 @@ use std::process::exit;
|
||||||
|
|
||||||
use binary_braillie::to_binary_braillie;
|
use binary_braillie::to_binary_braillie;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
use common::argument_parsing;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = parse_args();
|
let args = parse_args();
|
||||||
if args.value_to_convert.len() <= 0 {
|
if args.value_to_convert.len() <= 0 {
|
||||||
|
@ -24,17 +27,11 @@ fn main() {
|
||||||
print!("{}", to_binary_braillie(&value, value.len(), args.mode.try_into().unwrap()))
|
print!("{}", to_binary_braillie(&value, value.len(), args.mode.try_into().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Arguments {
|
|
||||||
pub hexadecimal: bool,
|
|
||||||
pub mode: u8,
|
|
||||||
pub program_name: String,
|
|
||||||
pub reverse_characters: bool,
|
|
||||||
pub value_to_convert: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_args() -> Arguments {
|
|
||||||
|
fn parse_args() -> argument_parsing::Arguments {
|
||||||
let mut args = env::args().peekable();
|
let mut args = env::args().peekable();
|
||||||
let mut rvalue = Arguments {
|
let mut rvalue = argument_parsing::Arguments {
|
||||||
hexadecimal: false,
|
hexadecimal: false,
|
||||||
mode: 0,
|
mode: 0,
|
||||||
program_name: args.next().unwrap_or(String::from("t2br")),
|
program_name: args.next().unwrap_or(String::from("t2br")),
|
||||||
|
@ -57,31 +54,19 @@ fn parse_args() -> Arguments {
|
||||||
rvalue.hexadecimal = true;
|
rvalue.hexadecimal = true;
|
||||||
}
|
}
|
||||||
else if arg == "--direction" {
|
else if arg == "--direction" {
|
||||||
let direction = args.next().unwrap_or_else(|| {
|
match argument_parsing::parse_direction(&mut args, &rvalue, arg) {
|
||||||
println!("{}: argument for {} was not provided", program_name, arg);
|
Ok(e) => rvalue.mode = e,
|
||||||
exit(64);
|
Err(e) => {
|
||||||
});
|
print!("{}: {}", program_name, e);
|
||||||
match direction.as_str() {
|
exit(64);
|
||||||
"row" => { rvalue.mode &= !(1 << 1) ; rvalue.mode &= !(1 << 2); }
|
|
||||||
"row-reverse" => { rvalue.mode |= 1 << 1 ; rvalue.mode &= !(1 << 2); }
|
|
||||||
"column" => { rvalue.mode &= !(1 << 1) ; rvalue.mode |= 1 << 2 ; }
|
|
||||||
"column-reverse" => { rvalue.mode |= 1 << 1 ; rvalue.mode |= 1 << 2 ; }
|
|
||||||
_ => {
|
|
||||||
println!("{}: invalid direction \"{}\" provided", program_name, direction);
|
|
||||||
exit(65);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if arg == "--wrap" {
|
else if arg == "--wrap" {
|
||||||
let wrap = args.next().unwrap_or_else(|| {
|
match argument_parsing::parse_wrap(&mut args, &rvalue, arg) {
|
||||||
println!("{}: argument for {} was not provided", program_name, arg);
|
Ok(e) => rvalue.mode = e,
|
||||||
exit(64);
|
Err(e) => {
|
||||||
});
|
print!("{}: {}", program_name, e);
|
||||||
match wrap.as_str() {
|
|
||||||
"normal" => rvalue.mode &= !(1 << 0),
|
|
||||||
"reverse" => rvalue.mode |= 1 << 0,
|
|
||||||
_ => {
|
|
||||||
println!("{}: invalid wrap \"{}\" provided", program_name, wrap);
|
|
||||||
exit(65);
|
exit(65);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
118
src/lib.rs
118
src/lib.rs
|
@ -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);
|
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)]
|
#[cfg(test)]
|
||||||
mod test_lib {
|
mod test_lib_to_braillie {
|
||||||
use crate::{index_to_braillie_char, to_binary_braillie_str, EncodeOrientation};
|
use crate::{index_to_braillie_char, to_binary_braillie_str, EncodeOrientation};
|
||||||
|
|
||||||
#[test]
|
#[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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue