Coverage Report

Created: 2025-12-20 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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> {}