#![cfg_attr(not(feature = "std"), no_std)]
mod cmp;
pub mod iter;
pub use cmp::{
cmp, lexical_cmp, lexical_only_alnum_cmp, natural_cmp, natural_lexical_cmp,
natural_lexical_only_alnum_cmp, natural_only_alnum_cmp, only_alnum_cmp,
};
use core::cmp::Ordering;
#[cfg(feature = "std")]
use std::path::Path;
pub trait StringSort {
fn string_sort(&mut self, cmp: impl FnMut(&str, &str) -> Ordering);
fn string_sort_unstable(&mut self, cmp: impl FnMut(&str, &str) -> Ordering);
fn string_sort_by<Cmp, Map>(&mut self, cmp: Cmp, map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str;
fn string_sort_unstable_by<Cmp, Map>(&mut self, cmp: Cmp, map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str;
}
impl<A: AsRef<str>> StringSort for [A] {
fn string_sort(&mut self, mut cmp: impl FnMut(&str, &str) -> Ordering) {
self.sort_by(|lhs, rhs| cmp(lhs.as_ref(), rhs.as_ref()));
}
fn string_sort_unstable(&mut self, mut cmp: impl FnMut(&str, &str) -> Ordering) {
self.sort_unstable_by(|lhs, rhs| cmp(lhs.as_ref(), rhs.as_ref()));
}
fn string_sort_by<Cmp, Map>(&mut self, mut cmp: Cmp, mut map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str,
{
self.sort_by(|lhs, rhs| cmp(map(lhs.as_ref()), map(rhs.as_ref())));
}
fn string_sort_unstable_by<Cmp, Map>(&mut self, mut cmp: Cmp, mut map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str,
{
self.sort_unstable_by(|lhs, rhs| cmp(map(lhs.as_ref()), map(rhs.as_ref())));
}
}
#[cfg(feature = "std")]
pub trait PathSort {
fn path_sort(&mut self, comparator: impl FnMut(&str, &str) -> Ordering);
fn path_sort_unstable(&mut self, comparator: impl FnMut(&str, &str) -> Ordering);
fn path_sort_by<Cmp, Map>(&mut self, cmp: Cmp, map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str;
fn path_sort_unstable_by<Cmp, Map>(&mut self, cmp: Cmp, map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str;
}
#[cfg(feature = "std")]
impl<A: AsRef<Path>> PathSort for [A] {
fn path_sort(&mut self, mut cmp: impl FnMut(&str, &str) -> Ordering) {
self.sort_by(|lhs, rhs| {
cmp(
&lhs.as_ref().to_string_lossy(),
&rhs.as_ref().to_string_lossy(),
)
});
}
fn path_sort_unstable(&mut self, mut cmp: impl FnMut(&str, &str) -> Ordering) {
self.sort_unstable_by(|lhs, rhs| {
cmp(
&lhs.as_ref().to_string_lossy(),
&rhs.as_ref().to_string_lossy(),
)
});
}
fn path_sort_by<Cmp, Map>(&mut self, mut cmp: Cmp, mut map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str,
{
self.sort_by(|lhs, rhs| {
cmp(
map(&lhs.as_ref().to_string_lossy()),
map(&rhs.as_ref().to_string_lossy()),
)
});
}
fn path_sort_unstable_by<Cmp, Map>(&mut self, mut cmp: Cmp, mut map: Map)
where
Cmp: FnMut(&str, &str) -> Ordering,
Map: FnMut(&str) -> &str,
{
self.sort_unstable_by(|lhs, rhs| {
cmp(
map(&lhs.as_ref().to_string_lossy()),
map(&rhs.as_ref().to_string_lossy()),
)
});
}
}
#[test]
fn test_sort() {
macro_rules! assert_lexically_sorted {
($T:ident, $array:expr, natural = $natural:expr) => {{
let mut sorted = $array.clone();
if $natural {
sorted.$T(natural_lexical_cmp);
} else {
sorted.$T(lexical_cmp);
}
assert_eq!($array, sorted);
}};
}
let strings = [
"-", "-$", "-a", "100", "50", "a", "ä", "aa", "áa", "AB", "Ab", "ab", "AE", "ae", "æ", "af",
];
let strings_nat = [
"-", "-$", "-a", "50", "100", "a", "ä", "aa", "áa", "AB", "Ab", "ab", "AE", "ae", "æ", "af",
];
assert_lexically_sorted!(string_sort, strings, natural = false);
assert_lexically_sorted!(string_sort, strings_nat, natural = true);
#[cfg(feature = "std")]
{
let paths: Vec<&Path> = strings.iter().map(|s| Path::new(s)).collect();
let paths_nat: Vec<&Path> = strings_nat.iter().map(|s| Path::new(s)).collect();
assert_lexically_sorted!(path_sort, paths, natural = false);
assert_lexically_sorted!(path_sort, paths_nat, natural = true);
}
}