my_ecs/ds/ptr.rs
1use super::types::TypeIdExt;
2use std::{
3 cmp, fmt, hash,
4 ops::{Deref, DerefMut},
5 ptr::NonNull,
6};
7
8/// A pointer that implements [`Send`] and [`Sync`] regardless of whether `T`
9/// implements both [`Send`] and [`Sync`].
10///
11/// # Safety
12///
13/// This pointer can be sent to another worker. Owner must guarantee that
14/// sending the pointer is safe. For instance, if you are controlling access to
15/// pointer over workers completely, it will be safe in terms of `Send` and
16/// `Sync`.
17#[derive(Debug)]
18#[repr(transparent)]
19pub struct SendSyncPtr<T: ?Sized>(NonNull<T>);
20
21unsafe impl<T: ?Sized> Send for SendSyncPtr<T> {}
22unsafe impl<T: ?Sized> Sync for SendSyncPtr<T> {}
23
24impl<T: ?Sized> SendSyncPtr<T> {
25 /// Creates a [`SendSyncPtr`] by wrapping the given pointer.
26 ///
27 /// # Examples
28 ///
29 /// ```
30 /// use my_ecs::ds::SendSyncPtr;
31 /// use std::ptr::NonNull;
32 ///
33 /// let mut v = 0;
34 /// let ptr = NonNull::new(&mut v as *mut i32).unwrap();
35 /// let ptr = SendSyncPtr::new(ptr);
36 /// ```
37 #[inline]
38 pub const fn new(ptr: NonNull<T>) -> Self {
39 Self(ptr)
40 }
41
42 /// Creates a [`SendSyncPtr`] that is dangling, but well-aligned.
43 ///
44 /// In many Rust functions, they require aligned pointers even if they are
45 /// some trash values. This function will be usuful in that cases.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// use my_ecs::ds::SendSyncPtr;
51 /// use std::ptr::NonNull;
52 ///
53 /// let dangling = SendSyncPtr::<i32>::dangling();
54 /// ```
55 #[inline]
56 pub const fn dangling() -> Self
57 where
58 T: Sized,
59 {
60 Self::new(NonNull::dangling())
61 }
62
63 /// Returns true if the pointer is dangling.
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// use my_ecs::ds::SendSyncPtr;
69 ///
70 /// let dangling = SendSyncPtr::<i32>::dangling();
71 /// assert!(dangling.is_dangling());
72 /// ```
73 #[inline]
74 pub fn is_dangling(&self) -> bool
75 where
76 T: Sized,
77 {
78 self == &Self::dangling()
79 }
80
81 /// Creates a [`NonNull`] from this pointer.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use my_ecs::ds::SendSyncPtr;
87 /// use std::ptr::NonNull;
88 ///
89 /// let mut v = 0;
90 /// let nn = NonNull::new(&mut v as *mut i32).unwrap();
91 /// let ptr = SendSyncPtr::new(nn);
92 /// assert_eq!(ptr.as_nonnull(), nn);
93 /// ```
94 #[inline]
95 pub const fn as_nonnull(self) -> NonNull<T> {
96 self.0
97 }
98
99 /// Creates a raw pointer from this pointer.
100 ///
101 /// # Examples
102 ///
103 /// ```
104 /// use my_ecs::ds::SendSyncPtr;
105 /// use std::ptr::NonNull;
106 ///
107 /// let mut v = 0;
108 /// let nn = NonNull::new(&mut v as *mut i32).unwrap();
109 /// let ptr = SendSyncPtr::new(nn);
110 /// assert_eq!(ptr.as_ptr(), nn.as_ptr());
111 /// ```
112 #[inline]
113 pub const fn as_ptr(self) -> *mut T {
114 self.0.as_ptr()
115 }
116
117 /// Returns a shared reference to the value.
118 ///
119 /// # Safety
120 ///
121 /// See [`NonNull::as_ref`].
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// use my_ecs::ds::SendSyncPtr;
127 /// use std::ptr::NonNull;
128 ///
129 /// let mut v = 0;
130 /// let ptr = NonNull::new(&mut v as *mut i32).unwrap();
131 /// let ptr = SendSyncPtr::new(ptr);
132 /// let ref_v = unsafe { ptr.as_ref() };
133 /// assert_eq!(ref_v, &v);
134 /// ```
135 #[inline]
136 pub const unsafe fn as_ref<'a>(&self) -> &'a T {
137 unsafe { self.0.as_ref() }
138 }
139
140 /// Returns a mutable reference to the value.
141 ///
142 /// # Safety
143 ///
144 /// See [`NonNull::as_mut`].
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use my_ecs::ds::SendSyncPtr;
150 /// use std::ptr::NonNull;
151 ///
152 /// let mut v = 0;
153 /// let ptr = NonNull::new(&mut v as *mut i32).unwrap();
154 /// let mut ptr = SendSyncPtr::new(ptr);
155 /// let mut_v = unsafe { ptr.as_mut() };
156 /// assert_eq!(mut_v, &mut v);
157 /// ```
158 #[inline]
159 pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
160 unsafe { self.0.as_mut() }
161 }
162
163 /// Adds an offset to the pointer then returns the result.
164 ///
165 /// Note that `count` is in units of `T`. For example, `count` = 3 means
166 /// 12 bytes offset if `T` is `i32`.
167 ///
168 /// # Safety
169 ///
170 /// See [`NonNull::add`].
171 ///
172 /// # Examples
173 ///
174 /// ```
175 /// use my_ecs::ds::SendSyncPtr;
176 /// use std::ptr::NonNull;
177 ///
178 /// let arr: [char; 3] = ['a', 'b', 'c'];
179 /// let ptr = NonNull::new(arr.as_ptr().cast_mut()).unwrap();
180 /// let ptr = SendSyncPtr::new(ptr);
181 ///
182 /// let ref_v = unsafe { ptr.add(1).as_ref() };
183 /// assert_eq!(ref_v, &'b');
184 ///
185 /// let ref_v = unsafe { ptr.add(2).as_ref() };
186 /// assert_eq!(ref_v, &'c');
187 /// ```
188 #[inline]
189 pub const unsafe fn add(self, count: usize) -> Self
190 where
191 T: Sized,
192 {
193 let inner = unsafe { self.0.add(count) };
194 Self::new(inner)
195 }
196
197 /// Subtracts an offset from the pointer then returns the result.
198 ///
199 /// Note that `count` is in units of `T`. For example, `count` = 3 means
200 /// 12 bytes offset if `T` is `i32`.
201 ///
202 /// # Safety
203 ///
204 /// See [`NonNull::sub`].
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// use my_ecs::ds::SendSyncPtr;
210 /// use std::ptr::NonNull;
211 ///
212 /// let arr: [char; 3] = ['a', 'b', 'c'];
213 /// let ptr = NonNull::new((&arr[2] as *const char).cast_mut()).unwrap();
214 /// let ptr = SendSyncPtr::new(ptr);
215 ///
216 /// let ref_v = unsafe { ptr.sub(1).as_ref() };
217 /// assert_eq!(ref_v, &'b');
218 ///
219 /// let ref_v = unsafe { ptr.sub(2).as_ref() };
220 /// assert_eq!(ref_v, &'a');
221 /// ```
222 #[inline]
223 pub const unsafe fn sub(self, count: usize) -> Self
224 where
225 T: Sized,
226 {
227 let inner = unsafe { self.0.sub(count) };
228 Self::new(inner)
229 }
230
231 /// Casts the pointer to another type.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use my_ecs::ds::SendSyncPtr;
237 /// use std::ptr::NonNull;
238 ///
239 /// let mut v = 0x1234_5678;
240 /// let ptr = NonNull::new(&mut v as *mut i32).unwrap();
241 /// let ptr = SendSyncPtr::new(ptr);
242 ///
243 /// let ptr = ptr.cast::<[u8; 4]>();
244 /// let ref_v = unsafe { ptr.as_ref() };
245 /// assert_eq!(*ref_v, i32::to_ne_bytes(v));
246 /// ```
247 #[inline]
248 pub const fn cast<U>(self) -> SendSyncPtr<U> {
249 // Safety: Nothing has changed except `T` -> `U`.
250 SendSyncPtr::new(self.0.cast())
251 }
252}
253
254impl<T: ?Sized> PartialEq for SendSyncPtr<T> {
255 #[allow(ambiguous_wide_pointer_comparisons)]
256 #[inline]
257 fn eq(&self, other: &Self) -> bool {
258 self.as_ptr() == other.as_ptr()
259 }
260}
261
262impl<T: ?Sized> Eq for SendSyncPtr<T> {}
263
264impl<T: ?Sized> PartialOrd for SendSyncPtr<T> {
265 #[inline]
266 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
267 Some(self.cmp(other))
268 }
269}
270
271impl<T: ?Sized> Ord for SendSyncPtr<T> {
272 #[allow(ambiguous_wide_pointer_comparisons)]
273 #[inline]
274 fn cmp(&self, other: &Self) -> cmp::Ordering {
275 self.as_ptr().cmp(&other.as_ptr())
276 }
277}
278
279impl<T: ?Sized> hash::Hash for SendSyncPtr<T> {
280 #[inline]
281 fn hash<H: hash::Hasher>(&self, state: &mut H) {
282 self.0.hash(state)
283 }
284}
285
286impl<T: ?Sized> Clone for SendSyncPtr<T> {
287 #[inline]
288 fn clone(&self) -> Self {
289 *self
290 }
291}
292
293impl<T: ?Sized> Copy for SendSyncPtr<T> {}
294
295/// A pointer that is extended with type id or name.
296///
297/// If 'check' feature is enabled, it contains type id or name. Otherwise, it's
298/// just a [`NonNull`]. This is useful when you want to know the type of the
299/// pointer.
300#[cfg_attr(not(feature = "check"), repr(transparent))]
301pub struct NonNullExt<T: ?Sized> {
302 inner: NonNull<T>,
303 #[cfg(feature = "check")]
304 ty_or_name: crate::util::Or<TypeIdExt, &'static str>,
305}
306
307impl<T: ?Sized> fmt::Debug for NonNullExt<T> {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 #[cfg(not(feature = "check"))]
310 {
311 self.inner.fmt(f)
312 }
313
314 #[cfg(feature = "check")]
315 {
316 write!(f, "NonNullExt({:?})", self.ty_or_name)
317 }
318 }
319}
320
321impl<T: ?Sized> NonNullExt<T> {
322 /// Creates a [`NonNullExt`] from the given pointer.
323 ///
324 /// Returns `None` if the pointer is null.
325 ///
326 /// # Examples
327 ///
328 /// ```
329 /// use my_ecs::ds::NonNullExt;
330 ///
331 /// let mut v = 0;
332 /// let ptr = NonNullExt::new(&mut v as *mut i32).unwrap();
333 /// ```
334 #[inline]
335 pub fn new(ptr: *mut T) -> Option<Self> {
336 let ptr = NonNull::new(ptr)?;
337 Some(Self::from_nonnull(ptr))
338 }
339
340 /// Creates a [`NonNullExt`] from the given pointer.
341 ///
342 /// # Safety
343 ///
344 /// The pointer must be non-null.
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use my_ecs::ds::NonNullExt;
350 ///
351 /// let mut v = 0;
352 /// let ptr = unsafe { NonNullExt::new_unchecked(&mut v as *mut i32) };
353 /// ```
354 #[inline]
355 pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
356 debug_assert!(
357 !ptr.is_null(),
358 "NonNullExt::new_unchecked: expected non-null pointer"
359 );
360
361 Self {
362 inner: unsafe { NonNull::new_unchecked(ptr) },
363 #[cfg(feature = "check")]
364 ty_or_name: crate::util::Or::B(std::any::type_name::<T>()),
365 }
366 }
367
368 /// Creates a [`NonNullExt`] from the given pointer.
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// use my_ecs::ds::NonNullExt;
374 /// use std::ptr::NonNull;
375 ///
376 /// let mut v = 0;
377 /// let ptr = NonNull::new(&mut v as *mut i32).unwrap();
378 /// let ptr = NonNullExt::from_nonnull(ptr);
379 /// ```
380 #[inline]
381 pub fn from_nonnull(ptr: NonNull<T>) -> Self {
382 Self {
383 inner: ptr,
384 #[cfg(feature = "check")]
385 ty_or_name: crate::util::Or::B(std::any::type_name::<T>()),
386 }
387 }
388
389 /// Creates a [`NonNullExt`] that is dangling, but well-aligned.
390 ///
391 /// In many Rust functions, they require aligned pointers even if they are
392 /// some trash values. This function will be usuful in that cases.
393 ///
394 /// # Examples
395 ///
396 /// ```
397 /// use my_ecs::ds::NonNullExt;
398 ///
399 /// let dangling = NonNullExt::<i32>::dangling();
400 /// ```
401 #[inline]
402 pub const fn dangling() -> Self
403 where
404 T: Sized,
405 {
406 Self {
407 inner: NonNull::dangling(),
408 #[cfg(feature = "check")]
409 ty_or_name: crate::util::Or::B(""), // type_name() is not const yet.
410 }
411 }
412
413 /// Returns true if the pointer is dangling.
414 ///
415 /// # Examples
416 ///
417 /// ```
418 /// use my_ecs::ds::NonNullExt;
419 ///
420 /// let dangling = NonNullExt::<i32>::dangling();
421 /// assert!(dangling.is_dangling());
422 /// ```
423 #[inline]
424 pub fn is_dangling(&self) -> bool
425 where
426 T: Sized,
427 {
428 self == &Self::dangling()
429 }
430
431 /// Sets the [`TypeIdExt`] to the pointer then returns the pointer.
432 ///
433 /// Basically, [`NonNullExt`] contains type name of the pointer if `check`
434 /// feature is enabled. You can replace it with the given `TypeIdExt`
435 /// using this method. But `check` feature is disabled, this method is
436 /// no-op.
437 ///
438 /// # Examples
439 ///
440 /// ```
441 /// use my_ecs::{prelude::*, ds::NonNullExt};
442 ///
443 /// let mut v = 0;
444 /// let ptr = NonNullExt::new(&mut v as *mut i32)
445 /// .unwrap()
446 /// .with_type(TypeIdExt::of::<i32>());
447 /// ```
448 #[inline]
449 pub fn with_type(self, _ty: TypeIdExt) -> Self {
450 #[cfg(not(feature = "check"))]
451 {
452 self
453 }
454
455 #[cfg(feature = "check")]
456 {
457 let mut this = self;
458 this.ty_or_name = crate::util::Or::A(_ty);
459 this
460 }
461 }
462
463 /// Returns [`TypeIdExt`] of the pointer if `check` feature is enabled and
464 /// the pointer contains `TypeIdExt` rather than type name.
465 ///
466 /// If you want to set the `TypeIdExt` to the pointer, call
467 /// [`NonNullExt::with_type`].
468 ///
469 /// # Examples
470 ///
471 /// ```
472 /// use my_ecs::{prelude::*, ds::NonNullExt};
473 ///
474 /// let mut v = 0;
475 /// let ptr = NonNullExt::new(&mut v as *mut i32)
476 /// .unwrap()
477 /// .with_type(TypeIdExt::of::<i32>());
478 /// ```
479 #[inline]
480 pub fn get_type(&self) -> Option<&TypeIdExt> {
481 #[cfg(not(feature = "check"))]
482 {
483 None
484 }
485
486 #[cfg(feature = "check")]
487 {
488 match &self.ty_or_name {
489 crate::util::Or::A(ty) => Some(ty),
490 crate::util::Or::B(_name) => None,
491 }
492 }
493 }
494
495 /// Returns type name of the pointer if `check` feature is enabled.
496 ///
497 /// # Examples
498 ///
499 /// ```
500 /// use my_ecs::ds::NonNullExt;
501 ///
502 /// let mut v = 0;
503 /// let ptr = NonNullExt::new(&mut v as *mut i32).unwrap();
504 /// let name = ptr.get_name();
505 /// ```
506 #[inline]
507 pub fn get_name(&self) -> Option<&'static str> {
508 #[cfg(not(feature = "check"))]
509 {
510 None
511 }
512
513 #[cfg(feature = "check")]
514 {
515 match &self.ty_or_name {
516 crate::util::Or::A(ty) => Some(ty.name()),
517 crate::util::Or::B(name) => Some(name),
518 }
519 }
520 }
521
522 /// Casts the pointer to another type.
523 ///
524 /// Note that this method resets [`TypeIdExt`] you set through
525 /// [`NonNullExt::with_type`].
526 ///
527 /// # Examples
528 ///
529 /// ```
530 /// use my_ecs::ds::NonNullExt;
531 ///
532 /// let mut v = 0x1234_5678;
533 /// let ptr = NonNullExt::new(&mut v as *mut i32).unwrap();
534 ///
535 /// let ptr = ptr.cast::<[u8; 4]>();
536 /// let ref_v = unsafe { ptr.as_ref() };
537 /// assert_eq!(*ref_v, i32::to_ne_bytes(v));
538 /// ```
539 #[inline]
540 pub fn cast<U>(self) -> NonNullExt<U> {
541 NonNullExt {
542 inner: self.inner.cast(),
543 #[cfg(feature = "check")]
544 ty_or_name: crate::util::Or::B(std::any::type_name::<U>()),
545 }
546 }
547
548 /// Adds an offset to the pointer then returns the result.
549 ///
550 /// Note that `count` is in units of `T`. For example, `count` = 3 means
551 /// 12 bytes offset if `T` is `i32`.
552 ///
553 /// # Safety
554 ///
555 /// See [`NonNull::add`].
556 ///
557 /// # Examples
558 ///
559 /// ```
560 /// use my_ecs::ds::NonNullExt;
561 ///
562 /// let arr: [char; 3] = ['a', 'b', 'c'];
563 /// let ptr = NonNullExt::new(arr.as_ptr().cast_mut()).unwrap();
564 ///
565 /// let ref_v = unsafe { ptr.add(1).as_ref() };
566 /// assert_eq!(ref_v, &'b');
567 ///
568 /// let ref_v = unsafe { ptr.add(2).as_ref() };
569 /// assert_eq!(ref_v, &'c');
570 /// ```
571 #[inline]
572 pub unsafe fn add(self, count: usize) -> Self
573 where
574 T: Sized,
575 {
576 let inner = unsafe { self.inner.add(count) };
577
578 Self {
579 inner,
580 #[cfg(feature = "check")]
581 ty_or_name: self.ty_or_name,
582 }
583 }
584
585 /// Subtracts an offset from the pointer then returns the result.
586 ///
587 /// Note that `count` is in units of `T`. For example, `count` = 3 means
588 /// 12 bytes offset if `T` is `i32`.
589 ///
590 /// # Safety
591 ///
592 /// See [`NonNull::sub`].
593 ///
594 /// # Examples
595 ///
596 /// ```
597 /// use my_ecs::ds::NonNullExt;
598 ///
599 /// let arr: [char; 3] = ['a', 'b', 'c'];
600 /// let ptr = NonNullExt::new((&arr[2] as *const char).cast_mut()).unwrap();
601 ///
602 /// let ref_v = unsafe { ptr.sub(1).as_ref() };
603 /// assert_eq!(ref_v, &'b');
604 ///
605 /// let ref_v = unsafe { ptr.sub(2).as_ref() };
606 /// assert_eq!(ref_v, &'a');
607 /// ```
608 #[inline]
609 pub unsafe fn sub(self, count: usize) -> Self
610 where
611 T: Sized,
612 {
613 let inner = unsafe { self.inner.sub(count) };
614
615 Self {
616 inner,
617 #[cfg(feature = "check")]
618 ty_or_name: self.ty_or_name,
619 }
620 }
621}
622
623impl<T: ?Sized> Deref for NonNullExt<T> {
624 type Target = NonNull<T>;
625
626 #[inline]
627 fn deref(&self) -> &Self::Target {
628 &self.inner
629 }
630}
631
632impl<T: ?Sized> DerefMut for NonNullExt<T> {
633 #[inline]
634 fn deref_mut(&mut self) -> &mut Self::Target {
635 &mut self.inner
636 }
637}
638
639impl<T: ?Sized> PartialEq for NonNullExt<T> {
640 #[allow(ambiguous_wide_pointer_comparisons)]
641 #[inline]
642 fn eq(&self, other: &Self) -> bool {
643 self.as_ptr() == other.as_ptr()
644 }
645}
646
647impl<T: ?Sized> Eq for NonNullExt<T> {}
648
649impl<T: ?Sized> PartialOrd for NonNullExt<T> {
650 #[inline]
651 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
652 Some(self.cmp(other))
653 }
654}
655
656impl<T: ?Sized> Ord for NonNullExt<T> {
657 #[allow(ambiguous_wide_pointer_comparisons)]
658 #[inline]
659 fn cmp(&self, other: &Self) -> cmp::Ordering {
660 self.as_ptr().cmp(&other.as_ptr())
661 }
662}
663
664impl<T: ?Sized> hash::Hash for NonNullExt<T> {
665 #[inline]
666 fn hash<H: hash::Hasher>(&self, state: &mut H) {
667 self.inner.hash(state)
668 }
669}
670
671impl<T: ?Sized> Clone for NonNullExt<T> {
672 #[inline]
673 fn clone(&self) -> Self {
674 *self
675 }
676}
677
678impl<T: ?Sized> Copy for NonNullExt<T> {}
679
680/// A wrapper of [`NonNullExt`] that can be used to manage a constant pointer.
681///
682/// When the `check` feature is enabled, the crate tracks whether
683/// [`ManagedMutPtr`] that has the same address is being created while the
684/// pointer is alive. This could be useful when you need extra debugging
685/// facility than `NonNullExt`.
686///
687/// # Safety
688///
689/// The pointer is used as a shared reference without unsafe function such as
690/// [`NonNull::as_ref`] because the pointer is completely managed. Therefore,
691/// You must make sure that the pointer will not violate any conditions of
692/// `Pointer to reference conversion` in [`std::ptr`] document.
693pub struct ManagedConstPtr<T: ?Sized> {
694 inner: NonNullExt<T>,
695 #[cfg(feature = "check")]
696 is_trace: bool,
697}
698
699impl<T: ?Sized> fmt::Debug for ManagedConstPtr<T> {
700 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
701 self.inner.fmt(f)
702 }
703}
704
705unsafe impl<T: ?Sized + Send> Send for ManagedConstPtr<T> {}
706
707impl<T: ?Sized> ManagedConstPtr<T> {
708 /// Creates a [`ManagedConstPtr`] from the given pointer.
709 ///
710 /// # Safety
711 ///
712 /// See [`ManagedConstPtr`] safety section.
713 ///
714 /// # Examples
715 ///
716 /// ```
717 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
718 ///
719 /// let mut v = 0;
720 /// let ptr = NonNullExt::new(&mut v as *mut i32).unwrap();
721 /// let ptr = unsafe { ManagedConstPtr::new(ptr) };
722 /// ```
723 #[inline]
724 pub unsafe fn new(ptr: NonNullExt<T>) -> Self {
725 // Tracks the address because `is_trace` is true.
726 #[cfg(feature = "check")]
727 {
728 debug::insert_const_ptr(ptr);
729 }
730
731 Self {
732 inner: ptr,
733 #[cfg(feature = "check")]
734 is_trace: true,
735 }
736 }
737
738 /// Creates a [`ManagedConstPtr`] that is dangling, but well-aligned.
739 ///
740 /// In many Rust functions, they require aligned pointers even if they are
741 /// some trash values. This function will be usuful in that cases.
742 ///
743 /// # Examples
744 ///
745 /// ```
746 /// use my_ecs::ds::ManagedConstPtr;
747 ///
748 /// let dangling = ManagedConstPtr::<i32>::dangling();
749 /// ```
750 #[inline]
751 pub const fn dangling() -> Self
752 where
753 T: Sized,
754 {
755 Self {
756 inner: NonNullExt::dangling(),
757 #[cfg(feature = "check")]
758 is_trace: false,
759 }
760 }
761
762 /// Returns true if the pointer is dangling.
763 ///
764 /// # Examples
765 ///
766 /// ```
767 /// use my_ecs::ds::ManagedConstPtr;
768 ///
769 /// let dangling = ManagedConstPtr::<i32>::dangling();
770 /// assert!(dangling.is_dangling());
771 /// ```
772 #[inline]
773 pub fn is_dangling(&self) -> bool
774 where
775 T: Sized,
776 {
777 self == &Self::dangling()
778 }
779
780 /// Creates a [`NonNullExt`] from this pointer.
781 ///
782 /// # Examples
783 ///
784 /// ```
785 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
786 ///
787 /// let mut v = 0;
788 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
789 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
790 /// assert_eq!(ptr.as_nonnullext(), nne);
791 /// ```
792 #[inline]
793 pub fn as_nonnullext(&self) -> NonNullExt<T> {
794 self.inner
795 }
796
797 /// Creates a [`NonNull`] from this pointer.
798 ///
799 /// # Examples
800 ///
801 /// ```
802 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
803 ///
804 /// let mut v = 0;
805 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
806 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
807 /// assert_eq!(ptr.as_nonnull(), *nne);
808 /// ```
809 #[inline]
810 pub fn as_nonnull(&self) -> NonNull<T> {
811 self.inner.inner
812 }
813
814 /// Creates a raw poitner from this pointer.
815 ///
816 /// # Examples
817 ///
818 /// ```
819 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
820 ///
821 /// let mut v = 0;
822 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
823 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
824 /// assert_eq!(ptr.as_ptr(), nne.as_ptr());
825 /// ```
826 #[inline]
827 pub fn as_ptr(&self) -> *const T {
828 self.inner.as_ptr().cast_const()
829 }
830
831 /// Converts the pointer into a shared reference.
832 ///
833 /// Note that trace of the address by `check` feature ends by consuming the
834 /// pointer.
835 ///
836 /// # Examples
837 ///
838 /// ```
839 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
840 ///
841 /// let mut v = 0;
842 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
843 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
844 /// assert_eq!(ptr.into_ref(), &0);
845 /// ```
846 #[inline]
847 pub fn into_ref<'a>(self) -> &'a T {
848 let inner = self.as_nonnullext();
849
850 #[cfg(feature = "check")]
851 drop(self);
852
853 // Safety: Managed pointer.
854 unsafe { inner.as_ref() }
855 }
856
857 /// Casts the pointer to another type.
858 ///
859 /// This method doesn't break the trace of the address by `check` feature.
860 /// But internal type information is reset. See [`NonNullExt::cast`].
861 ///
862 /// # Examples
863 ///
864 /// ```
865 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
866 ///
867 /// let mut v = 0x1234_5678;
868 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
869 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
870 ///
871 /// let ptr = ptr.cast::<[u8; 4]>();
872 /// let ref_v = ptr.into_ref();
873 /// assert_eq!(*ref_v, i32::to_ne_bytes(v));
874 /// ```
875 #[inline]
876 pub fn cast<U>(self) -> ManagedConstPtr<U> {
877 let inner = self.as_nonnullext();
878
879 #[cfg(feature = "check")]
880 drop(self);
881
882 // Safety: Nothing has changed except `T` -> `U`.
883 unsafe { ManagedConstPtr::new(inner.cast()) }
884 }
885
886 /// Adds an offset to the pointer then returns the result.
887 ///
888 /// Note that `count` is in units of `T`. For example, `count` = 3 means
889 /// 12 bytes offset if `T` is `i32`.
890 ///
891 /// # Safety
892 ///
893 /// See [`NonNull::add`].
894 ///
895 /// # Examples
896 ///
897 /// ```
898 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
899 ///
900 /// let arr: [char; 3] = ['a', 'b', 'c'];
901 /// let nne = NonNullExt::new(arr.as_ptr().cast_mut()).unwrap();
902 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
903 ///
904 /// unsafe {
905 /// assert_eq!(*ptr.add(1), 'b');
906 /// assert_eq!(*ptr.add(2), 'c');
907 /// }
908 /// ```
909 #[inline]
910 pub unsafe fn add(self, count: usize) -> Self
911 where
912 T: Sized,
913 {
914 Self {
915 inner: unsafe { self.inner.add(count) },
916 #[cfg(feature = "check")]
917 is_trace: self.is_trace,
918 }
919 }
920
921 /// Subtracts an offset from the pointer then returns the result.
922 ///
923 /// Note that `count` is in units of `T`. For example, `count` = 3 means
924 /// 12 bytes offset if `T` is `i32`.
925 ///
926 /// # Safety
927 ///
928 /// See [`NonNull::sub`].
929 ///
930 /// # Examples
931 ///
932 /// ```
933 /// use my_ecs::ds::{NonNullExt, ManagedConstPtr};
934 ///
935 /// let arr: [char; 3] = ['a', 'b', 'c'];
936 /// let nne = NonNullExt::new((&arr[2] as *const char).cast_mut()).unwrap();
937 /// let ptr = unsafe { ManagedConstPtr::new(nne) };
938 ///
939 /// unsafe {
940 /// assert_eq!(*ptr.sub(1), 'b');
941 /// assert_eq!(*ptr.sub(2), 'a');
942 /// }
943 /// ```
944 #[inline]
945 pub unsafe fn sub(self, count: usize) -> Self
946 where
947 T: Sized,
948 {
949 Self {
950 inner: unsafe { self.inner.sub(count) },
951 #[cfg(feature = "check")]
952 is_trace: self.is_trace,
953 }
954 }
955}
956
957#[cfg(feature = "check")]
958impl<T: ?Sized> Drop for ManagedConstPtr<T> {
959 fn drop(&mut self) {
960 if self.is_trace {
961 debug::remove_ptr(*self.inner);
962 }
963 }
964}
965
966impl<T: ?Sized> Deref for ManagedConstPtr<T> {
967 type Target = T;
968
969 #[inline]
970 fn deref(&self) -> &Self::Target {
971 // Safety: We assume that the pointer is valid by the constructor.
972 unsafe { self.inner.as_ref() }
973 }
974}
975
976impl<T: ?Sized> PartialEq for ManagedConstPtr<T> {
977 #[allow(ambiguous_wide_pointer_comparisons)]
978 #[inline]
979 fn eq(&self, other: &Self) -> bool {
980 self.as_ptr() == other.as_ptr()
981 }
982}
983
984impl<T: ?Sized> Eq for ManagedConstPtr<T> {}
985
986impl<T: ?Sized> PartialOrd for ManagedConstPtr<T> {
987 #[inline]
988 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
989 Some(self.cmp(other))
990 }
991}
992
993impl<T: ?Sized> Ord for ManagedConstPtr<T> {
994 #[allow(ambiguous_wide_pointer_comparisons)]
995 #[inline]
996 fn cmp(&self, other: &Self) -> cmp::Ordering {
997 self.as_ptr().cmp(&other.as_ptr())
998 }
999}
1000
1001impl<T: ?Sized> hash::Hash for ManagedConstPtr<T> {
1002 #[inline]
1003 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1004 self.inner.hash(state)
1005 }
1006}
1007
1008impl<T: ?Sized> Clone for ManagedConstPtr<T> {
1009 #[inline]
1010 fn clone(&self) -> Self {
1011 #[cfg(feature = "check")]
1012 {
1013 Self {
1014 inner: self.inner,
1015 is_trace: self.is_trace,
1016 }
1017 }
1018
1019 #[cfg(not(feature = "check"))]
1020 *self
1021 }
1022}
1023
1024// It's pointer. We can copy it regardless of T.
1025#[cfg(not(feature = "check"))]
1026impl<T: ?Sized> Copy for ManagedConstPtr<T> {}
1027
1028/// A wrapper of [`NonNullExt`] that can be used to manage a mutable pointer.
1029///
1030/// When the `check` feature is enabled, the crate tracks whether
1031/// [`ManagedMutPtr`] or [`ManagedConstPtr`] that has the same address is being
1032/// created while the pointer is alive. This could be useful when you need extra
1033/// debugging facility than `NonNullExt`.
1034///
1035/// # Safety
1036///
1037/// The pointer is used as a mutable reference without unsafe function such as
1038/// [`NonNull::as_mut`] because the pointer is completely managed. Therefore,
1039/// You must make sure that the pointer will not violate any conditions of
1040/// `Pointer to reference conversion` in [`std::ptr`] document.
1041pub struct ManagedMutPtr<T: ?Sized> {
1042 inner: NonNullExt<T>,
1043 #[cfg(feature = "check")]
1044 is_trace: bool,
1045}
1046
1047impl<T: ?Sized> fmt::Debug for ManagedMutPtr<T> {
1048 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1049 self.inner.fmt(f)
1050 }
1051}
1052
1053unsafe impl<T: ?Sized + Send> Send for ManagedMutPtr<T> {}
1054
1055impl<T: ?Sized> ManagedMutPtr<T> {
1056 /// Creates a [`ManagedMutPtr`] from the given pointer.
1057 ///
1058 /// # Safety
1059 ///
1060 /// See [`ManagedMutPtr`] safety section.
1061 ///
1062 /// # Examples
1063 ///
1064 /// ```
1065 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1066 ///
1067 /// let mut v = 0;
1068 /// let ptr = NonNullExt::new(&mut v as *mut i32).unwrap();
1069 /// let ptr = unsafe { ManagedMutPtr::new(ptr) };
1070 /// ```
1071 #[inline]
1072 pub unsafe fn new(ptr: NonNullExt<T>) -> Self {
1073 // Tracks the address because `is_trace` is true.
1074 #[cfg(feature = "check")]
1075 {
1076 debug::insert_mut_ptr(ptr);
1077 }
1078
1079 Self {
1080 inner: ptr,
1081 #[cfg(feature = "check")]
1082 is_trace: true,
1083 }
1084 }
1085
1086 /// Creates a [`ManagedMutPtr`] that is dangling, but well-aligned.
1087 ///
1088 /// In many Rust functions, they require aligned pointers even if they are
1089 /// some trash values. This function will be usuful in that cases.
1090 ///
1091 /// # Examples
1092 ///
1093 /// ```
1094 /// use my_ecs::ds::ManagedMutPtr;
1095 ///
1096 /// let dangling = ManagedMutPtr::<i32>::dangling();
1097 /// ```
1098 #[inline]
1099 pub const fn dangling() -> Self
1100 where
1101 T: Sized,
1102 {
1103 Self {
1104 inner: NonNullExt::dangling(),
1105 #[cfg(feature = "check")]
1106 is_trace: false,
1107 }
1108 }
1109
1110 /// Returns true if the pointer is dangling.
1111 ///
1112 /// # Examples
1113 ///
1114 /// ```
1115 /// use my_ecs::ds::ManagedMutPtr;
1116 ///
1117 /// let dangling = ManagedMutPtr::<i32>::dangling();
1118 /// assert!(dangling.is_dangling());
1119 /// ```
1120 #[inline]
1121 pub fn is_dangling(&self) -> bool
1122 where
1123 T: Sized,
1124 {
1125 self == &Self::dangling()
1126 }
1127
1128 /// Creates a [`NonNullExt`] from this pointer.
1129 ///
1130 /// # Examples
1131 ///
1132 /// ```
1133 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1134 ///
1135 /// let mut v = 0;
1136 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1137 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1138 /// assert_eq!(ptr.as_nonnullext(), nne);
1139 /// ```
1140 #[inline]
1141 pub fn as_nonnullext(&self) -> NonNullExt<T> {
1142 self.inner
1143 }
1144
1145 /// Creates a [`NonNull`] from this pointer.
1146 ///
1147 /// # Examples
1148 ///
1149 /// ```
1150 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1151 ///
1152 /// let mut v = 0;
1153 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1154 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1155 /// assert_eq!(ptr.as_nonnull(), *nne);
1156 /// ```
1157 #[inline]
1158 pub fn as_nonnull(&self) -> NonNull<T> {
1159 self.inner.inner
1160 }
1161
1162 /// Creates a raw poitner from this pointer.
1163 ///
1164 /// # Examples
1165 ///
1166 /// ```
1167 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1168 ///
1169 /// let mut v = 0;
1170 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1171 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1172 /// assert_eq!(ptr.as_ptr(), nne.as_ptr());
1173 /// ```
1174 #[inline]
1175 pub fn as_ptr(&self) -> *mut T {
1176 self.inner.as_ptr()
1177 }
1178
1179 /// Converts the pointer into a mutable reference.
1180 ///
1181 /// Note that trace of the address by `check` feature ends by consuming the
1182 /// pointer.
1183 ///
1184 /// # Examples
1185 ///
1186 /// ```
1187 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1188 ///
1189 /// let mut v = 0;
1190 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1191 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1192 /// assert_eq!(ptr.into_mut(), &0);
1193 /// ```
1194 #[inline]
1195 pub fn into_mut<'a>(self) -> &'a mut T {
1196 let mut inner = self.as_nonnullext();
1197
1198 #[cfg(feature = "check")]
1199 drop(self);
1200
1201 // Safety: Managed pointer.
1202 unsafe { inner.as_mut() }
1203 }
1204
1205 /// Casts the pointer to another type.
1206 ///
1207 /// This method doesn't break the trace of the address by `check` feature.
1208 /// But internal type information is reset. See [`NonNullExt::cast`].
1209 ///
1210 /// # Examples
1211 ///
1212 /// ```
1213 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1214 ///
1215 /// let mut v = 0x1234_5678;
1216 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1217 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1218 ///
1219 /// let ptr = ptr.cast::<[u8; 4]>();
1220 /// let ref_v = ptr.into_mut();
1221 /// assert_eq!(*ref_v, i32::to_ne_bytes(v));
1222 /// ```
1223 #[inline]
1224 pub fn cast<U>(self) -> ManagedMutPtr<U> {
1225 let inner = self.as_nonnullext();
1226
1227 #[cfg(feature = "check")]
1228 drop(self);
1229
1230 // Safety: Nothing has changed except `T` -> `U`.
1231 unsafe { ManagedMutPtr::new(inner.cast()) }
1232 }
1233
1234 /// Changes constness without changing the type.
1235 ///
1236 /// # Examples
1237 ///
1238 /// ```
1239 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1240 ///
1241 /// let mut v = 0;
1242 /// let nne = NonNullExt::new(&mut v as *mut i32).unwrap();
1243 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1244 /// let ptr = ptr.cast_const();
1245 /// ```
1246 #[inline]
1247 pub fn cast_const(self) -> ManagedConstPtr<T> {
1248 let inner = self.as_nonnullext();
1249
1250 #[cfg(feature = "check")]
1251 drop(self);
1252
1253 // Safety: Nothing has changed except `Mut` -> `Const`.
1254 unsafe { ManagedConstPtr::new(inner) }
1255 }
1256
1257 /// Adds an offset to the pointer then returns the result.
1258 ///
1259 /// Note that `count` is in units of `T`. For example, `count` = 3 means
1260 /// 12 bytes offset if `T` is `i32`.
1261 ///
1262 /// # Safety
1263 ///
1264 /// See [`NonNull::add`].
1265 ///
1266 /// # Examples
1267 ///
1268 /// ```
1269 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1270 ///
1271 /// let arr: [char; 2] = ['a', 'b'];
1272 /// let nne = NonNullExt::new(arr.as_ptr().cast_mut()).unwrap();
1273 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1274 /// unsafe { assert_eq!(*ptr.add(1), 'b') };
1275 /// ```
1276 #[inline]
1277 pub unsafe fn add(self, count: usize) -> Self
1278 where
1279 T: Sized,
1280 {
1281 Self {
1282 inner: unsafe { self.inner.add(count) },
1283 #[cfg(feature = "check")]
1284 is_trace: self.is_trace,
1285 }
1286 }
1287
1288 /// Subtracts an offset from the pointer then returns the result.
1289 ///
1290 /// Note that `count` is in units of `T`. For example, `count` = 3 means
1291 /// 12 bytes offset if `T` is `i32`.
1292 ///
1293 /// # Safety
1294 ///
1295 /// See [`NonNull::sub`].
1296 ///
1297 /// # Examples
1298 ///
1299 /// ```
1300 /// use my_ecs::ds::{NonNullExt, ManagedMutPtr};
1301 ///
1302 /// let arr: [char; 2] = ['a', 'b'];
1303 /// let nne = NonNullExt::new((&arr[1] as *const char).cast_mut()).unwrap();
1304 /// let ptr = unsafe { ManagedMutPtr::new(nne) };
1305 ///
1306 /// unsafe { assert_eq!(*ptr.sub(1), 'a') };
1307 /// ```
1308 #[inline]
1309 pub unsafe fn sub(self, count: usize) -> Self
1310 where
1311 T: Sized,
1312 {
1313 Self {
1314 inner: unsafe { self.inner.sub(count) },
1315 #[cfg(feature = "check")]
1316 is_trace: self.is_trace,
1317 }
1318 }
1319}
1320
1321#[cfg(feature = "check")]
1322impl<T: ?Sized> Drop for ManagedMutPtr<T> {
1323 fn drop(&mut self) {
1324 if self.is_trace {
1325 debug::remove_ptr(*self.inner);
1326 }
1327 }
1328}
1329
1330impl<T: ?Sized> Deref for ManagedMutPtr<T> {
1331 type Target = T;
1332
1333 #[inline]
1334 fn deref(&self) -> &Self::Target {
1335 // Safety: We assume that the pointer is valid by the constructor.
1336 unsafe { self.inner.as_ref() }
1337 }
1338}
1339
1340impl<T: ?Sized> DerefMut for ManagedMutPtr<T> {
1341 #[inline]
1342 fn deref_mut(&mut self) -> &mut Self::Target {
1343 // Safety: We assume that the pointer is valid by the constructor.
1344 unsafe { self.inner.as_mut() }
1345 }
1346}
1347
1348impl<T: ?Sized> PartialEq for ManagedMutPtr<T> {
1349 #[allow(ambiguous_wide_pointer_comparisons)]
1350 #[inline]
1351 fn eq(&self, other: &Self) -> bool {
1352 self.as_ptr() == other.as_ptr()
1353 }
1354}
1355
1356impl<T: ?Sized> Eq for ManagedMutPtr<T> {}
1357
1358impl<T: ?Sized> PartialOrd for ManagedMutPtr<T> {
1359 #[inline]
1360 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1361 Some(self.cmp(other))
1362 }
1363}
1364
1365impl<T: ?Sized> Ord for ManagedMutPtr<T> {
1366 #[allow(ambiguous_wide_pointer_comparisons)]
1367 #[inline]
1368 fn cmp(&self, other: &Self) -> cmp::Ordering {
1369 self.as_ptr().cmp(&other.as_ptr())
1370 }
1371}
1372
1373impl<T: ?Sized> hash::Hash for ManagedMutPtr<T> {
1374 #[inline]
1375 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1376 self.inner.hash(state)
1377 }
1378}
1379
1380// ManagedMutPtr is not a pure pointer unlike NonNull.
1381// It can be dereferenced as shared or mutable reference without need for unsafe block.
1382// That means it's more like a mutable reference.
1383// So, we don't implement Clone and Copy for it.
1384// impl<T: ?Sized> Clone for ManagedMutPtr<T> {..}
1385// impl<T: ?Sized> Copy for ManagedMutPtr<T> {..}
1386
1387#[cfg(feature = "check")]
1388mod debug {
1389 use super::*;
1390 use dashmap::DashMap;
1391 use std::{mem, sync::LazyLock};
1392
1393 enum RefCount {
1394 Shared(u16),
1395 Exclusive,
1396 }
1397
1398 static RC_MAP: LazyLock<DashMap<[usize; 2], RefCount>> = LazyLock::new(DashMap::new);
1399
1400 const MAX_RC: u16 = 256;
1401
1402 fn create_key<T: ?Sized>(ptr: NonNull<T>) -> [usize; 2] {
1403 const PTR_SIZE: usize = size_of::<*const ()>();
1404 // TODO: Wide pointer size may change in the future.
1405 // See https://doc.rust-lang.org/reference/type-layout.html#pointers-and-references-layout
1406 const WIDE_PTR_SIZE: usize = PTR_SIZE * 2;
1407
1408 const _: () = {
1409 assert!(PTR_SIZE == size_of::<usize>());
1410 assert!(WIDE_PTR_SIZE == size_of::<[usize; 2]>());
1411 };
1412
1413 match size_of_val(&ptr) {
1414 PTR_SIZE => [0, ptr.as_ptr() as *mut () as usize],
1415 WIDE_PTR_SIZE => {
1416 // Safety: We checked the size.
1417 unsafe { mem::transmute_copy(&ptr) }
1418 }
1419 _ => unimplemented!(),
1420 }
1421 }
1422
1423 /// Inserts the pointer to the global map.
1424 /// In the map, shared pointer is allowed to be inserted multiple times.
1425 ///
1426 /// # Panics
1427 ///
1428 /// - Panics if insertion count is greater than the limit (256).
1429 /// - Panics if the map contained the pointer as exclusive pointer.
1430 pub(super) fn insert_const_ptr<T: ?Sized>(ptr: NonNullExt<T>) {
1431 let key = create_key(*ptr);
1432 RC_MAP
1433 .entry(key)
1434 .and_modify(|rc| match rc {
1435 RefCount::Shared(cnt) => {
1436 *cnt += 1;
1437 assert!(*cnt <= MAX_RC, "too many ManagedConstPtr");
1438 }
1439 RefCount::Exclusive => {
1440 panic!("`{ptr:?}` cannot become managed shared pointer because it's already managed as a mutable pointer");
1441 }
1442 })
1443 .or_insert(RefCount::Shared(1));
1444 }
1445
1446 /// Inserts the pointer to the global map.
1447 /// In the map, exclusive pointer is not allowed to be inserted multiple times.
1448 /// To insert the same pointer, you must remove the pointer first.
1449 ///
1450 /// Note, however, that zero-sized `T` is considered shared pointer.
1451 /// It means the pointer is allowed to be inserted many times.
1452 ///
1453 /// # Panics
1454 ///
1455 /// Panics if the map contained the pointer.
1456 pub(super) fn insert_mut_ptr<T: ?Sized>(ptr: NonNullExt<T>) {
1457 // If `T` is a zero-sized type, then it's good to be allowed to have
1458 // the same pointers because they do not mutate the same data.
1459 // It can be considered as a const pointer.
1460 //
1461 // Safety: Even if it's aliased, we do not read the data here.
1462 if unsafe { size_of_val(ptr.as_ref()) } == 0 {
1463 insert_const_ptr(ptr);
1464 return;
1465 }
1466
1467 let key = create_key(*ptr);
1468 RC_MAP
1469 .entry(key)
1470 .and_modify(|rc| match rc {
1471 RefCount::Shared(_) => {
1472 panic!("`{ptr:?}` cannot become managed mutable pointer because it's already managed as a shared pointer: {:#0x}", ptr.as_ptr() as *mut u8 as usize);
1473 }
1474 RefCount::Exclusive => {
1475 panic!("`{ptr:?}` cannot become managed mutable pointer because it's already managed as a mutable pointer: {:#0x}", ptr.as_ptr() as *mut u8 as usize);
1476 }
1477 })
1478 .or_insert(RefCount::Exclusive);
1479 }
1480
1481 pub(super) fn remove_ptr<T: ?Sized>(ptr: NonNull<T>) {
1482 let key = create_key(ptr);
1483 assert!(
1484 RC_MAP.contains_key(&key),
1485 "cannot find pointer in the RC_MAP"
1486 );
1487 RC_MAP.remove_if_mut(&key, |_, rc| match rc {
1488 RefCount::Shared(cnt) => {
1489 *cnt -= 1;
1490 *cnt == 0
1491 }
1492 RefCount::Exclusive => true,
1493 });
1494 }
1495}