1use core::cmp::Ordering;
2use std::{
3 ffi::{CStr, OsStr},
4 path::Path,
5};
6
7use crate::compare_str;
8
9#[inline]
11pub fn compare_os_str<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
12 let sa = match a.as_ref().to_str() {
13 Some(s) => s,
14 None => {
15 return compare_os_str_fallback(a, b);
16 },
17 };
18
19 let sb = match b.as_ref().to_str() {
20 Some(s) => s,
21 None => {
22 return compare_os_str_fallback(a, b);
23 },
24 };
25
26 compare_str(sa, sb)
27}
28
29#[inline]
30fn compare_os_str_fallback<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
31 a.as_ref().cmp(b.as_ref())
32}
33
34#[inline]
36pub fn compare_c_str<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
37 let sa = match a.as_ref().to_str() {
38 Ok(s) => s,
39 Err(_) => {
40 return compare_c_str_fallback(a, b);
41 },
42 };
43
44 let sb = match b.as_ref().to_str() {
45 Ok(s) => s,
46 Err(_) => {
47 return compare_c_str_fallback(a, b);
48 },
49 };
50
51 compare_str(sa, sb)
52}
53
54#[inline]
55fn compare_c_str_fallback<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
56 a.as_ref().cmp(b.as_ref())
57}
58
59#[inline]
61pub fn compare_path<A: AsRef<Path>, B: AsRef<Path>>(a: A, b: B) -> Ordering {
62 compare_os_str(a.as_ref(), b.as_ref())
63}
64
65#[inline]
67pub fn sort_slice_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
68 slice: &mut [A],
69 f: F,
70) {
71 sort_slice_by_os_str_key_inner(
72 slice,
73 f,
74 ref_index_str_pairs_to_ref_indexes_unstable,
75 sort_slice_unstable_by_os_str_key_fallback,
76 )
77}
78
79#[inline]
81pub fn sort_slice_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
82 slice: &mut [A],
83 f: F,
84) {
85 sort_slice_by_os_str_key_inner(
86 slice,
87 f,
88 ref_index_str_pairs_to_ref_indexes,
89 sort_slice_by_os_str_key_fallback,
90 )
91}
92
93#[inline]
95pub fn sort_slice_rev_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
96 slice: &mut [A],
97 f: F,
98) {
99 sort_slice_by_os_str_key_inner(
100 slice,
101 f,
102 ref_index_str_pairs_to_ref_indexes_rev_unstable,
103 sort_slice_rev_unstable_by_os_str_key_fallback,
104 )
105}
106
107#[inline]
109pub fn sort_slice_rev_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
110 slice: &mut [A],
111 f: F,
112) {
113 sort_slice_by_os_str_key_inner(
114 slice,
115 f,
116 ref_index_str_pairs_to_ref_indexes_rev,
117 sort_slice_rev_by_os_str_key_fallback,
118 )
119}
120
121fn sort_slice_by_os_str_key_inner<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
122 slice: &mut [A],
123 mut f: F,
124 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
125 fallback: impl Fn(&mut [A], F),
126) {
127 let mut use_str = true;
128
129 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
130
131 for (i, p) in slice.iter().enumerate() {
132 let s = match f(p).as_ref().to_str() {
133 Some(s) => s,
134 None => {
135 use_str = false;
136 break;
137 },
138 };
139
140 ref_index_str_pairs.push((i, s));
141 }
142
143 if use_str {
144 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
145
146 sort_slice_ref_indexes(slice, ref_indexes);
147 } else {
148 fallback(slice, f);
149 }
150}
151
152#[inline]
153fn sort_slice_unstable_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
154 slice: &mut [A],
155 mut f: F,
156) {
157 slice.sort_unstable_by(|a, b| compare_os_str_fallback(f(a), f(b)));
158}
159
160#[inline]
161fn sort_slice_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
162 slice: &mut [A],
163 mut f: F,
164) {
165 slice.sort_by(|a, b| compare_os_str_fallback(f(a), f(b)));
166}
167
168#[inline]
169fn sort_slice_rev_unstable_by_os_str_key_fallback<
170 A,
171 T: ?Sized + AsRef<OsStr>,
172 F: FnMut(&A) -> &T,
173>(
174 slice: &mut [A],
175 mut f: F,
176) {
177 slice.sort_unstable_by(|a, b| compare_os_str_fallback(f(b), f(a)));
178}
179
180#[inline]
181fn sort_slice_rev_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
182 slice: &mut [A],
183 mut f: F,
184) {
185 slice.sort_by(|a, b| compare_os_str_fallback(f(b), f(a)));
186}
187
188#[inline]
190pub fn sort_slice_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
191 slice: &mut [A],
192 f: F,
193) {
194 sort_slice_by_c_str_key_inner(
195 slice,
196 f,
197 ref_index_str_pairs_to_ref_indexes_unstable,
198 sort_slice_unstable_by_c_str_key_fallback,
199 )
200}
201
202#[inline]
204pub fn sort_slice_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
205 slice: &mut [A],
206 f: F,
207) {
208 sort_slice_by_c_str_key_inner(
209 slice,
210 f,
211 ref_index_str_pairs_to_ref_indexes,
212 sort_slice_by_c_str_key_fallback,
213 )
214}
215
216#[inline]
218pub fn sort_slice_rev_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
219 slice: &mut [A],
220 f: F,
221) {
222 sort_slice_by_c_str_key_inner(
223 slice,
224 f,
225 ref_index_str_pairs_to_ref_indexes_rev_unstable,
226 sort_slice_rev_unstable_by_c_str_key_fallback,
227 )
228}
229
230#[inline]
232pub fn sort_slice_rev_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
233 slice: &mut [A],
234 f: F,
235) {
236 sort_slice_by_c_str_key_inner(
237 slice,
238 f,
239 ref_index_str_pairs_to_ref_indexes_rev,
240 sort_slice_rev_by_c_str_key_fallback,
241 )
242}
243
244fn sort_slice_by_c_str_key_inner<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
245 slice: &mut [A],
246 mut f: F,
247 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
248 fallback: impl Fn(&mut [A], F),
249) {
250 let mut use_str = true;
251
252 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
253
254 for (i, p) in slice.iter().enumerate() {
255 let s = match f(p).as_ref().to_str() {
256 Ok(s) => s,
257 Err(_) => {
258 use_str = false;
259 break;
260 },
261 };
262
263 ref_index_str_pairs.push((i, s));
264 }
265
266 if use_str {
267 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
268
269 sort_slice_ref_indexes(slice, ref_indexes);
270 } else {
271 fallback(slice, f);
272 }
273}
274
275#[inline]
276fn sort_slice_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
277 slice: &mut [A],
278 mut f: F,
279) {
280 slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(a), f(b)));
281}
282
283#[inline]
284fn sort_slice_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
285 slice: &mut [A],
286 mut f: F,
287) {
288 slice.sort_by(|a, b| compare_c_str_fallback(f(a), f(b)));
289}
290
291#[inline]
292fn sort_slice_rev_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
293 slice: &mut [A],
294 mut f: F,
295) {
296 slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(b), f(a)));
297}
298
299#[inline]
300fn sort_slice_rev_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
301 slice: &mut [A],
302 mut f: F,
303) {
304 slice.sort_by(|a, b| compare_c_str_fallback(f(b), f(a)));
305}
306
307#[inline]
310pub fn sort_slice_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
311 slice: &mut [A],
312 f: F,
313) {
314 sort_slice_by_path_key_inner(
315 slice,
316 f,
317 ref_index_str_pairs_to_ref_indexes_unstable,
318 sort_slice_unstable_by_path_key_fallback,
319 )
320}
321
322#[inline]
325pub fn sort_slice_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
326 slice: &mut [A],
327 f: F,
328) {
329 sort_slice_by_path_key_inner(
330 slice,
331 f,
332 ref_index_str_pairs_to_ref_indexes,
333 sort_slice_by_path_key_fallback,
334 )
335}
336
337#[inline]
340pub fn sort_slice_rev_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
341 slice: &mut [A],
342 f: F,
343) {
344 sort_slice_by_path_key_inner(
345 slice,
346 f,
347 ref_index_str_pairs_to_ref_indexes_rev_unstable,
348 sort_slice_rev_unstable_by_path_key_fallback,
349 )
350}
351
352#[inline]
355pub fn sort_slice_rev_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
356 slice: &mut [A],
357 f: F,
358) {
359 sort_slice_by_path_key_inner(
360 slice,
361 f,
362 ref_index_str_pairs_to_ref_indexes_rev,
363 sort_slice_rev_by_path_key_fallback,
364 )
365}
366
367fn sort_slice_by_path_key_inner<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
368 slice: &mut [A],
369 mut f: F,
370 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
371 fallback: impl Fn(&mut [A], F),
372) {
373 let mut use_str = true;
374
375 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
376
377 for (i, p) in slice.iter().enumerate() {
378 let s = match f(p).as_ref().to_str() {
379 Some(s) => s,
380 None => {
381 use_str = false;
382 break;
383 },
384 };
385
386 ref_index_str_pairs.push((i, s));
387 }
388
389 if use_str {
390 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
391
392 sort_slice_ref_indexes(slice, ref_indexes);
393 } else {
394 fallback(slice, f);
395 }
396}
397
398#[inline]
399fn sort_slice_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
400 slice: &mut [A],
401 mut f: F,
402) {
403 slice.sort_unstable_by(|a, b| {
404 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
405 });
406}
407
408#[inline]
409fn sort_slice_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
410 slice: &mut [A],
411 mut f: F,
412) {
413 slice.sort_by(|a, b| {
414 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
415 });
416}
417
418#[inline]
419fn sort_slice_rev_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
420 slice: &mut [A],
421 mut f: F,
422) {
423 slice.sort_unstable_by(|a, b| {
424 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
425 });
426}
427
428#[inline]
429fn sort_slice_rev_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
430 slice: &mut [A],
431 mut f: F,
432) {
433 slice.sort_by(|a, b| {
434 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
435 });
436}
437
438#[inline]
442pub fn sort_os_str_slice<S: AsRef<OsStr>>(slice: &mut [S]) {
443 sort_slice_unstable_by_os_str_key(slice, |e| e.as_ref())
444}
445
446#[inline]
448pub fn sort_os_str_slice_rev<S: AsRef<OsStr>>(slice: &mut [S]) {
449 sort_slice_rev_unstable_by_os_str_key(slice, |e| e.as_ref())
450}
451
452#[inline]
454pub fn sort_c_str_slice<S: AsRef<CStr>>(slice: &mut [S]) {
455 sort_slice_unstable_by_c_str_key(slice, |e| e.as_ref())
456}
457
458#[inline]
460pub fn sort_c_str_slice_rev<S: AsRef<CStr>>(slice: &mut [S]) {
461 sort_slice_rev_unstable_by_c_str_key(slice, |e| e.as_ref())
462}
463
464#[inline]
466pub fn sort_path_slice<P: AsRef<Path>>(slice: &mut [P]) {
467 sort_slice_unstable_by_path_key(slice, |e| e.as_ref())
468}
469
470#[inline]
472pub fn sort_path_slice_rev<P: AsRef<Path>>(slice: &mut [P]) {
473 sort_slice_rev_unstable_by_path_key(slice, |e| e.as_ref())
474}
475
476#[inline]
479fn ref_index_str_pairs_to_ref_indexes_unstable(
480 mut ref_index_str_pairs: Vec<(usize, &str)>,
481) -> Vec<(usize, usize)> {
482 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(a.1, b.1));
483
484 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
485}
486
487#[inline]
488fn ref_index_str_pairs_to_ref_indexes(
489 mut ref_index_str_pairs: Vec<(usize, &str)>,
490) -> Vec<(usize, usize)> {
491 ref_index_str_pairs.sort_by(|a, b| compare_str(a.1, b.1));
492
493 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
494}
495
496#[inline]
497fn ref_index_str_pairs_to_ref_indexes_rev_unstable(
498 mut ref_index_str_pairs: Vec<(usize, &str)>,
499) -> Vec<(usize, usize)> {
500 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(b.1, a.1));
501
502 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
503}
504
505#[inline]
506fn ref_index_str_pairs_to_ref_indexes_rev(
507 mut ref_index_str_pairs: Vec<(usize, &str)>,
508) -> Vec<(usize, usize)> {
509 ref_index_str_pairs.sort_by(|a, b| compare_str(b.1, a.1));
510
511 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
512}
513
514#[inline]
515fn ref_index_str_pairs_to_ref_indexes_inner(
516 ref_index_str_pairs: Vec<(usize, &str)>,
517) -> Vec<(usize, usize)> {
518 ref_index_str_pairs
519 .into_iter()
520 .enumerate()
521 .filter_map(|(j, (i, _))| if i != j { Some((i, j)) } else { None })
522 .collect()
523}
524
525#[inline]
526fn sort_slice_ref_indexes<S>(slice: &mut [S], mut ref_indexes: Vec<(usize, usize)>) {
527 let length = ref_indexes.len();
528
529 for index in 0..length {
530 let (i, j) = ref_indexes[index];
531
532 slice.swap(i, j);
533
534 for (t, _) in ref_indexes[index + 1..].iter_mut() {
535 if *t == j {
536 *t = i;
537 break;
538 }
539 }
540 }
541}