str_utils/
ends_with_ignore_case.rs

1use crate::{ToLowercase, ToUppercase};
2
3/// To extend `str` to have a `ends_with_ignore_case` method.
4pub trait EndsWithIgnoreCase {
5    /// Returns `true` if the given string slice case-insensitively (using case-folding) matches a suffix of this string slice.
6    ///
7    /// NOTE: This method may allocate heap memory.
8    fn ends_with_ignore_case<S: AsRef<str>>(&self, b: S) -> bool;
9}
10
11impl EndsWithIgnoreCase for str {
12    #[inline]
13    fn ends_with_ignore_case<S: AsRef<str>>(&self, b: S) -> bool {
14        let a = self;
15        let b = b.as_ref();
16
17        if b.is_empty() {
18            return true;
19        }
20
21        {
22            let au = a.to_uppercase_cow();
23            let bu = b.to_uppercase_cow();
24
25            let au_length = au.len();
26            let bu_length = bu.len();
27
28            if au_length >= bu_length
29                && unsafe { au.get_unchecked((au_length - bu_length)..) == bu }
30            {
31                return true;
32            }
33        }
34
35        let al = a.to_lowercase_cow();
36        let bl = b.to_lowercase_cow();
37
38        let al_length = al.len();
39        let bl_length = bl.len();
40
41        if al_length >= bl_length {
42            unsafe { al.get_unchecked((al_length - bl_length)..) == bl }
43        } else {
44            false
45        }
46    }
47}