1use core::cmp::Ordering;
2use std::{
3 ffi::{CStr, OsStr},
4 path::Path,
5};
6
7use crate::compare_str;
8
9#[inline]
15pub fn compare_os_str<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
16 let sa = match a.as_ref().to_str() {
17 Some(s) => s,
18 None => {
19 return compare_os_str_fallback(a, b);
20 },
21 };
22
23 let sb = match b.as_ref().to_str() {
24 Some(s) => s,
25 None => {
26 return compare_os_str_fallback(a, b);
27 },
28 };
29
30 compare_str(sa, sb)
31}
32
33#[inline]
34fn compare_os_str_fallback<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
35 a.as_ref().cmp(b.as_ref())
36}
37
38#[inline]
44pub fn compare_c_str<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
45 let sa = match a.as_ref().to_str() {
46 Ok(s) => s,
47 Err(_) => {
48 return compare_c_str_fallback(a, b);
49 },
50 };
51
52 let sb = match b.as_ref().to_str() {
53 Ok(s) => s,
54 Err(_) => {
55 return compare_c_str_fallback(a, b);
56 },
57 };
58
59 compare_str(sa, sb)
60}
61
62#[inline]
63fn compare_c_str_fallback<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
64 a.as_ref().cmp(b.as_ref())
65}
66
67#[inline]
73pub fn compare_path<A: AsRef<Path>, B: AsRef<Path>>(a: A, b: B) -> Ordering {
74 compare_os_str(a.as_ref(), b.as_ref())
75}
76
77#[inline]
83pub fn sort_slice_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
84 slice: &mut [A],
85 f: F,
86) {
87 sort_slice_by_os_str_key_inner(
88 slice,
89 f,
90 ref_index_str_pairs_to_ref_indexes_unstable,
91 sort_slice_unstable_by_os_str_key_fallback,
92 )
93}
94
95#[inline]
101pub fn sort_slice_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
102 slice: &mut [A],
103 f: F,
104) {
105 sort_slice_by_os_str_key_inner(
106 slice,
107 f,
108 ref_index_str_pairs_to_ref_indexes,
109 sort_slice_by_os_str_key_fallback,
110 )
111}
112
113#[inline]
119pub fn sort_slice_rev_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
120 slice: &mut [A],
121 f: F,
122) {
123 sort_slice_by_os_str_key_inner(
124 slice,
125 f,
126 ref_index_str_pairs_to_ref_indexes_rev_unstable,
127 sort_slice_rev_unstable_by_os_str_key_fallback,
128 )
129}
130
131#[inline]
137pub fn sort_slice_rev_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
138 slice: &mut [A],
139 f: F,
140) {
141 sort_slice_by_os_str_key_inner(
142 slice,
143 f,
144 ref_index_str_pairs_to_ref_indexes_rev,
145 sort_slice_rev_by_os_str_key_fallback,
146 )
147}
148
149fn sort_slice_by_os_str_key_inner<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
150 slice: &mut [A],
151 mut f: F,
152 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<usize>,
153 fallback: impl Fn(&mut [A], F),
154) {
155 let mut use_str = true;
156
157 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
158
159 for (i, p) in slice.iter().enumerate() {
160 let s = match f(p).as_ref().to_str() {
161 Some(s) => s,
162 None => {
163 use_str = false;
164 break;
165 },
166 };
167
168 ref_index_str_pairs.push((i, s));
169 }
170
171 if use_str {
172 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
173
174 sort_slice_ref_indexes(slice, ref_indexes);
175 } else {
176 fallback(slice, f);
177 }
178}
179
180#[inline]
181fn sort_slice_unstable_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_unstable_by(|a, b| compare_os_str_fallback(f(a), f(b)));
186}
187
188#[inline]
189fn sort_slice_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
190 slice: &mut [A],
191 mut f: F,
192) {
193 slice.sort_by(|a, b| compare_os_str_fallback(f(a), f(b)));
194}
195
196#[inline]
197fn sort_slice_rev_unstable_by_os_str_key_fallback<
198 A,
199 T: ?Sized + AsRef<OsStr>,
200 F: FnMut(&A) -> &T,
201>(
202 slice: &mut [A],
203 mut f: F,
204) {
205 slice.sort_unstable_by(|a, b| compare_os_str_fallback(f(b), f(a)));
206}
207
208#[inline]
209fn sort_slice_rev_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
210 slice: &mut [A],
211 mut f: F,
212) {
213 slice.sort_by(|a, b| compare_os_str_fallback(f(b), f(a)));
214}
215
216#[inline]
222pub fn sort_slice_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
223 slice: &mut [A],
224 f: F,
225) {
226 sort_slice_by_c_str_key_inner(
227 slice,
228 f,
229 ref_index_str_pairs_to_ref_indexes_unstable,
230 sort_slice_unstable_by_c_str_key_fallback,
231 )
232}
233
234#[inline]
240pub fn sort_slice_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
241 slice: &mut [A],
242 f: F,
243) {
244 sort_slice_by_c_str_key_inner(
245 slice,
246 f,
247 ref_index_str_pairs_to_ref_indexes,
248 sort_slice_by_c_str_key_fallback,
249 )
250}
251
252#[inline]
258pub fn sort_slice_rev_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
259 slice: &mut [A],
260 f: F,
261) {
262 sort_slice_by_c_str_key_inner(
263 slice,
264 f,
265 ref_index_str_pairs_to_ref_indexes_rev_unstable,
266 sort_slice_rev_unstable_by_c_str_key_fallback,
267 )
268}
269
270#[inline]
276pub fn sort_slice_rev_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
277 slice: &mut [A],
278 f: F,
279) {
280 sort_slice_by_c_str_key_inner(
281 slice,
282 f,
283 ref_index_str_pairs_to_ref_indexes_rev,
284 sort_slice_rev_by_c_str_key_fallback,
285 )
286}
287
288fn sort_slice_by_c_str_key_inner<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
289 slice: &mut [A],
290 mut f: F,
291 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<usize>,
292 fallback: impl Fn(&mut [A], F),
293) {
294 let mut use_str = true;
295
296 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
297
298 for (i, p) in slice.iter().enumerate() {
299 let s = match f(p).as_ref().to_str() {
300 Ok(s) => s,
301 Err(_) => {
302 use_str = false;
303 break;
304 },
305 };
306
307 ref_index_str_pairs.push((i, s));
308 }
309
310 if use_str {
311 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
312
313 sort_slice_ref_indexes(slice, ref_indexes);
314 } else {
315 fallback(slice, f);
316 }
317}
318
319#[inline]
320fn sort_slice_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
321 slice: &mut [A],
322 mut f: F,
323) {
324 slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(a), f(b)));
325}
326
327#[inline]
328fn sort_slice_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
329 slice: &mut [A],
330 mut f: F,
331) {
332 slice.sort_by(|a, b| compare_c_str_fallback(f(a), f(b)));
333}
334
335#[inline]
336fn sort_slice_rev_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
337 slice: &mut [A],
338 mut f: F,
339) {
340 slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(b), f(a)));
341}
342
343#[inline]
344fn sort_slice_rev_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
345 slice: &mut [A],
346 mut f: F,
347) {
348 slice.sort_by(|a, b| compare_c_str_fallback(f(b), f(a)));
349}
350
351#[inline]
357pub fn sort_slice_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
358 slice: &mut [A],
359 f: F,
360) {
361 sort_slice_by_path_key_inner(
362 slice,
363 f,
364 ref_index_str_pairs_to_ref_indexes_unstable,
365 sort_slice_unstable_by_path_key_fallback,
366 )
367}
368
369#[inline]
375pub fn sort_slice_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
376 slice: &mut [A],
377 f: F,
378) {
379 sort_slice_by_path_key_inner(
380 slice,
381 f,
382 ref_index_str_pairs_to_ref_indexes,
383 sort_slice_by_path_key_fallback,
384 )
385}
386
387#[inline]
393pub fn sort_slice_rev_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
394 slice: &mut [A],
395 f: F,
396) {
397 sort_slice_by_path_key_inner(
398 slice,
399 f,
400 ref_index_str_pairs_to_ref_indexes_rev_unstable,
401 sort_slice_rev_unstable_by_path_key_fallback,
402 )
403}
404
405#[inline]
411pub fn sort_slice_rev_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
412 slice: &mut [A],
413 f: F,
414) {
415 sort_slice_by_path_key_inner(
416 slice,
417 f,
418 ref_index_str_pairs_to_ref_indexes_rev,
419 sort_slice_rev_by_path_key_fallback,
420 )
421}
422
423fn sort_slice_by_path_key_inner<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
424 slice: &mut [A],
425 mut f: F,
426 ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<usize>,
427 fallback: impl Fn(&mut [A], F),
428) {
429 let mut use_str = true;
430
431 let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
432
433 for (i, p) in slice.iter().enumerate() {
434 let s = match f(p).as_ref().to_str() {
435 Some(s) => s,
436 None => {
437 use_str = false;
438 break;
439 },
440 };
441
442 ref_index_str_pairs.push((i, s));
443 }
444
445 if use_str {
446 let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
447
448 sort_slice_ref_indexes(slice, ref_indexes);
449 } else {
450 fallback(slice, f);
451 }
452}
453
454#[inline]
455fn sort_slice_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
456 slice: &mut [A],
457 mut f: F,
458) {
459 slice.sort_unstable_by(|a, b| {
460 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
461 });
462}
463
464#[inline]
465fn sort_slice_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
466 slice: &mut [A],
467 mut f: F,
468) {
469 slice.sort_by(|a, b| {
470 compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
471 });
472}
473
474#[inline]
475fn sort_slice_rev_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
476 slice: &mut [A],
477 mut f: F,
478) {
479 slice.sort_unstable_by(|a, b| {
480 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
481 });
482}
483
484#[inline]
485fn sort_slice_rev_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
486 slice: &mut [A],
487 mut f: F,
488) {
489 slice.sort_by(|a, b| {
490 compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
491 });
492}
493
494#[inline]
502pub fn sort_os_str_slice<S: AsRef<OsStr>>(slice: &mut [S]) {
503 sort_slice_unstable_by_os_str_key(slice, |e| e.as_ref())
504}
505
506#[inline]
512pub fn sort_os_str_slice_rev<S: AsRef<OsStr>>(slice: &mut [S]) {
513 sort_slice_rev_unstable_by_os_str_key(slice, |e| e.as_ref())
514}
515
516#[inline]
522pub fn sort_c_str_slice<S: AsRef<CStr>>(slice: &mut [S]) {
523 sort_slice_unstable_by_c_str_key(slice, |e| e.as_ref())
524}
525
526#[inline]
532pub fn sort_c_str_slice_rev<S: AsRef<CStr>>(slice: &mut [S]) {
533 sort_slice_rev_unstable_by_c_str_key(slice, |e| e.as_ref())
534}
535
536#[inline]
542pub fn sort_path_slice<P: AsRef<Path>>(slice: &mut [P]) {
543 sort_slice_unstable_by_path_key(slice, |e| e.as_ref())
544}
545
546#[inline]
552pub fn sort_path_slice_rev<P: AsRef<Path>>(slice: &mut [P]) {
553 sort_slice_rev_unstable_by_path_key(slice, |e| e.as_ref())
554}
555
556#[inline]
559fn ref_index_str_pairs_to_ref_indexes_unstable(
560 mut ref_index_str_pairs: Vec<(usize, &str)>,
561) -> Vec<usize> {
562 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(a.1, b.1));
563
564 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
565}
566
567#[inline]
568fn ref_index_str_pairs_to_ref_indexes(mut ref_index_str_pairs: Vec<(usize, &str)>) -> Vec<usize> {
569 ref_index_str_pairs.sort_by(|a, b| compare_str(a.1, b.1));
570
571 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
572}
573
574#[inline]
575fn ref_index_str_pairs_to_ref_indexes_rev_unstable(
576 mut ref_index_str_pairs: Vec<(usize, &str)>,
577) -> Vec<usize> {
578 ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(b.1, a.1));
579
580 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
581}
582
583#[inline]
584fn ref_index_str_pairs_to_ref_indexes_rev(
585 mut ref_index_str_pairs: Vec<(usize, &str)>,
586) -> Vec<usize> {
587 ref_index_str_pairs.sort_by(|a, b| compare_str(b.1, a.1));
588
589 ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
590}
591
592#[inline]
593fn ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs: Vec<(usize, &str)>) -> Vec<usize> {
594 ref_index_str_pairs.into_iter().map(|(i, _)| i).collect()
595}
596
597#[inline]
598fn sort_slice_ref_indexes<S>(slice: &mut [S], mut permutation: Vec<usize>) {
599 for i in 0..permutation.len() {
601 let mut current = i;
602
603 while permutation[current] != i {
604 let next = permutation[current];
605
606 slice.swap(current, next);
607
608 permutation[current] = current;
609 current = next;
610 }
611
612 permutation[current] = current;
613 }
614}