bitvec/ptr/
addr.rs
1#![doc = include_str!("../../doc/ptr/addr.md")]
2
3use core::{
4 any,
5 fmt::{
6 self,
7 Debug,
8 Display,
9 Formatter,
10 Pointer,
11 },
12 mem,
13 ptr::NonNull,
14};
15
16use tap::{
17 Pipe,
18 TryConv,
19};
20use wyz::{
21 comu::{
22 Address,
23 Const,
24 Mut,
25 Mutability,
26 },
27 fmt::FmtForward,
28};
29
30#[inline]
32pub fn check_alignment<M, T>(
33 addr: Address<M, T>,
34) -> Result<Address<M, T>, MisalignError<T>>
35where M: Mutability {
36 let ptr = addr.to_const();
37 let mask = mem::align_of::<T>() - 1;
38 if ptr as usize & mask != 0 {
39 Err(MisalignError { ptr })
40 }
41 else {
42 Ok(addr)
43 }
44}
45
46pub(crate) trait AddressExt {
48 type Permission: Mutability;
50 type Referent: Sized;
52
53 unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent>;
65}
66
67#[cfg(not(tarpaulin_include))]
68impl<T> AddressExt for *const T {
69 type Permission = Const;
70 type Referent = T;
71
72 unsafe fn into_address(self) -> Address<Const, T> {
73 if cfg!(debug_assertions) {
74 self.try_conv::<Address<_, _>>()
75 .unwrap_or_else(|err| panic!("{}", err))
76 .pipe(check_alignment)
77 .unwrap_or_else(|err| panic!("{}", err))
78 }
79 else {
80 Address::new(NonNull::new_unchecked(self as *mut T))
81 }
82 }
83}
84
85#[cfg(not(tarpaulin_include))]
86impl<T> AddressExt for *mut T {
87 type Permission = Mut;
88 type Referent = T;
89
90 unsafe fn into_address(self) -> Address<Mut, T> {
91 if cfg!(debug_assertions) {
92 self.try_conv::<Address<_, _>>()
93 .unwrap_or_else(|err| panic!("{}", err))
94 .pipe(check_alignment)
95 .unwrap_or_else(|err| panic!("{}", err))
96 }
97 else {
98 Address::new(NonNull::new_unchecked(self))
99 }
100 }
101}
102
103#[cfg(not(tarpaulin_include))]
104impl<T> AddressExt for &T {
105 type Permission = Const;
106 type Referent = T;
107
108 unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent> {
109 self.into()
110 }
111}
112
113#[cfg(not(tarpaulin_include))]
114impl<T> AddressExt for &mut T {
115 type Permission = Mut;
116 type Referent = T;
117
118 unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent> {
119 self.into()
120 }
121}
122
123#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
126pub struct MisalignError<T> {
127 ptr: *const T,
129}
130
131impl<T> MisalignError<T> {
132 const ALIGN: usize = mem::align_of::<T>();
134 const CTTZ: usize = Self::ALIGN.trailing_zeros() as usize;
137}
138
139#[cfg(not(tarpaulin_include))]
140impl<T> Debug for MisalignError<T> {
141 #[inline]
142 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
143 fmt.debug_tuple("MisalignError")
144 .field(&self.ptr.fmt_pointer())
145 .field(&Self::ALIGN)
146 .finish()
147 }
148}
149
150#[cfg(not(tarpaulin_include))]
151impl<T> Display for MisalignError<T> {
152 #[inline]
153 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
154 write!(
155 fmt,
156 "Type {} requires {}-byte alignment: address ",
157 any::type_name::<T>(),
158 Self::ALIGN,
159 )?;
160 Pointer::fmt(&self.ptr, fmt)?;
161 write!(fmt, " must clear its least {} bits", Self::CTTZ)
162 }
163}
164
165unsafe impl<T> Send for MisalignError<T> {}
166
167unsafe impl<T> Sync for MisalignError<T> {}
168
169#[cfg(feature = "std")]
170impl<T> std::error::Error for MisalignError<T> {}