1use std::{cmp::Ordering, fmt, hash, marker::PhantomData};
9
10pub type Index = crate::non_max_u32::NonMaxU32;
14
15#[derive(Clone, Copy, Debug, thiserror::Error, PartialEq)]
16#[error("Handle {index} of {kind} is either not present, or inaccessible yet")]
17pub struct BadHandle {
18 pub kind: &'static str,
19 pub index: usize,
20}
21
22impl BadHandle {
23 pub fn new<T>(handle: Handle<T>) -> Self {
24 Self {
25 kind: std::any::type_name::<T>(),
26 index: handle.index(),
27 }
28 }
29}
30
31#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
38#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
39#[cfg_attr(
40 any(feature = "serialize", feature = "deserialize"),
41 serde(transparent)
42)]
43#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
44pub struct Handle<T> {
45 index: Index,
46 #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
47 marker: PhantomData<T>,
48}
49
50impl<T> Clone for Handle<T> {
51 fn clone(&self) -> Self {
52 *self
53 }
54}
55
56impl<T> Copy for Handle<T> {}
57
58impl<T> PartialEq for Handle<T> {
59 fn eq(&self, other: &Self) -> bool {
60 self.index == other.index
61 }
62}
63
64impl<T> Eq for Handle<T> {}
65
66impl<T> PartialOrd for Handle<T> {
67 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68 Some(self.cmp(other))
69 }
70}
71
72impl<T> Ord for Handle<T> {
73 fn cmp(&self, other: &Self) -> Ordering {
74 self.index.cmp(&other.index)
75 }
76}
77
78impl<T> fmt::Debug for Handle<T> {
79 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
80 write!(formatter, "[{}]", self.index)
81 }
82}
83
84impl<T> hash::Hash for Handle<T> {
85 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
86 self.index.hash(hasher)
87 }
88}
89
90impl<T> Handle<T> {
91 pub(crate) const fn new(index: Index) -> Self {
92 Handle {
93 index,
94 marker: PhantomData,
95 }
96 }
97
98 pub const fn index(self) -> usize {
100 self.index.get() as usize
101 }
102
103 pub(super) fn from_usize(index: usize) -> Self {
105 let handle_index = u32::try_from(index)
106 .ok()
107 .and_then(Index::new)
108 .expect("Failed to insert into arena. Handle overflows");
109 Handle::new(handle_index)
110 }
111
112 pub(super) const unsafe fn from_usize_unchecked(index: usize) -> Self {
114 Handle::new(Index::new_unchecked(index as u32))
115 }
116
117 pub fn write_prefixed(
119 &self,
120 formatter: &mut fmt::Formatter,
121 prefix: &'static str,
122 ) -> fmt::Result {
123 formatter.write_str(prefix)?;
124 <usize as fmt::Display>::fmt(&self.index(), formatter)
125 }
126}