commit 1624db615bc6c08afed78b575cc4af8557401b8d Author: LongHairedHacker Date: Sat May 30 18:07:03 2020 +0200 First baudot code implementation works diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..93440bc --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "rusty-tty" +version = "0.1.0" +dependencies = [ + "lazy_static", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..870a717 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rusty-tty" +version = "0.1.0" +authors = ["Sebastian "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "*" diff --git a/src/baudot.rs b/src/baudot.rs new file mode 100644 index 0000000..aee12da --- /dev/null +++ b/src/baudot.rs @@ -0,0 +1,145 @@ +use std::collections::HashMap; + +const LETTERS: &[u8] = b"\0E\nA SIU\rDRJNFCKTZLWHYPQOBG\0MXV\0"; +const FIGURES: &[u8] = b"\03\n- \x0787\r\x054',!:(5\")2#6019?&\0./;\0"; + +lazy_static! { + static ref INV_LETTERS: HashMap = LETTERS + .iter() + .enumerate() + .map(|(c, f)| (*f, c as u8)) + .collect(); + static ref INV_FIGURES: HashMap = FIGURES + .iter() + .enumerate() + .map(|(c, f)| (*f, c as u8)) + .collect(); +} + +fn letter_from_code(code: u8) -> Option { + if code >= (LETTERS.len() as u8) { + None + } else { + Some(LETTERS[code as usize]) + } +} + +fn figure_from_code(code: u8) -> Option { + if code >= (FIGURES.len() as u8) { + None + } else { + Some(FIGURES[code as usize]) + } +} + +fn code_from_letter(letter: &u8) -> Option { + INV_LETTERS.get(letter).cloned() +} + +fn code_from_figure(figure: &u8) -> Option { + INV_FIGURES.get(figure).cloned() +} + +const SHIFT_FIGURES: u8 = 0b11011u8; +const SHIFT_LETTERS: u8 = 0b11111u8; + +#[derive(Copy, Clone)] +enum ShiftState { + None, + Letters, + Figures, +} + +pub fn encode(msg: &str) -> Result, u8> { + let mut res = Vec::::new(); + + let mut shift = ShiftState::None; + + for &byte in msg.to_ascii_uppercase().as_bytes().iter() { + let letter = code_from_letter(&byte); + let figure = code_from_figure(&byte); + match (letter, figure, shift) { + (Some(l), Some(_), ShiftState::None) => { + res.push(SHIFT_LETTERS); + shift = ShiftState::Letters; + res.push(l); + } + (Some(l), Some(_), _) => res.push(l), + (Some(l), None, ShiftState::Letters) => res.push(l), + (Some(l), None, _) => { + res.push(SHIFT_LETTERS); + shift = ShiftState::Letters; + res.push(l); + } + (None, Some(f), ShiftState::Figures) => res.push(f), + (None, Some(f), _) => { + res.push(SHIFT_FIGURES); + shift = ShiftState::Figures; + res.push(f); + } + (None, None, _) => return Err(byte), + } + } + + Ok(res) +} + +pub fn decode(msg: &Vec) -> Result { + let mut res = String::new(); + + // Lets assume this is a sane starting point. + let mut shift = ShiftState::Letters; + + for &code in msg.iter() { + match (code, shift) { + (SHIFT_LETTERS, _) => shift = ShiftState::Letters, + (SHIFT_FIGURES, _) => shift = ShiftState::Figures, + (c, ShiftState::Letters) => match letter_from_code(c) { + Some(l) => res.push(l as char), + None => return Err(c), + }, + (c, ShiftState::Figures) => match figure_from_code(c) { + Some(l) => res.push(l as char), + None => return Err(c), + }, + (_, ShiftState::None) => panic!("Shift state is expectedly None"), + } + } + + Ok(res) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_encode() { + let encoded = encode("kaufen sie jede woche vier gute bequeme pelze xy 1234567890"); + assert_eq!( + encoded, + Ok(vec![ + 31, 15, 3, 7, 13, 1, 12, 4, 5, 6, 1, 4, 11, 1, 9, 1, 4, 19, 24, 14, 20, 1, 4, 30, + 6, 1, 10, 4, 26, 7, 16, 1, 4, 25, 1, 23, 7, 1, 28, 1, 4, 22, 1, 18, 17, 1, 4, 29, + 21, 4, 27, 23, 19, 1, 10, 16, 21, 7, 6, 24, 22 + ]) + ); + } + + #[test] + fn test_decode() { + let kaufen_schleife: Vec = vec![ + 31, 15, 3, 7, 13, 1, 12, 4, 5, 6, 1, 4, 11, 1, 9, 1, 4, 19, 24, 14, 20, 1, 4, 30, 6, 1, + 10, 4, 26, 7, 16, 1, 4, 25, 1, 23, 7, 1, 28, 1, 4, 22, 1, 18, 17, 1, 4, 29, 21, 4, 27, + 23, 19, 1, 10, 16, 21, 7, 6, 24, 22, + ]; + + let decoded = decode(&kaufen_schleife); + assert_eq!( + Ok(String::from( + "KAUFEN SIE JEDE WOCHE VIER GUTE BEQUEME PELZE XY 1234567890" + )), + decoded + ) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..48d5de3 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,8 @@ +#[macro_use] +extern crate lazy_static; + +mod baudot; + +fn main() { + println!("Hello, world!"); +}