use crate::feature::*;
use core::UriBound;
use std::cmp::{Ordering, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::num::NonZeroU32;
#[repr(transparent)]
pub struct URID<T = ()>(NonZeroU32, PhantomData<T>)
where
T: ?Sized;
pub trait URIDCollection: Sized {
fn from_map(map: &Map) -> Option<Self>;
}
impl URID<()> {
#[inline]
pub fn new(raw_urid: u32) -> Option<Self> {
NonZeroU32::new(raw_urid).map(|inner| Self(inner, PhantomData))
}
}
impl<T: ?Sized> URID<T> {
pub unsafe fn new_unchecked(raw_urid: u32) -> Self {
Self(NonZeroU32::new_unchecked(raw_urid), PhantomData)
}
pub fn get(self) -> u32 {
self.0.get()
}
pub fn into_general(self) -> URID<()> {
unsafe { URID::new_unchecked(self.get()) }
}
}
impl<T: UriBound + ?Sized> URIDCollection for URID<T> {
fn from_map(map: &Map) -> Option<Self> {
map.map_type()
}
}
impl<T: ?Sized> fmt::Debug for URID<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: ?Sized> Clone for URID<T> {
fn clone(&self) -> Self {
Self(self.0, PhantomData)
}
}
impl<T: ?Sized> Copy for URID<T> {}
impl<T1: ?Sized, T2: ?Sized> PartialEq<URID<T1>> for URID<T2> {
fn eq(&self, other: &URID<T1>) -> bool {
self.0 == other.0
}
}
impl<T: ?Sized> PartialEq<u32> for URID<T> {
fn eq(&self, other: &u32) -> bool {
self.get() == *other
}
}
impl<T: ?Sized> PartialEq<URID<T>> for u32 {
fn eq(&self, other: &URID<T>) -> bool {
*self == other.get()
}
}
impl<T: ?Sized> Eq for URID<T> {}
impl<T1: ?Sized, T2: ?Sized> PartialOrd<URID<T1>> for URID<T2> {
fn partial_cmp(&self, other: &URID<T1>) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T: ?Sized> PartialOrd<u32> for URID<T> {
fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
self.get().partial_cmp(other)
}
}
impl<T: ?Sized> PartialOrd<URID<T>> for u32 {
fn partial_cmp(&self, other: &URID<T>) -> Option<Ordering> {
self.partial_cmp(&other.get())
}
}
impl<T: ?Sized> Ord for URID<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<T: ?Sized> Hash for URID<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl std::convert::TryFrom<u32> for URID {
type Error = ();
fn try_from(value: u32) -> Result<URID, ()> {
if value == 0 {
Err(())
} else {
Ok(unsafe { URID::new_unchecked(value) })
}
}
}
#[cfg(test)]
mod tests {
use crate::URID;
#[test]
fn test_urid_size() {
use std::mem::size_of;
let size = size_of::<u32>();
assert_eq!(size, size_of::<URID>());
assert_eq!(size, size_of::<Option<URID>>());
}
}