#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
#![warn(deprecated_in_future)]
#![doc(test(attr(warn(unused))))]
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt;
use core::ops::{Deref, DerefMut};
pub trait ArbitraryOrd<Rhs = Self>: PartialEq<Rhs> {
fn arbitrary_cmp(&self, other: &Rhs) -> Ordering;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Ordered<T>(pub T);
impl<T: Copy> Copy for Ordered<T> {}
impl<T> Ordered<T> {
pub const fn new(inner: T) -> Self { Self(inner) }
#[allow(clippy::ptr_as_ptr)]
pub fn from_ref(value: &T) -> &Self { unsafe { &*(value as *const _ as *const Self) } }
#[deprecated(since = "0.3.0", note = "use `ops::Deref` instead")]
pub const fn as_inner(&self) -> &T { &self.0 }
#[deprecated(since = "0.3.0", note = "use `ops::Deref` instead")]
pub fn into_inner(self) -> T { self.0 }
}
impl<T: ArbitraryOrd> ArbitraryOrd for &T {
fn arbitrary_cmp(&self, other: &Self) -> Ordering { (*self).arbitrary_cmp(other) }
}
impl<T: ArbitraryOrd> PartialOrd for Ordered<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some((*self).arbitrary_cmp(other)) }
}
impl<T: ArbitraryOrd + Eq> Ord for Ordered<T> {
fn cmp(&self, other: &Self) -> Ordering { (*self).arbitrary_cmp(other) }
}
impl<T: fmt::Display> fmt::Display for Ordered<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
impl<T> From<T> for Ordered<T> {
fn from(inner: T) -> Self { Self(inner) }
}
impl<T> AsRef<T> for Ordered<T> {
fn as_ref(&self) -> &T { &self.0 }
}
impl<T> AsMut<T> for Ordered<T> {
fn as_mut(&mut self) -> &mut T { &mut self.0 }
}
impl<T> Borrow<T> for Ordered<T> {
fn borrow(&self) -> &T { &self.0 }
}
impl<T> BorrowMut<T> for Ordered<T> {
fn borrow_mut(&mut self) -> &mut T { &mut self.0 }
}
impl<T> Deref for Ordered<T> {
type Target = T;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl<T> DerefMut for Ordered<T> {
fn deref_mut(&mut self) -> &mut T { &mut self.0 }
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Point {
x: u32,
y: u32,
}
impl Point {
fn new(x: u32, y: u32) -> Self { Point { x, y } }
}
impl ArbitraryOrd for Point {
fn arbitrary_cmp(&self, other: &Self) -> Ordering {
(self.x, self.y).cmp(&(other.x, other.y))
}
}
#[test]
fn can_compare() {
let a = Point::new(2, 3);
let b = Point::new(5, 7);
assert!(Ordered(a) < Ordered(b));
}
#[test]
fn can_compare_with_from_ref() {
let a = Point::new(2, 3);
let b = Point::new(5, 7);
assert!(Ordered::from_ref(&a) < Ordered::from_ref(&b));
}
#[test]
fn can_compare_with_reference() {
let a = Point::new(2, 3);
let b = Point::new(5, 7);
assert!(Ordered(&a) < Ordered(&b));
}
#[test]
fn send() {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Point {
x: u32,
y: u32,
}
impl ArbitraryOrd for Point {
fn arbitrary_cmp(&self, other: &Self) -> Ordering {
(self.x, self.y).cmp(&(other.x, other.y))
}
}
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Ordered<Point>>();
assert_sync::<Ordered<Point>>();
}
#[test]
fn trait_is_object_safe() {
extern crate std;
use std::boxed::Box;
#[allow(dead_code)]
struct ObjectSafe {
p: Box<dyn ArbitraryOrd<Self>>,
q: Box<dyn PartialOrd<Self>>, }
}
}