use crate::{SortableBy, TotalOrder};
use alloc::{boxed::Box, vec::Vec};
use core::{borrow::Borrow, cmp::Ordering, marker::PhantomData};
pub struct OrdTotalOrder<T: ?Sized + Ord>(PhantomData<fn(&T)>);
impl<T: ?Sized + Ord> Default for OrdTotalOrder<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T: ?Sized + Ord> Clone for OrdTotalOrder<T> {
fn clone(&self) -> Self {
Self(PhantomData)
}
}
impl<T: ?Sized + Ord> Copy for OrdTotalOrder<T> {}
impl<T: ?Sized + Ord> TotalOrder for OrdTotalOrder<T> {
type OrderedType = T;
fn cmp(&self, this: &T, that: &T) -> Ordering {
this.cmp(that)
}
fn eq<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() == that.sort_key()
}
fn ne<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() != that.sort_key()
}
fn ge<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() >= that.sort_key()
}
fn gt<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() > that.sort_key()
}
fn le<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() <= that.sort_key()
}
fn lt<A, B>(&self, this: &A, that: &B) -> bool
where
A: ?Sized + SortableBy<Self>,
B: ?Sized + SortableBy<Self>,
{
this.sort_key() < that.sort_key()
}
}
impl<T: ?Sized + Ord, K: ?Sized + Borrow<T>> SortableBy<OrdTotalOrder<T>> for K {
fn sort_key(&self) -> &T {
self.borrow()
}
}
pub trait OrdStoredKey: SortableBy<OrdTotalOrder<Self::OrdKeyType>> {
type OrdKeyType: ?Sized + Ord;
}
macro_rules! ord_keys {
() => {};
($(#[$attrs:meta])* $({$($g:tt)+})? $t:ty => $m:ty $(, $($rest:tt)*)?) => {
$(#[$attrs])*
impl$(<$($g)+>)? OrdStoredKey for $t {
type OrdKeyType = $m;
}
$(ord_keys!($($rest)*);)?
};
($(#[$attrs:meta])* $({$($g:tt)+})? $t:ty $(, $($rest:tt)*)?) => {
ord_keys!($(#[$attrs])* $({$($g)+})? $t => Self $(, $($rest)*)?);
};
}
ord_keys! {
(),
bool, char,
i8, u8,
i16, u16,
i32, u32,
i64, u64,
i128, u128,
isize, usize,
alloc::string::String => str, str,
alloc::ffi::CString => core::ffi::CStr, core::ffi::CStr,
{B: ?Sized + Ord + Clone} alloc::borrow::Cow<'_, B> => B,
{T: ?Sized + Ord} &T => T,
{T: ?Sized + Ord} &mut T => T,
{T: ?Sized + Ord} alloc::rc::Rc<T> => T,
{T: ?Sized + Ord} alloc::sync::Arc<T> => T,
{T: Ord, const N: usize} [T; N] => [T], {T: Ord} [T],
#[cfg(feature = "std")] std::ffi::OsString => std::ffi::OsStr, #[cfg(feature = "std")] std::ffi::OsStr,
#[cfg(feature = "std")] std::path::PathBuf => std::path::Path, #[cfg(feature = "std")] std::path::Path,
{T: Ord, #[cfg(feature = "allocator_api")] A: alloc::alloc::Allocator} A!(Vec<T, A>) => [T],
{T: Ord + ?Sized, #[cfg(feature = "allocator_api")] A: alloc::alloc::Allocator} A!(Box<T, A>) => T,
}