use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
pub trait Proxy<T: ?Sized> {
fn cmp(lhs: &T, rhs: &T) -> Ordering;
fn eq(lhs: &T, rhs: &T) -> bool {
matches!(Self::cmp(lhs, rhs), Ordering::Equal)
}
fn ne(lhs: &T, rhs: &T) -> bool {
!Self::eq(lhs, rhs)
}
#[inline]
fn wrap(value: T) -> ProxyWrapper<T, Self> where T: Sized {
ProxyWrapper::new(value)
}
}
impl<T> Proxy<T> for ()
where T: ?Sized + Ord {
#[inline]
fn cmp(lhs: &T, rhs: &T) -> Ordering {
Ord::cmp(lhs, rhs)
}
#[inline]
fn eq(lhs: &T, rhs: &T) -> bool {
PartialEq::eq(lhs, rhs)
}
}
#[repr(transparent)]
pub struct ProxyWrapper<T: ?Sized, P: Proxy<T> + ?Sized> {
#[allow(missing_docs)]
pub phantom: PhantomData<P>,
pub inner: T
}
impl<T, P: Proxy<T> + ?Sized> ProxyWrapper<T, P> {
#[inline]
pub const fn new(inner: T) -> Self {
ProxyWrapper { inner, phantom: PhantomData }
}
pub const fn into_inner(self) -> T {
unsafe { crate::transmute::transmute::<ProxyWrapper<T, P>, T>(self) }
}
pub const fn wrap_slice(s: &[T]) -> &[Self] {
unsafe { crate::transmute::transmute_slice::<T, Self>(s) }
}
pub const fn wrap_slice_mut(s: &mut [T]) -> &mut [Self] {
unsafe { crate::transmute::transmute_slice_mut::<T, Self>(s) }
}
pub const fn wrap_array<const N: usize>(s: [T; N]) -> [Self; N] {
unsafe { crate::transmute::transmute::<[T; N], [Self; N]>(s) }
}
pub const fn wrap_array_ref<const N: usize>(s: &[T; N]) -> &[Self; N] {
unsafe { crate::transmute::transmute_ref::<[T; N], [Self; N]>(s) }
}
pub const fn wrap_array_ref_mut<const N: usize>(s: &mut [T; N]) -> &mut [Self; N] {
unsafe { crate::transmute::transmute_ref_mut::<[T; N], [Self; N]>(s) }
}
pub const fn peel_slice(s: &[Self]) -> &[T] {
unsafe { crate::transmute::transmute_slice::<Self, T>(s) }
}
pub const fn peel_slice_mut(s: &mut [Self]) -> &mut [T] {
unsafe { crate::transmute::transmute_slice_mut::<Self, T>(s) }
}
pub const fn peel_array<const N: usize>(s: [Self; N]) -> [T; N] {
unsafe { crate::transmute::transmute::<[Self; N], [T; N]>(s) }
}
pub const fn peel_array_ref<const N: usize>(s: &[Self; N]) -> &[T; N] {
unsafe { crate::transmute::transmute_ref::<[Self; N], [T; N]>(s) }
}
pub const fn peel_array_ref_mut<const N: usize>(s: &mut [Self; N]) -> &mut [T; N] {
unsafe { crate::transmute::transmute_ref_mut::<[Self; N], [T; N]>(s) }
}
}
impl<T: ?Sized, P: Proxy<T> + ?Sized> ProxyWrapper<T, P> {
pub const fn wrap_ref(s: &T) -> &Self {
unsafe { crate::transmute::transmute_ref::<T, Self>(s) }
}
pub const fn wrap_ref_mut(s: &mut T) -> &mut Self {
unsafe { crate::transmute::transmute_ref_mut::<T, Self>(s) }
}
#[inline]
pub const fn peel_ref(s: &Self) -> &T {
&s.inner
}
#[inline]
pub const fn peel_ref_mut(s: &mut Self) -> &mut T {
&mut s.inner
}
}
impl<T: fmt::Debug, P: Proxy<T> + ?Sized> fmt::Debug for ProxyWrapper<T, P> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<T: fmt::Display, P: Proxy<T> + ?Sized> fmt::Display for ProxyWrapper<T, P> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<T: Copy, P: Proxy<T> + ?Sized> Copy for ProxyWrapper<T, P> {}
impl<T: Clone, P: Proxy<T> + ?Sized> Clone for ProxyWrapper<T, P> {
#[inline]
fn clone(&self) -> Self {
ProxyWrapper::new(self.inner.clone())
}
}
impl<T, P: Proxy<T> + ?Sized> PartialEq for ProxyWrapper<T, P> {
#[inline]
fn eq(&self, other: &Self) -> bool {
P::eq(&self.inner, &other.inner)
}
#[allow(clippy::partialeq_ne_impl)]
#[inline]
fn ne(&self, other: &Self) -> bool {
P::ne(&self.inner, &other.inner)
}
}
impl<T, P: Proxy<T> + ?Sized> Eq for ProxyWrapper<T, P> {}
impl<T, P: Proxy<T> + ?Sized> PartialOrd for ProxyWrapper<T, P> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(ProxyWrapper::cmp(self, other))
}
}
impl<T, P: Proxy<T> + ?Sized> Ord for ProxyWrapper<T, P> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
P::cmp(&self.inner, &other.inner)
}
}
impl<T: Default, P: Proxy<T> + ?Sized> Default for ProxyWrapper<T, P> {
fn default() -> Self {
ProxyWrapper::new(T::default())
}
}
impl<T: Hash, P: Proxy<T> + ?Sized> Hash for ProxyWrapper<T, P> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
#[cfg(feature = "serde")]
impl<T, P: Proxy<T>> serde::Serialize for ProxyWrapper<T, P>
where T: serde::Serialize {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer {
T::serialize(&self.inner, serializer)
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
#[cfg(feature = "serde")]
impl<'de, T, P: Proxy<T>> serde::Deserialize<'de> for ProxyWrapper<T, P>
where T: serde::Deserialize<'de> + Ord {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> {
T::deserialize(deserializer).map(ProxyWrapper::new)
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct TotalOrdFloat {}
impl Proxy<f64> for TotalOrdFloat {
#[inline]
fn cmp(lhs: &f64, rhs: &f64) -> Ordering {
f64::total_cmp(lhs, rhs)
}
}
impl Proxy<f32> for TotalOrdFloat {
#[inline]
fn cmp(lhs: &f32, rhs: &f32) -> Ordering {
f32::total_cmp(lhs, rhs)
}
}
impl<T> Proxy<&T> for TotalOrdFloat
where TotalOrdFloat: Proxy<T> {
#[inline]
fn cmp(lhs: &&T, rhs: &&T) -> Ordering {
TotalOrdFloat::cmp(&**lhs, &**rhs)
}
#[inline]
fn eq(lhs: &&T, rhs: &&T) -> bool {
TotalOrdFloat::eq(&**lhs, &**rhs)
}
#[inline]
fn ne(lhs: &&T, rhs: &&T) -> bool {
TotalOrdFloat::ne(&**lhs, &**rhs)
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct OrdSliceLike<Slice, T, P = ()>
where Slice: AsRef<[T]>, P: Proxy<T> + ?Sized {
slice: PhantomData<Slice>,
value: PhantomData<T>,
proxy: PhantomData<P>
}
impl<Slice, T, P> OrdSliceLike<Slice, T, P>
where Slice: AsRef<[T]>, P: Proxy<T> + ?Sized {
#[inline]
fn get_proxy_wrapper_slice(slice: &Slice) -> &[ProxyWrapper<T, P>] {
ProxyWrapper::wrap_slice(slice.as_ref())
}
}
impl<Slice, T, P> Proxy<Slice> for OrdSliceLike<Slice, T, P>
where Slice: AsRef<[T]>, P: Proxy<T> + ?Sized {
fn cmp(lhs: &Slice, rhs: &Slice) -> Ordering {
Ord::cmp(Self::get_proxy_wrapper_slice(lhs), Self::get_proxy_wrapper_slice(rhs))
}
fn eq(lhs: &Slice, rhs: &Slice) -> bool {
Self::get_proxy_wrapper_slice(lhs) == Self::get_proxy_wrapper_slice(rhs)
}
fn ne(lhs: &Slice, rhs: &Slice) -> bool {
Self::get_proxy_wrapper_slice(lhs) != Self::get_proxy_wrapper_slice(rhs)
}
}
impl<Slice, T, P> Proxy<&Slice> for OrdSliceLike<Slice, T, P>
where Slice: AsRef<[T]>, P: Proxy<T> + ?Sized {
#[inline]
fn cmp(lhs: &&Slice, rhs: &&Slice) -> Ordering {
OrdSliceLike::<Slice, T, P>::cmp(&**lhs, &**rhs)
}
#[inline]
fn eq(lhs: &&Slice, rhs: &&Slice) -> bool {
OrdSliceLike::<Slice, T, P>::eq(&**lhs, &**rhs)
}
#[inline]
fn ne(lhs: &&Slice, rhs: &&Slice) -> bool {
OrdSliceLike::<Slice, T, P>::ne(&**lhs, &**rhs)
}
}