albhed/
lib.rs

1//! A translator for the Al Bhed language.
2//!
3//! Al Bhed is the language spoken by the Al Bhed people in the land of Spira,
4//! the main setting of the game Final Fantasy X.
5//!
6//! This library doesn't attempt to detect English loanwords that are present in
7//! Al Bhed at the time of the game, as in airship/fiend/etc.
8//!
9//! # Usage
10//!
11//! Converting Al Bhed into English:
12//! ```
13//! let al_bhed = "Oui yvnyet uv dra cay?";
14//! let english = al_bhed.chars().filter_map(albhed::from_al_bhed).collect::<String>();
15//! assert_eq!("You afraid of the sea?", english);
16//! ```
17//!
18//! Converting English into Al Bhed:
19//! ```
20//! let english = "Beware of Sandstorms!";
21//! let al_bhed = english.chars().filter_map(albhed::to_al_bhed).collect::<String>();
22//! assert_eq!("Pafyna uv Cyhtcdunsc!", al_bhed);
23//! ```
24
25#![doc(html_root_url = "https://docs.rs/albhed/0.1.0")]
26
27/// The ordering that Al Bhed letters map into English. For instance, `A` in Al
28/// Bhed maps to the English `E`.
29const AL_BHED: [char; 26] = [
30    'E', 'P', 'S', 'T', 'I', 'W', 'K', 'N', 'U', 'V', 'G', 'C', 'L', 'R', 'Y', 'B', 'X', 'H', 'M',
31    'D', 'O', 'F', 'Z', 'Q', 'A', 'J',
32];
33
34/// The ordering that English letters map into Al Bhed. For instance, `Y` in Al
35/// Bhed maps to the English `A`.
36const ENGLISH: [char; 26] = [
37    'Y', 'P', 'L', 'T', 'A', 'V', 'K', 'R', 'E', 'Z', 'G', 'M', 'S', 'H', 'U', 'B', 'X', 'N', 'C',
38    'D', 'I', 'J', 'F', 'Q', 'O', 'W',
39];
40
41/// Convert a single `char` from Al Bhed into English.
42pub fn from_al_bhed(c: char) -> Option<char> {
43    work(&AL_BHED, c)
44}
45
46/// Convert a single `char` from English into Al Bhed.
47pub fn to_al_bhed(c: char) -> Option<char> {
48    work(&ENGLISH, c)
49}
50
51fn work(table: &[char; 26], c: char) -> Option<char> {
52    match c {
53        _ if c.is_ascii_whitespace() || c.is_ascii_digit() || c.is_ascii_punctuation() => Some(c),
54        _ if c.is_ascii_alphabetic() => {
55            let index: usize = (c.to_digit(36).unwrap() - 10) as usize;
56            let trans = table[index];
57            if c.is_ascii_lowercase() {
58                Some(trans.to_ascii_lowercase())
59            } else {
60                Some(trans)
61            }
62        }
63        _ => None,
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn conversions() {
73        let pairs = vec![
74            ("Fryd ec drec?", "What is this?"),
75            ("Fa gemm ed?", "We kill it?"),
76            ("E vunpet ed!", "I forbid it!"),
77            ("Cunno.", "Sorry."),
78        ];
79
80        pairs.into_iter().for_each(|(ab, eng)| {
81            let al_bhed: String = ab.chars().filter_map(from_al_bhed).collect();
82            assert_eq!(eng, al_bhed);
83
84            let english: String = eng.chars().filter_map(to_al_bhed).collect();
85            assert_eq!(ab, english);
86        });
87    }
88}