mod float;
mod integer;
mod string;
use crate::{ProcessingOrder, RadixDataType, RadixResult, RadixSortable, SortDirection};
use std::marker::PhantomData;
pub struct RadixSort<T>
where
T: RadixSortable,
{
data_type: RadixDataType,
direction: SortDirection,
processing_order: ProcessingOrder,
_phantom: PhantomData<T>,
}
impl<T> RadixSort<T>
where
T: RadixSortable,
{
pub fn new(data_type: RadixDataType, direction: SortDirection) -> Self {
Self {
data_type,
direction,
processing_order: ProcessingOrder::LsbFirst,
_phantom: PhantomData,
}
}
pub fn with_processing_order(
data_type: RadixDataType,
direction: SortDirection,
processing_order: ProcessingOrder,
) -> Self {
Self {
data_type,
direction,
processing_order,
_phantom: PhantomData,
}
}
pub fn sort(&self, slice: &mut [T]) -> RadixResult<()> {
if slice.is_empty() {
return Ok(());
}
for item in slice.iter() {
T::validate(item)?;
}
let result = match self.data_type {
RadixDataType::UnsignedInteger | RadixDataType::SignedInteger => {
self.sort_integers(slice)
}
RadixDataType::Float => self.sort_floats(slice),
RadixDataType::String => self.sort_strings_generic(slice),
};
result?;
if self.direction.is_descending() {
slice.reverse();
}
Ok(())
}
pub fn sort_to_vec(&self, collection: &[T]) -> RadixResult<Vec<T>> {
let mut result = collection.to_vec();
self.sort(&mut result)?;
Ok(result)
}
#[inline]
pub fn data_type(&self) -> RadixDataType {
self.data_type
}
#[inline]
pub fn direction(&self) -> SortDirection {
self.direction
}
#[inline]
pub fn processing_order(&self) -> ProcessingOrder {
self.processing_order
}
}
impl<T> Default for RadixSort<T>
where
T: RadixSortable,
{
fn default() -> Self {
Self::new(T::data_type(), SortDirection::Ascending)
}
}