rakata_core/
ascii.rs

1//! ASCII string utilities shared across KotOR crates.
2
3use std::cmp::Ordering;
4
5/// Byte-by-byte ASCII case-insensitive ordering, zero-allocation.
6///
7/// Compares two strings by mapping each byte through `to_ascii_lowercase()`
8/// using iterator adapters. For ASCII-only content (resource names, filenames)
9/// this is equivalent to `a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase())`
10/// without the per-call `String` allocation.
11pub fn cmp_ascii_case_insensitive(a: &str, b: &str) -> Ordering {
12    a.bytes()
13        .map(|b| b.to_ascii_lowercase())
14        .cmp(b.bytes().map(|b| b.to_ascii_lowercase()))
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20
21    #[test]
22    fn equal_strings() {
23        assert_eq!(
24            cmp_ascii_case_insensitive("hello", "hello"),
25            Ordering::Equal
26        );
27    }
28
29    #[test]
30    fn case_insensitive_equal() {
31        assert_eq!(
32            cmp_ascii_case_insensitive("Hello", "hELLO"),
33            Ordering::Equal
34        );
35    }
36
37    #[test]
38    fn ordering_preserved() {
39        assert_eq!(cmp_ascii_case_insensitive("abc", "def"), Ordering::Less);
40        assert_eq!(cmp_ascii_case_insensitive("DEF", "abc"), Ordering::Greater);
41    }
42
43    #[test]
44    fn prefix_shorter_is_less() {
45        assert_eq!(cmp_ascii_case_insensitive("ab", "abc"), Ordering::Less);
46    }
47}