jetcrab\vm/
handle.rs

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}