fancy_mocker/
lib.rs

1mod tests;
2
3fn start_uppercase(text: &str) -> bool {
4    let ambiguous_char: &[_] = &['i', 'I', 'l', 'L'];
5
6    match text.find(ambiguous_char) {
7        Some(index) => {
8            match text.chars().nth(index).unwrap() {
9                'i' | 'I' => index % 2 != 0,
10                _ => index % 2 == 0
11            }
12        },
13        None => false
14    }
15}
16
17fn should_be_uppercase(c: char) -> Option<bool> {
18    match c {
19        'i' | 'I' => Some(false),
20        'l' | 'L' => Some(true),
21        _ => None
22    }
23}
24
25/// Returns a String with the letters changed to alternate
26/// between uppercase and lowercase.
27/// 
28/// All instances of the letters L and i are set to uppercase
29/// and lowercase, respectively.
30/// The case of the first letter in the input is determined based on
31/// where either aforementioned letter first appears,
32/// defaulting to lowercase if neither appears in the text.
33/// 
34/// The capitalisation in the input is not preserved, although
35/// all non-ascii and non-alphabetic characters are preserved as-is.
36/// 
37/// # Examples
38/// 
39/// ```
40/// let hello = "Hello, world!";
41/// let ironic_hello = fancy_mocker::mock(hello);
42/// 
43/// assert_eq!(ironic_hello, "HeLLo, WoRLd!");
44/// ```
45pub fn mock(text: &str) -> String {
46    
47
48    let mut uppercase = start_uppercase(text);
49
50    let mut result = String::with_capacity(text.len());
51
52    for c in text.chars() {
53        if !c.is_ascii_alphabetic() {
54            result.push(c);
55        } else if should_be_uppercase(c).unwrap_or(uppercase) {
56            result.push(c.to_ascii_uppercase());
57            uppercase = false;
58        } else {
59            result.push(c.to_ascii_lowercase());
60            uppercase = true;
61        }
62    }
63
64    result
65}