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#[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/// Sort a slice by a `Path` key.
322#[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/// Reversely sort a slice by a `Path` key, but may not preserve the order of equal elements.
336#[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/// Reversely sort a slice by a `Path` key.
350#[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// TODO -----------
435
436/// Sort an `OsStr` slice.
437#[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/// Reversely sort an `OsStr` slice.
443#[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/// Sort a `CStr` slice.
449#[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/// Reversely sort a `CStr` slice.
455#[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/// Sort a `Path` slice.
461#[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/// Reversely sort a `Path` slice.
467#[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// TODO -----------
473
474#[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}