Skip to content

Commit

Permalink
feat(docs): document morse_code cipher (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
scriptandcompile authored Jun 11, 2024
1 parent a97a1a2 commit dbfef30
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/ciphers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod xor;
pub use self::aes::{aes_decrypt, aes_encrypt, AesKey};
pub use self::another_rot13::another_rot13;
pub use self::caesar::caesar;
pub use self::morse_code::encode;
pub use self::morse_code::{decode, encode};
pub use self::polybius::{decode_ascii, encode_ascii};
pub use self::rot13::rot13;
pub use self::sha256::sha256;
Expand Down
153 changes: 127 additions & 26 deletions src/ciphers/morse_code.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,35 @@
use std::collections::HashMap;

// The character used to represent an unknown morse code sequence
const UNKNOWN_CHARACTER: &str = "........";

// The character used to represent an unknown morse code character
const _UNKNOWN_MORSE_CHARACTER: &str = "_";

/// Encode a message into morse code.
///
/// Given a message, this function encodes it into morse code.
/// It uses a dictionary to map each character to its corresponding morse code sequence.
/// If a character is not found in the dictionary, it is replaced with the unknown character sequence.
///
/// # Arguments
///
/// * `message` - The message to encode into morse code.
///
/// # Returns
///
/// The encoded morse code as a string.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::ciphers::encode;
///
/// let message = "Hello Morse";
/// let cipher = encode(message);
///
/// assert_eq!(cipher, ".... . .-.. .-.. --- / -- --- .-. ... .");
/// ```
pub fn encode(message: &str) -> String {
let dictionary = _morse_dictionary();
message
Expand All @@ -22,6 +49,13 @@ macro_rules! map {
};
}

/// Create the morse code to alphanumeric dictionary.
///
/// This function creates a HashMap that maps each morse code sequence to its corresponding alphanumeric character.
///
/// # Returns
///
/// The morse code to alphanumeric dictionary as a HashMap.
fn _morse_dictionary() -> HashMap<&'static str, &'static str> {
map! {
"A" => ".-", "B" => "-...", "C" => "-.-.",
Expand All @@ -48,6 +82,13 @@ fn _morse_dictionary() -> HashMap<&'static str, &'static str> {
}
}

/// Create the morse code to alphanumeric dictionary.
///
/// This function creates a HashMap that maps each morse code sequence to its corresponding alphanumeric character.
///
/// # Returns
///
/// The morse code to alphanumeric dictionary as a HashMap.
fn _morse_to_alphanumeric_dictionary() -> HashMap<&'static str, &'static str> {
map! {
".-" => "A", "-..." => "B", "-.-." => "C",
Expand All @@ -74,6 +115,17 @@ fn _morse_to_alphanumeric_dictionary() -> HashMap<&'static str, &'static str> {
}
}

/// Check if a string is a valid morse code part.
///
/// This function checks if a string contains only valid morse code characters ('.', '-', and ' ').
///
/// # Arguments
///
/// * `string` - The string to check.
///
/// # Returns
///
/// `true` if the string is a valid morse code part, `false` otherwise.
fn _check_part(string: &str) -> bool {
for c in string.chars() {
match c {
Expand All @@ -84,30 +136,45 @@ fn _check_part(string: &str) -> bool {
true
}

/// Check if a string is a valid morse code.
///
/// This function checks if a string is a valid morse code by splitting it into parts and checking each part.
///
/// # Arguments
///
/// * `string` - The string to check.
///
/// # Returns
///
/// `true` if the string is a valid morse code, `false` otherwise.
fn _check_all_parts(string: &str) -> bool {
string.split('/').all(_check_part)
}

fn _decode_token(string: &str) -> String {
_morse_to_alphanumeric_dictionary()
.get(string)
.unwrap_or(&_UNKNOWN_MORSE_CHARACTER)
.to_string()
}

fn _decode_part(string: &str) -> String {
string
.split(' ')
.map(_decode_token)
.collect::<Vec<String>>()
.join("")
}

/// Convert morse code to ascii.
/// Decode a morse code into an alphanumeric message.
///
/// Given a morse code, return the corresponding message.
/// If the code is invalid, the undecipherable part of the code is replaced by `_`.
#[cfg(test)]
/// Given a morse code, this function decodes it into an alphanumeric message.
/// It uses a dictionary to map each morse code sequence to its corresponding alphanumeric character.
/// If a morse code sequence is not found in the dictionary, it is replaced with the unknown morse code character.
/// If the morse code is invalid, an `InvalidData` error is returned.
///
/// # Arguments
///
/// * `string` - The morse code to decode into an alphanumeric message.
///
/// # Returns
///
/// The decoded alphanumeric message as a `Result` containing a `String` if successful, or an `InvalidData` error.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::ciphers::decode;
///
/// let message = decode(".... . .-.. .-.. --- / -- --- .-. ... .").unwrap();
///
/// assert_eq!(message, "HELLO MORSE");
/// ```
pub fn decode(string: &str) -> Result<String, std::io::Error> {
if !_check_all_parts(string) {
return Err(std::io::Error::new(
Expand All @@ -125,6 +192,47 @@ pub fn decode(string: &str) -> Result<String, std::io::Error> {
Ok(partitions.join(" "))
}

/// Decode a morse code token into an alphanumeric character.
///
/// This function decodes a morse code token into its corresponding alphanumeric character.
/// It uses a dictionary to map each morse code sequence to its corresponding alphanumeric character.
/// If the morse code token is not found in the dictionary, it is replaced with the unknown morse code character.
///
/// # Arguments
///
/// * `string` - The morse code token to decode into an alphanumeric character.
///
/// # Returns
///
/// The decoded alphanumeric character as a string.
///
fn _decode_token(string: &str) -> String {
_morse_to_alphanumeric_dictionary()
.get(string)
.unwrap_or(&_UNKNOWN_MORSE_CHARACTER)
.to_string()
}

/// Decode a morse code part into an alphanumeric string.
///
/// This function decodes a morse code part into its corresponding alphanumeric string.
/// It splits the part into tokens, decodes each token, and joins them together.
///
/// # Arguments
///
/// * `string` - The morse code part to decode into an alphanumeric string.
///
/// # Returns
///
/// The decoded alphanumeric string.
fn _decode_part(string: &str) -> String {
string
.split(' ')
.map(_decode_token)
.collect::<Vec<String>>()
.join("")
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -195,11 +303,4 @@ mod tests {

assert_eq!(expected, result);
}

#[test]
fn test_decode() {
let message = ".... . .-.. .-.. --- / -- --- .-. ... .";
let cipher = decode(message).unwrap();
assert_eq!(cipher, "HELLO MORSE");
}
}

0 comments on commit dbfef30

Please sign in to comment.