1use core::fmt::Debug;
2
3use crate::{num::Integer, primitive::Primitive, reference::Mutability, util::cast_int};
4
5macro_rules! cast_ptr {
6 ($T:ty, $P:ty, $value:expr) => {
7 match <$P>::ptr_type() {
8 $crate::reference::Mutability::Const => unsafe {
9 $crate::util::transmute_unchecked::<*const $T, $P>($value as *const $T)
10 },
11 $crate::reference::Mutability::Mut => unsafe {
12 $crate::util::transmute_unchecked::<*mut $T, $P>($value as *mut $T)
13 },
14 }
15 };
16}
17
18pub(crate) use cast_ptr;
19
20pub trait Pointer<T: ?Sized>: Primitive + Copy + Debug + Sized {
21 fn ptr_type() -> Mutability;
22
23 fn cast_ptr<U: Sized, P: Pointer<U>>(self) -> P
24 where
25 Self: Sized;
26
27 fn cast_int<I: Integer>(self) -> I
28 where
29 T: Sized;
30}
31
32macro_rules! impl_pointer {
33 ($mut:tt, $ty:expr) => {
34 impl<T: ?Sized> Primitive for *$mut T {}
35
36 impl<T: ?Sized> Pointer<T> for *$mut T {
37 fn ptr_type() -> Mutability {
38 $ty
39 }
40
41 fn cast_ptr<U: Sized, P: Pointer<U>>(self) -> P where Self: Sized {
42 cast_ptr!(T, P, self)
43 }
44
45 fn cast_int<I: Integer>(self) -> I where T: Sized {
46 cast_int!(self => I)
47 }
48 }
49 }
50}
51
52impl_pointer!(const, Mutability::Const);
53impl_pointer!(mut, Mutability::Mut);
54
55#[cfg(test)]
56mod test {
57 use super::*;
58
59 #[test]
60 fn test_cast() {
61 let ptr: *const u8 = "foo".as_ptr();
62 let int: usize = ptr.cast_int();
63 let ptr2: *const u8 = int.cast_ptr();
64
65 assert_eq!(ptr, ptr2);
66 }
67}