1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::marker::PhantomData;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
6pub struct HeapHandleId(usize);
7
8impl HeapHandleId {
9 pub fn new(id: usize) -> Self {
10 Self(id)
11 }
12
13 pub fn as_usize(&self) -> usize {
14 self.0
15 }
16
17 pub fn is_valid(&self) -> bool {
18 self.0 != usize::MAX
19 }
20}
21
22impl From<usize> for HeapHandleId {
23 fn from(id: usize) -> Self {
24 Self(id)
25 }
26}
27
28impl From<HeapHandleId> for usize {
29 fn from(handle: HeapHandleId) -> Self {
30 handle.0
31 }
32}
33
34impl fmt::Display for HeapHandleId {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 write!(f, "Handle({})", self.0)
37 }
38}
39
40pub trait HandleEntry: Send + Sync {}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
43pub struct HeapHandle<T: HandleEntry> {
44 id: HeapHandleId,
45 _phantom: PhantomData<T>,
46}
47
48impl<T: HandleEntry> HeapHandle<T> {
49 pub fn new(id: HeapHandleId) -> Self {
50 Self {
51 id,
52 _phantom: PhantomData,
53 }
54 }
55
56 pub fn from_usize(id: usize) -> Self {
57 Self::new(HeapHandleId::new(id))
58 }
59
60 pub fn id(&self) -> HeapHandleId {
61 self.id
62 }
63
64 pub fn as_usize(&self) -> usize {
65 self.id.as_usize()
66 }
67
68 pub fn is_valid(&self) -> bool {
69 self.id.is_valid()
70 }
71}
72
73impl<T: HandleEntry> From<usize> for HeapHandle<T> {
74 fn from(id: usize) -> Self {
75 Self::from_usize(id)
76 }
77}
78
79impl<T: HandleEntry> From<HeapHandle<T>> for usize {
80 fn from(handle: HeapHandle<T>) -> Self {
81 handle.as_usize()
82 }
83}
84
85impl<T: HandleEntry> fmt::Display for HeapHandle<T> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(f, "{}", self.id)
88 }
89}
90
91#[derive(Debug, Clone, PartialEq)]
92pub struct ObjectEntry;
93#[derive(Debug, Clone, PartialEq)]
94pub struct ArrayEntry;
95#[derive(Debug, Clone, PartialEq)]
96pub struct FunctionEntry;
97
98impl HandleEntry for ObjectEntry {}
99impl HandleEntry for ArrayEntry {}
100impl HandleEntry for FunctionEntry {}
101
102pub type ObjectHandle = HeapHandle<ObjectEntry>;
103pub type ArrayHandle = HeapHandle<ArrayEntry>;
104pub type FunctionHandle = HeapHandle<FunctionEntry>;
105
106pub const INVALID_HANDLE: HeapHandleId = HeapHandleId(usize::MAX);
107
108pub fn create_object_handle(id: usize) -> ObjectHandle {
109 ObjectHandle::from_usize(id)
110}
111
112pub fn create_array_handle(id: usize) -> ArrayHandle {
113 ArrayHandle::from_usize(id)
114}
115
116pub fn create_function_handle(id: usize) -> FunctionHandle {
117 FunctionHandle::from_usize(id)
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_handle_creation() {
126 let handle_id = HeapHandleId::new(42);
127 assert_eq!(handle_id.as_usize(), 42);
128 assert!(handle_id.is_valid());
129
130 let obj_handle = ObjectHandle::from_usize(42);
131 assert_eq!(obj_handle.as_usize(), 42);
132 assert!(obj_handle.is_valid());
133 }
134
135 #[test]
136 fn test_invalid_handle() {
137 assert!(!INVALID_HANDLE.is_valid());
138
139 let invalid_obj = ObjectHandle::new(INVALID_HANDLE);
140 assert!(!invalid_obj.is_valid());
141 }
142
143 #[test]
144 fn test_handle_conversion() {
145 let id = 123;
146 let handle_id: HeapHandleId = id.into();
147 let back_to_usize: usize = handle_id.into();
148 assert_eq!(back_to_usize, id);
149
150 let obj_handle: ObjectHandle = id.into();
151 let back_to_usize: usize = obj_handle.into();
152 assert_eq!(back_to_usize, id);
153 }
154
155 #[test]
156 fn test_handle_display() {
157 let handle_id = HeapHandleId::new(42);
158 assert_eq!(handle_id.to_string(), "Handle(42)");
159
160 let obj_handle = ObjectHandle::from_usize(42);
161 assert_eq!(obj_handle.to_string(), "Handle(42)");
162 }
163}