Skip to main content

wafrift_encoding/encoding/keyword/
case.rs

1//! Case manipulation strategies.
2
3/// Shared alternating-case utility.
4///
5/// `SELECT` → `SeLeCt`. Bypasses case-sensitive keyword filters.
6pub fn alternating_case(payload: &str, start_upper: bool) -> String {
7    let mut upper = start_upper;
8    payload
9        .chars()
10        .map(|ch| {
11            if ch.is_ascii_alphabetic() {
12                let result = if upper {
13                    ch.to_ascii_uppercase()
14                } else {
15                    ch.to_ascii_lowercase()
16                };
17                upper = !upper;
18                result
19            } else {
20                ch
21            }
22        })
23        .collect()
24}
25
26/// Case alternation — deterministic alternating upper/lower.
27pub fn case_alternate(payload: &str) -> String {
28    alternating_case(payload, true)
29}
30
31/// Random case alternation — unpredictable mixed-case output.
32pub fn random_case_alternate(payload: &str) -> String {
33    payload
34        .chars()
35        .map(|ch| {
36            if ch.is_ascii_alphabetic() {
37                if rand::random::<bool>() {
38                    ch.to_ascii_uppercase()
39                } else {
40                    ch.to_ascii_lowercase()
41                }
42            } else {
43                ch
44            }
45        })
46        .collect()
47}
48
49/// Full lowercase conversion.
50pub fn lowercase(payload: &str) -> String {
51    payload.to_ascii_lowercase()
52}
53
54/// Full uppercase conversion.
55pub fn uppercase(payload: &str) -> String {
56    payload.to_ascii_uppercase()
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn case_alternate_basic() {
65        assert_eq!(case_alternate("select"), "SeLeCt");
66    }
67
68    #[test]
69    fn random_case_non_deterministic() {
70        let a = random_case_alternate("SELECT");
71        let b = random_case_alternate("SELECT");
72        // Very unlikely to match by chance, but allow for it
73        assert_eq!(a.to_ascii_lowercase(), "select");
74        assert_eq!(b.to_ascii_lowercase(), "select");
75    }
76
77    #[test]
78    fn lowercase_basic() {
79        assert_eq!(lowercase("SeLeCt"), "select");
80    }
81
82    #[test]
83    fn uppercase_basic() {
84        assert_eq!(uppercase("SeLeCt"), "SELECT");
85    }
86}