1use crate::ObjectType;
2use vpi_sys::{vpiHandle, PLI_INT32};
3
4#[derive(Debug, Clone)]
9pub struct Handle {
10 handle: vpiHandle,
12}
13
14impl Default for Handle {
15 fn default() -> Self {
16 Self::null()
17 }
18}
19
20impl PartialEq for Handle {
21 fn eq(&self, other: &Self) -> bool {
22 unsafe { vpi_sys::vpi_compare_objects(self.handle, other.handle) != 0 }
23 }
24}
25
26impl Drop for Handle {
27 fn drop(&mut self) {
28 #[cfg(feature = "release_handle")]
29 if !self.is_null() {
30 unsafe {
31 vpi_sys::vpi_release_handle(self.handle);
32 }
33 }
34 }
35}
36
37impl Handle {
38 #[must_use]
40 pub fn null() -> Self {
41 Self {
42 handle: std::ptr::null_mut(),
43 }
44 }
45
46 #[must_use]
48 pub fn is_null(&self) -> bool {
49 self.handle.is_null()
50 }
51
52 #[must_use]
54 pub fn as_raw(&self) -> vpiHandle {
55 self.handle
56 }
57
58 pub fn clear(&mut self) {
62 self.handle = std::ptr::null_mut();
63 }
64
65 pub fn from_raw(raw: vpiHandle) -> Self {
67 Self { handle: raw }
68 }
69
70 #[must_use]
76 pub fn handle_by_name(name: &str) -> Self {
77 Self::handle_by_name_and_scope(name, &Handle::null())
78 }
79
80 #[must_use]
86 pub fn handle_by_name_and_scope(name: &str, scope: &Handle) -> Self {
87 let Ok(c_name) = std::ffi::CString::new(name) else {
88 return Self::null();
89 };
90 let scope_raw = if scope.is_null() {
91 std::ptr::null_mut()
92 } else {
93 scope.as_raw()
94 };
95 let handle =
96 unsafe { vpi_sys::vpi_handle_by_name(c_name.as_ptr().cast_mut().cast(), scope_raw) };
97 Self::from_raw(handle)
98 }
99
100 #[must_use]
102 pub fn iterator(&self, typ: ObjectType) -> HandleIterator {
103 let raw = unsafe { vpi_sys::vpi_iterate(typ as PLI_INT32, self.as_raw()) };
104 HandleIterator {
105 iter: Handle::from_raw(raw),
106 }
107 }
108
109 #[must_use]
113 pub fn get(&self, typ: ObjectType) -> Self {
114 let handle = unsafe { vpi_sys::vpi_handle(typ as PLI_INT32, self.as_raw()) };
115 Self::from_raw(handle)
116 }
117
118 #[must_use]
122 pub fn handle_by_index(&self, index: i32) -> Self {
123 let handle = unsafe { vpi_sys::vpi_handle_by_index(self.as_raw(), index) };
124 Self::from_raw(handle)
125 }
126
127 pub fn iterators<'a>(&'a self, typ: &'a [ObjectType]) -> impl Iterator<Item = Handle> + 'a {
129 typ.iter().copied().flat_map(move |t| self.iterator(t))
130 }
131
132 #[must_use]
138 pub fn get_multi(&self, typ: ObjectType, other: &Handle) -> Self {
139 if self.is_null() || other.is_null() {
140 return Self::null();
141 }
142
143 let handle =
144 unsafe { vpi_sys::vpi_handle_multi(typ as PLI_INT32, self.as_raw(), other.as_raw()) };
145 Self::from_raw(handle)
146 }
147
148 #[must_use]
155 pub fn handle_by_multi_index(&self, indices: impl AsRef<[i32]>) -> Self {
156 let indices = indices.as_ref();
157 if self.is_null() || indices.is_empty() {
158 return Self::null();
159 }
160
161 let Ok(num_index) = i32::try_from(indices.len()) else {
162 return Self::null();
163 };
164
165 let handle = unsafe {
166 vpi_sys::vpi_handle_by_multi_index(
167 self.as_raw(),
168 num_index as PLI_INT32,
169 indices.as_ptr().cast_mut(),
170 )
171 };
172 Self::from_raw(handle)
173 }
174
175 #[must_use]
180 pub fn multi_handle_traversal(&self, typ: ObjectType, indices: impl AsRef<[i32]>) -> Self {
181 self.get(typ).handle_by_multi_index(indices)
182 }
183}
184
185pub struct HandleIterator {
187 pub(crate) iter: Handle,
189}
190
191impl Iterator for HandleIterator {
192 type Item = Handle;
193
194 fn next(&mut self) -> Option<Self::Item> {
195 if self.iter.is_null() {
196 return None;
197 }
198
199 let next = Handle::from_raw(unsafe { vpi_sys::vpi_scan(self.iter.as_raw()) });
200
201 if next.is_null() {
202 self.iter.clear();
204 None
205 } else {
206 Some(next)
207 }
208 }
209}