1use std::{cmp, fmt, hash, mem, str};
6use std::marker::PhantomData;
7
8use crate::Pod;
9
10use super::image::{Va, SignedVa};
11
12#[repr(transparent)]
14pub struct Ptr<T: ?Sized = ()> {
15 va: Va,
16 marker: PhantomData<fn() -> T>
17}
18
19impl<T: ?Sized> Ptr<T> {
20 const MARKER: PhantomData<fn() -> T> = PhantomData;
22 pub const NULL: Ptr<T> = Ptr { va: 0, marker: PhantomData };
24 pub const fn null() -> Ptr<T> {
26 Ptr::NULL
27 }
28 pub const fn is_null(self) -> bool {
30 self.va == 0
31 }
32 pub const fn member(va: Va, offset: u32) -> Ptr<T> {
34 let va = va + offset as Va;
35 Ptr { va, marker: Self::MARKER }
36 }
37 pub const fn cast<U: ?Sized>(self) -> Ptr<U> {
39 Ptr { va: self.va, marker: Ptr::<U>::MARKER }
40 }
41 pub const fn offset<U: ?Sized>(self, offset: SignedVa) -> Ptr<U> {
62 let va = self.va.wrapping_add(offset as Va);
63 Ptr { va, marker: Ptr::<U>::MARKER }
64 }
65 pub const fn into_raw(self) -> Va {
67 self.va
68 }
69 fn fmt(self) -> [u8; mem::size_of::<Va>() * 2 + 2] {
71 let mut s = [0; mem::size_of::<Va>() * 2 + 2];
72 s[0] = b'0';
73 s[1] = b'x';
74 let mut va = self.va;
75 for i in 0..mem::size_of::<Va>() * 2 {
76 va = va.rotate_left(4);
77 let digit = (va & 0xf) as u8;
78 let chr = if digit < 10 { b'0' + digit } else { b'a' + (digit - 10) };
79 s[i + 2] = chr;
80 }
81 return s;
82 }
83}
84impl<T> Ptr<[T]> {
85 pub const fn decay(self) -> Ptr<T> {
87 Ptr { va: self.va, marker: Ptr::<T>::MARKER }
88 }
89 pub const fn at(self, i: usize) -> Ptr<T> {
91 let va = self.va + (i * mem::size_of::<T>()) as Va;
92 Ptr { va, marker: Ptr::<T>::MARKER }
93 }
94}
95
96unsafe impl<T: ?Sized> Pod for Ptr<T> where Ptr<T>: 'static {}
97
98impl<T: ?Sized> Copy for Ptr<T> {}
99impl<T: ?Sized> Clone for Ptr<T> {
100 fn clone(&self) -> Ptr<T> {
101 *self
102 }
103}
104impl<T: ?Sized> Default for Ptr<T> {
105 fn default() -> Ptr<T> {
106 Ptr::NULL
107 }
108}
109impl<T: ?Sized> Eq for Ptr<T> {}
110impl<T: ?Sized> PartialEq for Ptr<T> {
111 fn eq(&self, rhs: &Ptr<T>) -> bool {
112 self.va == rhs.va
113 }
114}
115impl<T: ?Sized> PartialOrd for Ptr<T> {
116 fn partial_cmp(&self, rhs: &Ptr<T>) -> Option<cmp::Ordering> {
117 self.va.partial_cmp(&rhs.va)
118 }
119}
120impl<T: ?Sized> Ord for Ptr<T> {
121 fn cmp(&self, rhs: &Ptr<T>) -> cmp::Ordering {
122 self.va.cmp(&rhs.va)
123 }
124}
125impl<T: ?Sized> hash::Hash for Ptr<T> {
126 fn hash<H: hash::Hasher>(&self, state: &mut H) {
127 self.va.hash(state)
128 }
129}
130impl<T: ?Sized> From<Va> for Ptr<T> {
131 fn from(va: Va) -> Ptr<T> {
132 Ptr { va, marker: PhantomData }
133 }
134}
135impl<T: ?Sized> From<Ptr<T>> for Va {
136 fn from(ptr: Ptr<T>) -> Va {
137 ptr.va
138 }
139}
140impl<T: ?Sized> AsRef<Va> for Ptr<T> {
141 fn as_ref(&self) -> &Va {
142 &self.va
143 }
144}
145impl<T: ?Sized> AsMut<Va> for Ptr<T> {
146 fn as_mut(&mut self) -> &mut Va {
147 &mut self.va
148 }
149}
150impl<T: ?Sized> fmt::Debug for Ptr<T> {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 let buf = Ptr::fmt(*self);
153 f.write_str(unsafe { str::from_utf8_unchecked(&buf) })
154 }
155}
156impl<T: ?Sized> fmt::UpperHex for Ptr<T> {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 self.va.fmt(f)
159 }
160}
161impl<T: ?Sized> fmt::LowerHex for Ptr<T> {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 self.va.fmt(f)
164 }
165}
166impl<T: ?Sized> fmt::Display for Ptr<T> {
167 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168 let buf = Ptr::fmt(*self);
169 f.write_str(unsafe { str::from_utf8_unchecked(&buf) })
170 }
171}
172
173#[cfg(feature = "serde")]
174impl<T: ?Sized> serde::Serialize for Ptr<T> {
175 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
176 branch! {
177 pe32 { serializer.serialize_u32(self.va) }
178 pe64 { serializer.serialize_u64(self.va) }
179 }
180 }
181}