/* 0 3 1 4 2 5 6 7 */ use std::u32; use std::convert::TryFrom; #[derive(Clone, Copy)] #[repr(u8)] pub enum EncodeOrientation { // reverse - points in line ordered backwards (direction) // Backwards - major lines ordered backwards (wrap) Rows = 0b00000000, RowsBackwards = 0b00000001, RowsReverse = 0b00000010, RowsBackwardsReverse = 0b00000011, Columns = 0b00000100, ColumnsBackwards = 0b00000101, ColumnsReverse = 0b00000110, ColumnsBackwardsReverse = 0b00000111, } impl TryFrom for EncodeOrientation { type Error = (); fn try_from(value: u8) -> Result { match value { 0 => Ok(EncodeOrientation::Rows), 1 => Ok(EncodeOrientation::RowsBackwards), 2 => Ok(EncodeOrientation::RowsReverse), 3 => Ok(EncodeOrientation::RowsBackwardsReverse), 4 => Ok(EncodeOrientation::Columns), 5 => Ok(EncodeOrientation::ColumnsBackwards), 6 => Ok(EncodeOrientation::ColumnsReverse), 7 => Ok(EncodeOrientation::ColumnsBackwardsReverse), _ => panic!("Unknown encode orientation provided") } } } const MAPPINGS: [[u8; 8]; 8] = [ [0, 3, 1, 4, 2, 5, 6, 7], [6, 7, 2, 5, 1, 4, 0, 3], [3, 0, 4, 1, 5, 2, 7, 6], [7, 6, 5, 2, 4, 1, 3, 0], [0, 1, 2, 6, 3, 4, 5, 7], [3, 4, 5, 7, 0, 1, 2, 6], [6, 2, 1, 0, 7, 5, 4, 3], [7, 5, 4, 3, 6, 2, 1, 0] ]; pub fn index_to_braillie_char(_index: u8, mode: EncodeOrientation) -> char { let mapping = MAPPINGS[mode as usize]; let index: u8 = ((_index >> 7) & 1) << mapping[0] | ((_index >> 6) & 1) << mapping[1] | ((_index >> 5) & 1) << mapping[2] | ((_index >> 4) & 1) << mapping[3] | ((_index >> 3) & 1) << mapping[4] | ((_index >> 2) & 1) << mapping[5] | ((_index >> 1) & 1) << mapping[6] | ((_index >> 0) & 1) << mapping[7]; return char::from_u32(0x2800 + index as u32).unwrap(); } pub fn to_binary_braillie(input: &[u8], length: usize, mode: EncodeOrientation) -> String { let mut rvalue = String::with_capacity(length); for i in 0..length { rvalue.push(index_to_braillie_char(input[i], mode)); } return rvalue; } pub fn to_binary_braillie_str(input: impl AsRef, mode: EncodeOrientation) -> String { return to_binary_braillie(input.as_ref().as_bytes(), input.as_ref().len(), mode); } #[cfg(test)] mod test_lib { use crate::{index_to_braillie_char, to_binary_braillie_str, EncodeOrientation}; #[test] fn check_characters_in_range() { for i in 0..0xff { let char = index_to_braillie_char(i, EncodeOrientation::Rows); assert!(0x2800 <= char as u32 && char as u32 <= 0x28ff); } } #[test] fn check_individual_bits() { assert_eq!( index_to_braillie_char(0b10000000, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00000001).unwrap() ); assert_eq!( index_to_braillie_char(0b01000000, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00001000).unwrap() ); assert_eq!( index_to_braillie_char(0b00100000, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00000010).unwrap() ); assert_eq!( index_to_braillie_char(0b00010000, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00010000).unwrap() ); assert_eq!( index_to_braillie_char(0b00001000, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00000100).unwrap() ); assert_eq!( index_to_braillie_char(0b00000100, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b00100000).unwrap() ); assert_eq!( index_to_braillie_char(0b00000010, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b01000000).unwrap() ); assert_eq!( index_to_braillie_char(0b00000001, EncodeOrientation::Rows), char::from_u32(0x2800 + 0b10000000).unwrap() ); } #[test] fn check_some_strings() { assert_eq!( to_binary_braillie_str("Hi", EncodeOrientation::Rows), "⠌⢎" ); assert_eq!( to_binary_braillie_str("Hello, world!", EncodeOrientation::Rows), "⠌⢪⠮⠮⣮⠦⠂⣺⣮⡚⠮⠪⢂" ); assert_eq!( to_binary_braillie_str("ąęćó", EncodeOrientation::Rows), "⠩⢡⠩⢕⠩⣡⣉⣓" ); } }