#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use core::cmp::Ordering;
#[cfg(feature = "std")]
use std::ffi::{CStr, OsStr};
#[cfg(feature = "std")]
use std::path::Path;
#[allow(clippy::while_let_on_iterator)]
pub fn compare_str<A: AsRef<str>, B: AsRef<str>>(a: A, b: B) -> Ordering {
let mut c1 = a.as_ref().chars();
let mut c2 = b.as_ref().chars();
let mut last_is_number = false;
let mut v1: Option<char> = None;
let mut v2: Option<char> = None;
loop {
let ca = {
match v1.take() {
Some(c) => c,
None => {
match c1.next() {
Some(c) => c,
None => {
if v2.take().is_some() || c2.next().is_some() {
return Ordering::Less;
} else {
return Ordering::Equal;
}
}
}
}
}
};
let cb = {
match v2.take() {
Some(c) => c,
None => {
match c2.next() {
Some(c) => c,
None => {
return Ordering::Greater;
}
}
}
}
};
if ca >= '0' && ca <= '9' && cb >= '0' && cb <= '9' {
let mut da = f64::from(ca as u32) - f64::from(b'0');
let mut db = f64::from(cb as u32) - f64::from(b'0');
let mut dc = 0isize;
while let Some(ca) = c1.next() {
if ca >= '0' && ca <= '9' {
da = da * 10.0 + (f64::from(ca as u32) - f64::from(b'0'));
dc += 1;
} else {
v1 = Some(ca);
break;
}
}
while let Some(cb) = c2.next() {
if cb >= '0' && cb <= '9' {
db = db * 10.0 + (f64::from(cb as u32) - f64::from(b'0'));
dc -= 1;
} else {
v2 = Some(cb);
break;
}
}
last_is_number = true;
match da.partial_cmp(&db) {
Some(ordering) if ordering != Ordering::Equal => {
return ordering;
}
_ => {
match dc.cmp(&0) {
Ordering::Equal => (),
Ordering::Greater => return Ordering::Greater,
Ordering::Less => return Ordering::Less,
}
}
}
} else {
match ca.cmp(&cb) {
Ordering::Equal => last_is_number = false,
Ordering::Greater => {
return if last_is_number && (ca > (255 as char)) ^ (cb > (255 as char)) {
Ordering::Less
} else {
Ordering::Greater
};
}
Ordering::Less => {
return if last_is_number && (ca > (255 as char)) ^ (cb > (255 as char)) {
Ordering::Greater
} else {
Ordering::Less
};
}
}
}
}
}
#[cfg(feature = "std")]
#[inline]
pub fn compare_os_str<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
let sa = match a.as_ref().to_str() {
Some(s) => s,
None => {
return compare_os_str_fallback(a, b);
}
};
let sb = match b.as_ref().to_str() {
Some(s) => s,
None => {
return compare_os_str_fallback(a, b);
}
};
compare_str(sa, sb)
}
#[cfg(feature = "std")]
#[inline]
fn compare_os_str_fallback<A: AsRef<OsStr>, B: AsRef<OsStr>>(a: A, b: B) -> Ordering {
a.as_ref().cmp(b.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn compare_c_str<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
let sa = match a.as_ref().to_str() {
Ok(s) => s,
Err(_) => {
return compare_c_str_fallback(a, b);
}
};
let sb = match b.as_ref().to_str() {
Ok(s) => s,
Err(_) => {
return compare_c_str_fallback(a, b);
}
};
compare_str(sa, sb)
}
#[cfg(feature = "std")]
#[inline]
fn compare_c_str_fallback<A: AsRef<CStr>, B: AsRef<CStr>>(a: A, b: B) -> Ordering {
a.as_ref().cmp(b.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn compare_path<A: AsRef<Path>, B: AsRef<Path>>(a: A, b: B) -> Ordering {
compare_os_str(a.as_ref(), b.as_ref())
}
#[inline]
pub fn sort_slice_unstable_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_str(f(a), f(b)));
}
#[inline]
pub fn sort_slice_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_str(f(a), f(b)));
}
#[inline]
pub fn sort_slice_rev_unstable_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_str(f(b), f(a)));
}
#[inline]
pub fn sort_slice_rev_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_str(f(b), f(a)));
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_os_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_unstable,
sort_slice_unstable_by_os_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_os_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes,
sort_slice_by_os_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_unstable_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_os_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev_unstable,
sort_slice_rev_unstable_by_os_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_by_os_str_key<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_os_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev,
sort_slice_rev_by_os_str_key_fallback,
)
}
#[cfg(feature = "std")]
fn sort_slice_by_os_str_key_inner<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
fallback: impl Fn(&mut [A], F),
) {
let mut use_str = true;
let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
for (i, p) in slice.iter().enumerate() {
let s = match f(p).as_ref().to_str() {
Some(s) => s,
None => {
use_str = false;
break;
}
};
ref_index_str_pairs.push((i, s));
}
if use_str {
let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
sort_slice_ref_indexes(slice, ref_indexes);
} else {
fallback(slice, f);
}
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_unstable_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_os_str_fallback(f(a), f(b)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_os_str_fallback(f(a), f(b)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_unstable_by_os_str_key_fallback<
A,
T: ?Sized + AsRef<OsStr>,
F: FnMut(&A) -> &T,
>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_os_str_fallback(f(b), f(a)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_by_os_str_key_fallback<A, T: ?Sized + AsRef<OsStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_os_str_fallback(f(b), f(a)));
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_c_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_unstable,
sort_slice_unstable_by_c_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_c_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes,
sort_slice_by_c_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_unstable_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_c_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev_unstable,
sort_slice_rev_unstable_by_c_str_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_by_c_str_key<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_c_str_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev,
sort_slice_rev_by_c_str_key_fallback,
)
}
#[cfg(feature = "std")]
fn sort_slice_by_c_str_key_inner<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
fallback: impl Fn(&mut [A], F),
) {
let mut use_str = true;
let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
for (i, p) in slice.iter().enumerate() {
let s = match f(p).as_ref().to_str() {
Ok(s) => s,
Err(_) => {
use_str = false;
break;
}
};
ref_index_str_pairs.push((i, s));
}
if use_str {
let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
sort_slice_ref_indexes(slice, ref_indexes);
} else {
fallback(slice, f);
}
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(a), f(b)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_c_str_fallback(f(a), f(b)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_unstable_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_c_str_fallback(f(b), f(a)));
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_by_c_str_key_fallback<A, T: ?Sized + AsRef<CStr>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_c_str_fallback(f(b), f(a)));
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_path_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_unstable,
sort_slice_unstable_by_path_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_path_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes,
sort_slice_by_path_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_unstable_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_path_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev_unstable,
sort_slice_rev_unstable_by_path_key_fallback,
)
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_slice_rev_by_path_key<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
f: F,
) {
sort_slice_by_path_key_inner(
slice,
f,
ref_index_str_pairs_to_ref_indexes_rev,
sort_slice_rev_by_path_key_fallback,
)
}
#[cfg(feature = "std")]
fn sort_slice_by_path_key_inner<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
ref_index_str_pairs_to_ref_indexes: impl Fn(Vec<(usize, &str)>) -> Vec<(usize, usize)>,
fallback: impl Fn(&mut [A], F),
) {
let mut use_str = true;
let mut ref_index_str_pairs = Vec::with_capacity(slice.len());
for (i, p) in slice.iter().enumerate() {
let s = match f(p).as_ref().to_str() {
Some(s) => s,
None => {
use_str = false;
break;
}
};
ref_index_str_pairs.push((i, s));
}
if use_str {
let ref_indexes = ref_index_str_pairs_to_ref_indexes(ref_index_str_pairs);
sort_slice_ref_indexes(slice, ref_indexes);
} else {
fallback(slice, f);
}
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| {
compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
});
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| {
compare_os_str_fallback(f(a).as_ref().as_os_str(), f(b).as_ref().as_os_str())
});
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_unstable_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| {
compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
});
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_rev_by_path_key_fallback<A, T: ?Sized + AsRef<Path>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| {
compare_os_str_fallback(f(b).as_ref().as_os_str(), f(a).as_ref().as_os_str())
});
}
#[allow(clippy::redundant_closure)]
#[inline]
pub fn sort_str_slice<S: AsRef<str>>(slice: &mut [S]) {
slice.sort_unstable_by(|a, b| compare_str(a, b));
}
#[inline]
pub fn sort_str_slice_rev<S: AsRef<str>>(slice: &mut [S]) {
slice.sort_unstable_by(|a, b| compare_str(b, a));
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_os_str_slice<S: AsRef<OsStr>>(slice: &mut [S]) {
sort_slice_unstable_by_os_str_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_os_str_slice_rev<S: AsRef<OsStr>>(slice: &mut [S]) {
sort_slice_rev_unstable_by_os_str_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_c_str_slice<S: AsRef<CStr>>(slice: &mut [S]) {
sort_slice_unstable_by_c_str_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_c_str_slice_rev<S: AsRef<CStr>>(slice: &mut [S]) {
sort_slice_rev_unstable_by_c_str_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_path_slice<P: AsRef<Path>>(slice: &mut [P]) {
sort_slice_unstable_by_path_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
pub fn sort_path_slice_rev<P: AsRef<Path>>(slice: &mut [P]) {
sort_slice_rev_unstable_by_path_key(slice, |e| e.as_ref())
}
#[cfg(feature = "std")]
#[inline]
fn ref_index_str_pairs_to_ref_indexes_unstable(
mut ref_index_str_pairs: Vec<(usize, &str)>,
) -> Vec<(usize, usize)> {
ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(a.1, b.1));
ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
}
#[cfg(feature = "std")]
#[inline]
fn ref_index_str_pairs_to_ref_indexes(
mut ref_index_str_pairs: Vec<(usize, &str)>,
) -> Vec<(usize, usize)> {
ref_index_str_pairs.sort_by(|a, b| compare_str(a.1, b.1));
ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
}
#[cfg(feature = "std")]
#[inline]
fn ref_index_str_pairs_to_ref_indexes_rev_unstable(
mut ref_index_str_pairs: Vec<(usize, &str)>,
) -> Vec<(usize, usize)> {
ref_index_str_pairs.sort_unstable_by(|a, b| compare_str(b.1, a.1));
ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
}
#[cfg(feature = "std")]
#[inline]
fn ref_index_str_pairs_to_ref_indexes_rev(
mut ref_index_str_pairs: Vec<(usize, &str)>,
) -> Vec<(usize, usize)> {
ref_index_str_pairs.sort_by(|a, b| compare_str(b.1, a.1));
ref_index_str_pairs_to_ref_indexes_inner(ref_index_str_pairs)
}
#[cfg(feature = "std")]
#[inline]
fn ref_index_str_pairs_to_ref_indexes_inner(
ref_index_str_pairs: Vec<(usize, &str)>,
) -> Vec<(usize, usize)> {
ref_index_str_pairs
.into_iter()
.enumerate()
.filter_map(|(j, (i, _))| {
if i != j {
Some((i, j))
} else {
None
}
})
.collect()
}
#[cfg(feature = "std")]
#[inline]
fn sort_slice_ref_indexes<S>(slice: &mut [S], mut ref_indexes: Vec<(usize, usize)>) {
let length = ref_indexes.len();
for index in 0..length {
let (i, j) = ref_indexes[index];
slice.swap(i, j);
for (t, _) in ref_indexes[index + 1..].iter_mut() {
if *t == j {
*t = i;
break;
}
}
}
}