hpt_common/utils/
pointer.rs1use std::{
2    fmt::{Debug, Display, Formatter},
3    ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut, SubAssign},
4};
5
6#[derive(Debug)]
11pub struct Pointer<T> {
12    pub ptr: *mut T,
14    #[cfg(feature = "bound_check")]
16    pub len: i64,
17}
18
19impl<T> Clone for Pointer<T> {
20    fn clone(&self) -> Self {
21        Self {
22            ptr: self.ptr.clone(),
23            #[cfg(feature = "bound_check")]
24            len: self.len.clone(),
25        }
26    }
27}
28
29impl<T> Pointer<T> {
30    pub fn cast<U>(&self) -> Pointer<U> {
38        #[cfg(feature = "bound_check")]
39        return Pointer::new(self.ptr as *mut U, self.len);
40        #[cfg(not(feature = "bound_check"))]
41        return Pointer::new(self.ptr as *mut U);
42    }
43    #[inline(always)]
57    pub fn get_ptr(&self) -> *mut T {
58        self.ptr
59    }
60
61    #[cfg(not(feature = "bound_check"))]
77    #[inline(always)]
78    pub fn new(ptr: *mut T) -> Self {
79        Self { ptr }
80    }
81
82    #[cfg(feature = "bound_check")]
98    #[inline(always)]
99    pub fn new(ptr: *mut T, len: i64) -> Self {
100        Self { ptr, len }
101    }
102
103    #[inline(always)]
119    pub fn modify(&mut self, offset: i64, value: T) {
120        unsafe {
121            self.ptr.offset(offset as isize).write(value);
122        }
123    }
124
125    #[inline(always)]
141    pub fn add(&mut self, offset: usize) {
142        unsafe {
143            self.ptr = self.ptr.add(offset);
144        }
145    }
146
147    #[inline(always)]
163    pub fn offset(&mut self, offset: i64) {
164        unsafe {
165            self.ptr = self.ptr.offset(offset as isize);
166        }
167    }
168}
169
170unsafe impl<T> Send for Pointer<T> {}
171
172impl<T> Index<i64> for Pointer<T> {
173    type Output = T;
174    fn index(&self, index: i64) -> &Self::Output {
175        #[cfg(feature = "bound_check")]
176        {
177            if index < 0 || index >= (self.len as i64) {
178                panic!("index out of bounds. index: {}, len: {}", index, self.len);
179            }
180        }
181        unsafe { &*self.ptr.offset(index as isize) }
182    }
183}
184
185impl<T: Display> Index<isize> for Pointer<T> {
186    type Output = T;
187    fn index(&self, index: isize) -> &Self::Output {
188        #[cfg(feature = "bound_check")]
189        {
190            if index < 0 || (index as i64) >= (self.len as i64) {
191                panic!("index out of bounds. index: {}, len: {}", index, self.len);
192            }
193        }
194        unsafe { &*self.ptr.offset(index) }
195    }
196}
197
198impl<T: Display> Index<usize> for Pointer<T> {
199    type Output = T;
200    fn index(&self, index: usize) -> &Self::Output {
201        #[cfg(feature = "bound_check")]
202        {
203            if (index as i64) >= (self.len as i64) {
204                panic!("index out of bounds. index: {}, len: {}", index, self.len);
205            }
206        }
207        unsafe { &*self.ptr.add(index) }
208    }
209}
210
211impl<T: Display> IndexMut<i64> for Pointer<T> {
212    fn index_mut(&mut self, index: i64) -> &mut Self::Output {
213        #[cfg(feature = "bound_check")]
214        {
215            if index < 0 || index >= (self.len as i64) {
216                panic!("index out of bounds. index: {}, len: {}", index, self.len);
217            }
218        }
219        unsafe { &mut *self.ptr.offset(index as isize) }
220    }
221}
222
223impl<T: Display> IndexMut<isize> for Pointer<T> {
224    fn index_mut(&mut self, index: isize) -> &mut Self::Output {
225        #[cfg(feature = "bound_check")]
226        {
227            if index < 0 || (index as i64) >= (self.len as i64) {
228                panic!("index out of bounds. index: {}, len: {}", index, self.len);
229            }
230        }
231        unsafe { &mut *self.ptr.offset(index) }
232    }
233}
234
235impl<T: Display> IndexMut<usize> for Pointer<T> {
236    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
237        #[cfg(feature = "bound_check")]
238        {
239            if (index as i64) >= (self.len as i64) {
240                panic!("index out of bounds. index: {}, len: {}", index, self.len);
241            }
242        }
243        unsafe { &mut *self.ptr.add(index) }
244    }
245}
246
247impl<T> AddAssign<usize> for Pointer<T> {
248    fn add_assign(&mut self, rhs: usize) {
249        #[cfg(feature = "bound_check")]
250        {
251            self.len -= rhs as i64;
252            assert!(self.len >= 0);
253        }
254        unsafe {
255            self.ptr = self.ptr.add(rhs);
256        }
257    }
258}
259
260impl<T> Add<usize> for Pointer<T> {
261    type Output = Self;
262    fn add(self, rhs: usize) -> Self::Output {
263        #[cfg(feature = "bound_check")]
264        unsafe {
265            Self {
266                ptr: self.ptr.add(rhs),
267                len: self.len,
268            }
269        }
270        #[cfg(not(feature = "bound_check"))]
271        unsafe {
272            Self {
273                ptr: self.ptr.add(rhs),
274            }
275        }
276    }
277}
278
279impl<T> AddAssign<usize> for &mut Pointer<T> {
280    fn add_assign(&mut self, rhs: usize) {
281        #[cfg(feature = "bound_check")]
282        {
283            self.len -= rhs as i64;
284        }
285        unsafe {
286            self.ptr = self.ptr.add(rhs);
287        }
288    }
289}
290
291impl<T> AddAssign<i64> for &mut Pointer<T> {
292    fn add_assign(&mut self, rhs: i64) {
293        #[cfg(feature = "bound_check")]
294        {
295            self.len -= rhs;
296            assert!(self.len >= 0);
297        }
298        unsafe {
299            self.ptr = self.ptr.offset(rhs as isize);
300        }
301    }
302}
303
304impl<T> Add<usize> for &mut Pointer<T> {
305    type Output = Pointer<T>;
306    fn add(self, rhs: usize) -> Self::Output {
307        #[cfg(feature = "bound_check")]
308        unsafe {
309            Pointer::new(self.ptr.add(rhs), self.len)
310        }
311        #[cfg(not(feature = "bound_check"))]
312        unsafe {
313            Pointer::new(self.ptr.add(rhs))
314        }
315    }
316}
317
318impl<T> AddAssign<isize> for Pointer<T> {
319    fn add_assign(&mut self, rhs: isize) {
320        #[cfg(feature = "bound_check")]
321        {
322            self.len -= rhs as i64;
323            assert!(self.len >= 0);
324        }
325        unsafe {
326            self.ptr = self.ptr.offset(rhs);
327        }
328    }
329}
330
331impl<T> Add<isize> for Pointer<T> {
332    type Output = Self;
333    fn add(self, rhs: isize) -> Self::Output {
334        #[cfg(feature = "bound_check")]
335        unsafe {
336            Self {
337                ptr: self.ptr.offset(rhs),
338                len: self.len,
339            }
340        }
341        #[cfg(not(feature = "bound_check"))]
342        unsafe {
343            Self {
344                ptr: self.ptr.offset(rhs),
345            }
346        }
347    }
348}
349
350impl<T> AddAssign<i64> for Pointer<T> {
351    fn add_assign(&mut self, rhs: i64) {
352        #[cfg(feature = "bound_check")]
353        {
354            self.len -= rhs as i64;
355            assert!(self.len >= 0);
356        }
357        unsafe {
358            self.ptr = self.ptr.offset(rhs as isize);
359        }
360    }
361}
362
363impl<T> Add<i64> for Pointer<T> {
364    type Output = Self;
365    fn add(self, rhs: i64) -> Self::Output {
366        #[cfg(feature = "bound_check")]
367        unsafe {
368            Self {
369                ptr: self.ptr.offset(rhs as isize),
370                len: self.len,
371            }
372        }
373        #[cfg(not(feature = "bound_check"))]
374        unsafe {
375            Self {
376                ptr: self.ptr.offset(rhs as isize),
377            }
378        }
379    }
380}
381
382impl<T> SubAssign<usize> for Pointer<T> {
383    fn sub_assign(&mut self, rhs: usize) {
384        #[cfg(feature = "bound_check")]
385        {
386            self.len += rhs as i64;
387        }
388        unsafe {
389            self.ptr = self.ptr.offset(-(rhs as isize));
390        }
391    }
392}
393
394impl<T> SubAssign<isize> for Pointer<T> {
395    fn sub_assign(&mut self, rhs: isize) {
396        #[cfg(feature = "bound_check")]
397        {
398            self.len += rhs as i64;
399        }
400        unsafe {
401            self.ptr = self.ptr.offset(-rhs);
402        }
403    }
404}
405
406impl<T> SubAssign<i64> for Pointer<T> {
407    fn sub_assign(&mut self, rhs: i64) {
408        #[cfg(feature = "bound_check")]
409        {
410            self.len += rhs as i64;
411        }
412        unsafe {
413            self.ptr = self.ptr.offset(-rhs as isize);
414        }
415    }
416}
417
418impl<T> SubAssign<i64> for &mut Pointer<T> {
419    fn sub_assign(&mut self, rhs: i64) {
420        #[cfg(feature = "bound_check")]
421        {
422            self.len += rhs as i64;
423        }
424        unsafe {
425            self.ptr = self.ptr.offset(-rhs as isize);
426        }
427    }
428}
429
430impl<T> Deref for Pointer<T> {
431    type Target = T;
432    fn deref(&self) -> &Self::Target {
433        unsafe { &*self.ptr }
434    }
435}
436
437impl<T> DerefMut for Pointer<T> {
438    fn deref_mut(&mut self) -> &mut Self::Target {
439        unsafe { &mut *self.ptr }
440    }
441}
442
443unsafe impl<T> Sync for Pointer<T> {}
444
445impl<T: Display> Display for Pointer<T> {
446    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
447        write!(
448            f,
449            "Pointer( ptr: {}, val: {} )",
450            self.ptr as usize,
451            unsafe { self.ptr.read() }
452        )
453    }
454}