glib/
unicollate.rs
1use crate::ffi;
4
5#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub struct CollationKey(crate::Slice<u8>);
9
10impl<T: AsRef<str>> From<T> for CollationKey {
11 #[doc(alias = "g_utf8_collate_key")]
15 fn from(s: T) -> Self {
16 let s = s.as_ref();
17 let key = unsafe {
18 let ptr = ffi::g_utf8_collate_key(s.as_ptr() as *const _, s.len() as isize);
19 let len = libc::strlen(ptr);
20
21 crate::Slice::from_glib_full_num(ptr as *mut u8, len)
22 };
23 Self(key)
24 }
25}
26
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
32pub struct FilenameCollationKey(crate::Slice<u8>);
33
34impl<T: AsRef<str>> From<T> for FilenameCollationKey {
35 #[doc(alias = "g_utf8_collate_key_for_filename")]
39 fn from(s: T) -> Self {
40 let s = s.as_ref();
41 let key = unsafe {
42 let ptr =
43 ffi::g_utf8_collate_key_for_filename(s.as_ptr() as *const _, s.len() as isize);
44 let len = libc::strlen(ptr);
45
46 crate::Slice::from_glib_full_num(ptr as *mut u8, len)
47 };
48 Self(key)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn collate() {
58 let mut unsorted = vec![
59 String::from("bcd"),
60 String::from("cde"),
61 String::from("abc"),
62 ];
63
64 let sorted = vec![
65 String::from("abc"),
66 String::from("bcd"),
67 String::from("cde"),
68 ];
69
70 unsorted.sort_by(|s1, s2| CollationKey::from(&s1).cmp(&CollationKey::from(&s2)));
71
72 assert_eq!(unsorted, sorted);
73 }
74
75 #[test]
76 fn collate_non_ascii() {
77 let mut unsorted = vec![
78 String::from("猫の手も借りたい"),
79 String::from("日本語は難しい"),
80 String::from("ありがとう"),
81 ];
82
83 let sorted = vec![
84 String::from("ありがとう"),
85 String::from("日本語は難しい"),
86 String::from("猫の手も借りたい"),
87 ];
88
89 unsorted.sort_by(|s1, s2| CollationKey::from(&s1).cmp(&CollationKey::from(&s2)));
90
91 assert_eq!(unsorted, sorted);
92 }
93
94 #[test]
95 fn collate_filenames() {
96 let mut unsorted = vec![
97 String::from("bcd.a"),
98 String::from("cde.b"),
99 String::from("abc.c"),
100 ];
101
102 let sorted = vec![
103 String::from("abc.c"),
104 String::from("bcd.a"),
105 String::from("cde.b"),
106 ];
107
108 unsorted.sort_by(|s1, s2| {
109 FilenameCollationKey::from(&s1).cmp(&FilenameCollationKey::from(&s2))
110 });
111
112 assert_eq!(unsorted, sorted);
113 }
114
115 #[test]
116 fn collate_filenames_non_ascii() {
117 let mut unsorted = vec![
118 String::from("猫の手も借りたい.foo"),
119 String::from("日本語は難しい.bar"),
120 String::from("ありがとう.baz"),
121 ];
122
123 let sorted = vec![
124 String::from("ありがとう.baz"),
125 String::from("日本語は難しい.bar"),
126 String::from("猫の手も借りたい.foo"),
127 ];
128
129 unsorted.sort_by(|s1, s2| {
130 FilenameCollationKey::from(&s1).cmp(&FilenameCollationKey::from(&s2))
131 });
132
133 assert_eq!(unsorted, sorted);
134 }
135
136 #[test]
137 fn collate_filenames_from_path() {
138 use std::path::PathBuf;
139
140 let mut unsorted = vec![
141 PathBuf::from("猫の手も借りたい.foo"),
142 PathBuf::from("日本語は難しい.bar"),
143 PathBuf::from("ありがとう.baz"),
144 ];
145
146 let sorted = vec![
147 PathBuf::from("ありがとう.baz"),
148 PathBuf::from("日本語は難しい.bar"),
149 PathBuf::from("猫の手も借りたい.foo"),
150 ];
151
152 unsorted.sort_by(|s1, s2| {
153 FilenameCollationKey::from(&s1.to_string_lossy())
154 .cmp(&FilenameCollationKey::from(&s2.to_string_lossy()))
155 });
156
157 assert_eq!(unsorted, sorted);
158 }
159}