1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::translate::*;

// rustdoc-stripper-ignore-next
/// A `CollationKey` allows ordering strings using the linguistically correct rules for the current locale.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CollationKey(crate::GString);

impl<T: AsRef<str>> From<T> for CollationKey {
    // rustdoc-stripper-ignore-next
    /// Converts a string into a `CollationKey` that can be compared with other
    /// collation keys produced by the same function using `std::cmp::Ordering::cmp()`.
    #[doc(alias = "g_utf8_collate_key")]
    fn from(s: T) -> Self {
        let s = s.as_ref();
        let key = unsafe {
            from_glib_full(ffi::g_utf8_collate_key(
                s.as_ptr() as *const _,
                s.len() as isize,
            ))
        };
        Self(key)
    }
}

// rustdoc-stripper-ignore-next
/// A `FilenameCollationKey` allows ordering file names using the linguistically correct rules for the current locale.
/// Compared to `CollationKey`, filename collation keys take into consideration dots and other characters
/// commonly found in file names.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct FilenameCollationKey(crate::GString);

impl<T: AsRef<str>> From<T> for FilenameCollationKey {
    // rustdoc-stripper-ignore-next
    /// Converts a string into a `FilenameCollationKey` that can be compared with other
    /// collation keys produced by the same function using `std::cmp::Ordering::cmp()`.
    #[doc(alias = "g_utf8_collate_key_for_filename")]
    fn from(s: T) -> Self {
        let s = s.as_ref();
        let key = unsafe {
            from_glib_full(ffi::g_utf8_collate_key_for_filename(
                s.as_ptr() as *const _,
                s.len() as isize,
            ))
        };
        Self(key)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn collate() {
        let mut unsorted = vec![
            String::from("bcd"),
            String::from("cde"),
            String::from("abc"),
        ];

        let sorted = vec![
            String::from("abc"),
            String::from("bcd"),
            String::from("cde"),
        ];

        unsorted.sort_by(|s1, s2| CollationKey::from(&s1).cmp(&CollationKey::from(&s2)));

        assert_eq!(unsorted, sorted);
    }

    #[test]
    fn collate_filenames() {
        let mut unsorted = vec![
            String::from("bcd.a"),
            String::from("cde.b"),
            String::from("abc.c"),
        ];

        let sorted = vec![
            String::from("abc.c"),
            String::from("bcd.a"),
            String::from("cde.b"),
        ];

        unsorted.sort_by(|s1, s2| {
            FilenameCollationKey::from(&s1).cmp(&FilenameCollationKey::from(&s2))
        });

        assert_eq!(unsorted, sorted);
    }
}