1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
use std::marker::PhantomData; use std::u32::MAX; use std::hash; use std::fmt; use std::cmp::Ordering; #[derive(Serialize, Deserialize)] pub struct Id<T> { index: u32, #[serde(skip)] marker: PhantomData<T>, } impl<T> Id<T> { pub fn invalid() -> Self { Self::new(MAX) } pub fn is_invalid(&self) -> bool { self.index == MAX } pub fn is_valid(&self) -> bool { self.index != MAX } pub fn cast<U>(&self) -> Id<U> { Id::new(self.index) } fn new(index: u32) -> Self { Self { index, marker: PhantomData } } } impl<T> Copy for Id<T> {} impl<T> Clone for Id<T> { fn clone(&self) -> Self { *self } } impl<T> PartialEq for Id<T> { fn eq(&self, other: &Self) -> bool { self.index == other.index } } impl<T> Eq for Id<T> {} impl<T> PartialOrd for Id<T> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.index.partial_cmp(&other.index) } } impl<T> Ord for Id<T> { fn cmp(&self, other: &Self) -> Ordering { self.index.cmp(&other.index) } } impl<T> hash::Hash for Id<T> { fn hash<H: hash::Hasher>(&self, hasher: &mut H) { self.index.hash(hasher); } } impl<T> fmt::Debug for Id<T> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "Id[{}]", self.index) } } impl<T> From<usize> for Id<T> { fn from(index: usize) -> Self { if index >= MAX as usize { Self::invalid() } else { Self::new(index as u32) } } } impl<T> Into<usize> for Id<T> { fn into(self) -> usize { self.index as usize } }