alphanumeric_sort/
std_functions.rs

1use core::cmp::Ordering;
2use std::{
3    ffi::{CStr, OsStr},
4    path::Path,
5};
6
7use crate::compare_str;
8
9/// Compare two `OsStr`.
10#[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/// Compare two `CStr`.
35#[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/// Compare two `Path`.
60#[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/// Sort a slice by an `OsStr` key, but may not preserve the order of equal elements.
66#[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/// Sort a slice by an `OsStr` key.
80#[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/// Reversely sort a slice by an `OsStr` key, but may not preserve the order of equal elements.
94#[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/// Reversely sort a slice by an `OsStr` key.
108#[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/// Sort a slice by a `CStr` key, but may not preserve the order of equal elements.
189#[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/// Sort a slice by a `CStr` key.
203#[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/// Reversely sort a slice by a `CStr` key, but may not preserve the order of equal elements.
217#[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/// Reversely sort a slice by a `CStr` key.
231#[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/// Sort a slice by a `Path` key, but may not preserve the order of equal elements.
308
309#[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/// Sort a slice by a `Path` key.
323
324#[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/// Reversely sort a slice by a `Path` key, but may not preserve the order of equal elements.
338
339#[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/// Reversely sort a slice by a `Path` key.
353
354#[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// TODO -----------
439
440/// Sort an `OsStr` slice.
441#[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/// Reversely sort an `OsStr` slice.
447#[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/// Sort a `CStr` slice.
453#[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/// Reversely sort a `CStr` slice.
459#[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/// Sort a `Path` slice.
465#[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/// Reversely sort a `Path` slice.
471#[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// TODO -----------
477
478#[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}