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]
309pub fn sort_slice_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
310 slice: &mut [A],
311 f: F,
312) {
313 sort_slice_by_path_key_inner(
314 slice,
315 f,
316 ref_index_str_pairs_to_ref_indexes_unstable,
317 sort_slice_unstable_by_path_key_fallback,
318 )
319}
320
321#[inline]
323pub fn sort_slice_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
324 slice: &mut [A],
325 f: F,
326) {
327 sort_slice_by_path_key_inner(
328 slice,
329 f,
330 ref_index_str_pairs_to_ref_indexes,
331 sort_slice_by_path_key_fallback,
332 )
333}
334
335#[inline]
337pub fn sort_slice_rev_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
338 slice: &mut [A],
339 f: F,
340) {
341 sort_slice_by_path_key_inner(
342 slice,
343 f,
344 ref_index_str_pairs_to_ref_indexes_rev_unstable,
345 sort_slice_rev_unstable_by_path_key_fallback,
346 )
347}
348
349#[inline]
351pub fn sort_slice_rev_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
352 slice: &mut [A],
353 f: F,
354) {
355 sort_slice_by_path_key_inner(
356 slice,
357 f,
358 ref_index_str_pairs_to_ref_indexes_rev,
359 sort_slice_rev_by_path_key_fallback,
360 )
361}
362
363fn sort_slice_by_path_key_inner<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
364 slice: &mut [A],
365 mut f: F,
366 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
367 fallback: impl Fn(&mut [A], F),
368) {
369 let mut use_str = true;
370
371 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
372
373 for (i, p) in slice.iter().enumerate() {
374 let s = match f(p).as_ref().to_str() {
375 Some(s) => s,
376 None => {
377 use_str = false;
378 break;
379 },
380 };
381
382 ref_index_str_pairs.push((i, s));
383 }
384
385 if use_str {
386 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
387
388 sort_slice_ref_indexes(slice, ref_indexes);
389 } else {
390 fallback(slice, f);
391 }
392}
393
394#[inline]
395fn sort_slice_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
396 slice: &mut [A],
397 mut f: F,
398) {
399 slice.sort_unstable_by(|a, b| {
400 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
401 });
402}
403
404#[inline]
405fn sort_slice_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
406 slice: &mut [A],
407 mut f: F,
408) {
409 slice.sort_by(|a, b| {
410 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
411 });
412}
413
414#[inline]
415fn sort_slice_rev_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
416 slice: &mut [A],
417 mut f: F,
418) {
419 slice.sort_unstable_by(|a, b| {
420 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
421 });
422}
423
424#[inline]
425fn sort_slice_rev_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
426 slice: &mut [A],
427 mut f: F,
428) {
429 slice.sort_by(|a, b| {
430 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
431 });
432}
433
434#[inline]
438pub fn sort_os_str_slice<S: AsRef<OsStr>>(slice: &mut [S]) {
439 sort_slice_unstable_by_os_str_key(slice, |e| e.as_ref())
440}
441
442#[inline]
444pub fn sort_os_str_slice_rev<S: AsRef<OsStr>>(slice: &mut [S]) {
445 sort_slice_rev_unstable_by_os_str_key(slice, |e| e.as_ref())
446}
447
448#[inline]
450pub fn sort_c_str_slice<S: AsRef<CStr>>(slice: &mut [S]) {
451 sort_slice_unstable_by_c_str_key(slice, |e| e.as_ref())
452}
453
454#[inline]
456pub fn sort_c_str_slice_rev<S: AsRef<CStr>>(slice: &mut [S]) {
457 sort_slice_rev_unstable_by_c_str_key(slice, |e| e.as_ref())
458}
459
460#[inline]
462pub fn sort_path_slice<P: AsRef<Path>>(slice: &mut [P]) {
463 sort_slice_unstable_by_path_key(slice, |e| e.as_ref())
464}
465
466#[inline]
468pub fn sort_path_slice_rev<P: AsRef<Path>>(slice: &mut [P]) {
469 sort_slice_rev_unstable_by_path_key(slice, |e| e.as_ref())
470}
471
472#[inline]
475fn ref_index_str_pairs_to_ref_indexes_unstable(
476 mut ref_index_str_pairs: Vec<(usize, &str)>,
477) -> Vec<(usize, usize)> {
478 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(a.1, b.1));
479
480 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
481}
482
483#[inline]
484fn ref_index_str_pairs_to_ref_indexes(
485 mut ref_index_str_pairs: Vec<(usize, &str)>,
486) -> Vec<(usize, usize)> {
487 ref_index_str_pairs.sort_by(|a, b| compare_str(a.1, b.1));
488
489 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
490}
491
492#[inline]
493fn ref_index_str_pairs_to_ref_indexes_rev_unstable(
494 mut ref_index_str_pairs: Vec<(usize, &str)>,
495) -> Vec<(usize, usize)> {
496 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(b.1, a.1));
497
498 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
499}
500
501#[inline]
502fn ref_index_str_pairs_to_ref_indexes_rev(
503 mut ref_index_str_pairs: Vec<(usize, &str)>,
504) -> Vec<(usize, usize)> {
505 ref_index_str_pairs.sort_by(|a, b| compare_str(b.1, a.1));
506
507 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
508}
509
510#[inline]
511fn ref_index_str_pairs_to_ref_indexes_inner(
512 ref_index_str_pairs: Vec<(usize, &str)>,
513) -> Vec<(usize, usize)> {
514 ref_index_str_pairs
515 .into_iter()
516 .enumerate()
517 .filter_map(|(j, (i, _))| if i != j { Some((i, j)) } else { None })
518 .collect()
519}
520
521#[inline]
522fn sort_slice_ref_indexes<S>(slice: &mut [S], mut ref_indexes: Vec<(usize, usize)>) {
523 let length = ref_indexes.len();
524
525 for index in 0..length {
526 let (i, j) = ref_indexes[index];
527
528 slice.swap(i, j);
529
530 for (t, _) in ref_indexes[index + 1..].iter_mut() {
531 if *t == j {
532 *t = i;
533 break;
534 }
535 }
536 }
537}