/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bitvec-1.0.1/src/ptr/addr.rs
Line | Count | Source |
1 | | #![doc = include_str!("../../doc/ptr/addr.md")] |
2 | | |
3 | | use core::{ |
4 | | any, |
5 | | fmt::{ |
6 | | self, |
7 | | Debug, |
8 | | Display, |
9 | | Formatter, |
10 | | Pointer, |
11 | | }, |
12 | | mem, |
13 | | ptr::NonNull, |
14 | | }; |
15 | | |
16 | | use tap::{ |
17 | | Pipe, |
18 | | TryConv, |
19 | | }; |
20 | | use wyz::{ |
21 | | comu::{ |
22 | | Address, |
23 | | Const, |
24 | | Mut, |
25 | | Mutability, |
26 | | }, |
27 | | fmt::FmtForward, |
28 | | }; |
29 | | |
30 | | /// Ensures that an address is well-aligned to its referent type width. |
31 | | #[inline] |
32 | 0 | pub fn check_alignment<M, T>( |
33 | 0 | addr: Address<M, T>, |
34 | 0 | ) -> Result<Address<M, T>, MisalignError<T>> |
35 | 0 | where M: Mutability { |
36 | 0 | let ptr = addr.to_const(); |
37 | 0 | let mask = mem::align_of::<T>() - 1; |
38 | 0 | if ptr as usize & mask != 0 { |
39 | 0 | Err(MisalignError { ptr }) |
40 | | } |
41 | | else { |
42 | 0 | Ok(addr) |
43 | | } |
44 | 0 | } |
45 | | |
46 | | /// Extension methods for raw pointers. |
47 | | pub(crate) trait AddressExt { |
48 | | /// Tracks the original mutation capability of the source pointer. |
49 | | type Permission: Mutability; |
50 | | /// The type to which the pointer points. |
51 | | type Referent: Sized; |
52 | | |
53 | | /// Forcibly wraps a raw pointer as an `Address`, without handling errors. |
54 | | /// |
55 | | /// In debug builds, this panics on null or misaligned pointers. In release |
56 | | /// builds, it is permitted to remove the error-handling codepaths and |
57 | | /// assume these invariants are upheld by the caller. |
58 | | /// |
59 | | /// ## Safety |
60 | | /// |
61 | | /// The caller must ensure that this is only called on non-null, |
62 | | /// well-aligned pointers. Pointers derived from Rust references or calls to |
63 | | /// the Rust allocator API will always satisfy this. |
64 | | unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent>; |
65 | | } |
66 | | |
67 | | #[cfg(not(tarpaulin_include))] |
68 | | impl<T> AddressExt for *const T { |
69 | | type Permission = Const; |
70 | | type Referent = T; |
71 | | |
72 | 123k | unsafe fn into_address(self) -> Address<Const, T> { |
73 | 123k | if cfg!(debug_assertions) { |
74 | 0 | self.try_conv::<Address<_, _>>() |
75 | 0 | .unwrap_or_else(|err| panic!("{}", err)) |
76 | 0 | .pipe(check_alignment) |
77 | 0 | .unwrap_or_else(|err| panic!("{}", err)) |
78 | | } |
79 | | else { |
80 | 123k | Address::new(NonNull::new_unchecked(self as *mut T)) |
81 | | } |
82 | 123k | } <*const u8 as bitvec::ptr::addr::AddressExt>::into_address Line | Count | Source | 72 | 123k | unsafe fn into_address(self) -> Address<Const, T> { | 73 | 123k | if cfg!(debug_assertions) { | 74 | 0 | self.try_conv::<Address<_, _>>() | 75 | 0 | .unwrap_or_else(|err| panic!("{}", err)) | 76 | 0 | .pipe(check_alignment) | 77 | 0 | .unwrap_or_else(|err| panic!("{}", err)) | 78 | | } | 79 | | else { | 80 | 123k | Address::new(NonNull::new_unchecked(self as *mut T)) | 81 | | } | 82 | 123k | } |
Unexecuted instantiation: <*const _ as bitvec::ptr::addr::AddressExt>::into_address |
83 | | } |
84 | | |
85 | | #[cfg(not(tarpaulin_include))] |
86 | | impl<T> AddressExt for *mut T { |
87 | | type Permission = Mut; |
88 | | type Referent = T; |
89 | | |
90 | 145k | unsafe fn into_address(self) -> Address<Mut, T> { |
91 | 145k | if cfg!(debug_assertions) { |
92 | 0 | self.try_conv::<Address<_, _>>() |
93 | 0 | .unwrap_or_else(|err| panic!("{}", err)) |
94 | 0 | .pipe(check_alignment) |
95 | 0 | .unwrap_or_else(|err| panic!("{}", err)) |
96 | | } |
97 | | else { |
98 | 145k | Address::new(NonNull::new_unchecked(self)) |
99 | | } |
100 | 145k | } <*mut u8 as bitvec::ptr::addr::AddressExt>::into_address Line | Count | Source | 90 | 145k | unsafe fn into_address(self) -> Address<Mut, T> { | 91 | 145k | if cfg!(debug_assertions) { | 92 | 0 | self.try_conv::<Address<_, _>>() | 93 | 0 | .unwrap_or_else(|err| panic!("{}", err)) | 94 | 0 | .pipe(check_alignment) | 95 | 0 | .unwrap_or_else(|err| panic!("{}", err)) | 96 | | } | 97 | | else { | 98 | 145k | Address::new(NonNull::new_unchecked(self)) | 99 | | } | 100 | 145k | } |
Unexecuted instantiation: <*mut _ as bitvec::ptr::addr::AddressExt>::into_address |
101 | | } |
102 | | |
103 | | #[cfg(not(tarpaulin_include))] |
104 | | impl<T> AddressExt for &T { |
105 | | type Permission = Const; |
106 | | type Referent = T; |
107 | | |
108 | 0 | unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent> { |
109 | 0 | self.into() |
110 | 0 | } |
111 | | } |
112 | | |
113 | | #[cfg(not(tarpaulin_include))] |
114 | | impl<T> AddressExt for &mut T { |
115 | | type Permission = Mut; |
116 | | type Referent = T; |
117 | | |
118 | 0 | unsafe fn into_address(self) -> Address<Self::Permission, Self::Referent> { |
119 | 0 | self.into() |
120 | 0 | } |
121 | | } |
122 | | |
123 | | /// The error produced when an address is insufficiently aligned to the width of |
124 | | /// its type. |
125 | | #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] |
126 | | pub struct MisalignError<T> { |
127 | | /// The misaligned pointer. |
128 | | ptr: *const T, |
129 | | } |
130 | | |
131 | | impl<T> MisalignError<T> { |
132 | | /// The minimum address alignment of `T` values. |
133 | | const ALIGN: usize = mem::align_of::<T>(); |
134 | | /// The number of least-significant-bits of an address that must be `0` in |
135 | | /// order for it to be validly aligned for `T`. |
136 | | const CTTZ: usize = Self::ALIGN.trailing_zeros() as usize; |
137 | | } |
138 | | |
139 | | #[cfg(not(tarpaulin_include))] |
140 | | impl<T> Debug for MisalignError<T> { |
141 | | #[inline] |
142 | 0 | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
143 | 0 | fmt.debug_tuple("MisalignError") |
144 | 0 | .field(&self.ptr.fmt_pointer()) |
145 | 0 | .field(&Self::ALIGN) |
146 | 0 | .finish() |
147 | 0 | } Unexecuted instantiation: <bitvec::ptr::addr::MisalignError<u8> as core::fmt::Debug>::fmt Unexecuted instantiation: <bitvec::ptr::addr::MisalignError<_> as core::fmt::Debug>::fmt |
148 | | } |
149 | | |
150 | | #[cfg(not(tarpaulin_include))] |
151 | | impl<T> Display for MisalignError<T> { |
152 | | #[inline] |
153 | 0 | fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { |
154 | 0 | write!( |
155 | 0 | fmt, |
156 | 0 | "Type {} requires {}-byte alignment: address ", |
157 | 0 | any::type_name::<T>(), |
158 | | Self::ALIGN, |
159 | 0 | )?; |
160 | 0 | Pointer::fmt(&self.ptr, fmt)?; |
161 | 0 | write!(fmt, " must clear its least {} bits", Self::CTTZ) |
162 | 0 | } |
163 | | } |
164 | | |
165 | | unsafe impl<T> Send for MisalignError<T> {} |
166 | | |
167 | | unsafe impl<T> Sync for MisalignError<T> {} |
168 | | |
169 | | #[cfg(feature = "std")] |
170 | | impl<T> std::error::Error for MisalignError<T> {} |