use std::cmp::Ordering;
pub trait ChunkSorter<T> {
fn sort(&self, chunk: &mut [T], cmp: impl Fn(&T, &T) -> Ordering + Send + Sync);
}
pub struct Sequential;
impl<T> ChunkSorter<T> for Sequential {
#[inline]
fn sort(&self, chunk: &mut [T], cmp: impl Fn(&T, &T) -> Ordering + Send + Sync) {
chunk.sort_unstable_by(cmp);
}
}
#[cfg(feature = "rayon")]
pub struct Parallel;
#[cfg(feature = "rayon")]
impl<T: Send> ChunkSorter<T> for Parallel {
#[inline]
fn sort(&self, chunk: &mut [T], cmp: impl Fn(&T, &T) -> Ordering + Send + Sync) {
use rayon::prelude::*;
chunk.par_sort_unstable_by(cmp);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sequential_sorts_integers() {
let mut data = vec![5, 3, 1, 4, 2];
Sequential.sort(&mut data, Ord::cmp);
assert_eq!(data, vec![1, 2, 3, 4, 5]);
}
#[test]
fn sequential_sorts_empty_slice() {
let mut data: Vec<i32> = vec![];
Sequential.sort(&mut data, Ord::cmp);
assert!(data.is_empty(), "sorting an empty slice should be a no-op");
}
#[test]
fn sequential_sorts_single_element() {
let mut data = vec![42];
Sequential.sort(&mut data, Ord::cmp);
assert_eq!(data, vec![42]);
}
#[test]
fn sequential_sorts_already_sorted() {
let mut data = vec![1, 2, 3, 4, 5];
Sequential.sort(&mut data, Ord::cmp);
assert_eq!(data, vec![1, 2, 3, 4, 5]);
}
#[test]
fn sequential_sorts_reverse() {
let mut data = vec![5, 4, 3, 2, 1];
Sequential.sort(&mut data, |a, b| b.cmp(a));
assert_eq!(
data,
vec![5, 4, 3, 2, 1],
"reverse comparator should preserve reverse order"
);
}
#[test]
fn sequential_sorts_with_custom_comparator() {
let mut data = vec![(3, "c"), (1, "a"), (2, "b")];
Sequential.sort(&mut data, |a, b| a.0.cmp(&b.0));
assert_eq!(data, vec![(1, "a"), (2, "b"), (3, "c")]);
}
#[test]
fn sequential_sorts_strings_by_length() {
let mut data = vec!["hello", "hi", "hey"];
Sequential.sort(&mut data, |a, b| a.len().cmp(&b.len()));
assert_eq!(
data,
vec!["hi", "hey", "hello"],
"should sort by string length"
);
}
#[test]
fn sequential_is_send_and_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<Sequential>();
}
}