Skip to content

Commit 6bae168

Browse files
committed
Add formatting traits to Address/Offset
Signed-off-by: Nathaniel McCallum <[email protected]>
1 parent 1b9a555 commit 6bae168

File tree

2 files changed

+85
-27
lines changed

2 files changed

+85
-27
lines changed

src/address.rs

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// SPDX-License-Identifier: Apache-2.0
22

33
use super::*;
4-
use core::fmt::{self, Formatter};
54
use core::marker::PhantomData;
6-
use core::mem::align_of;
5+
use core::mem::{align_of, size_of};
76
use core::ops::*;
87

98
/// An address
@@ -18,10 +17,54 @@ use core::ops::*;
1817
/// Unlike the naked underlying types, you can infallibly convert between,
1918
/// for example, an `Address<usize, ()>` and an `Address<u64, ()>` wherever
2019
/// such a conversion is lossless given the target CPU architecture.
21-
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
20+
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
2221
#[repr(transparent)]
2322
pub struct Address<T, U>(T, PhantomData<U>);
2423

24+
impl<T: core::fmt::Binary, U> core::fmt::Binary for Address<T, U> {
25+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26+
core::fmt::Binary::fmt(&self.0, f)
27+
}
28+
}
29+
30+
impl<T: core::fmt::LowerHex, U> core::fmt::Debug for Address<T, U> {
31+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32+
f.write_fmt(format_args!(
33+
"Address(0x{:01$x})",
34+
self.0,
35+
size_of::<T>() * 2
36+
))
37+
}
38+
}
39+
40+
impl<T: core::fmt::Display, U> core::fmt::Display for Address<T, U> {
41+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
42+
core::fmt::Display::fmt(&self.0, f)
43+
}
44+
}
45+
46+
impl<T: core::fmt::LowerHex, U> core::fmt::LowerHex for Address<T, U> {
47+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48+
core::fmt::LowerHex::fmt(&self.0, f)
49+
}
50+
}
51+
52+
impl<T, U> core::fmt::Pointer for Address<T, U>
53+
where
54+
Self: Into<Address<usize, U>>,
55+
Self: Copy,
56+
{
57+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58+
core::fmt::Pointer::fmt(&self.as_ptr(), f)
59+
}
60+
}
61+
62+
impl<T: core::fmt::UpperHex, U> core::fmt::UpperHex for Address<T, U> {
63+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64+
core::fmt::UpperHex::fmt(&self.0, f)
65+
}
66+
}
67+
2568
#[cfg(feature = "const-default")]
2669
impl<T: Zero, U> const_default::ConstDefault for Address<T, U> {
2770
const DEFAULT: Self = Self::NULL;
@@ -56,57 +99,48 @@ impl<T, U> Address<T, U> {
5699

57100
impl<T, U> Address<T, U>
58101
where
59-
Address<usize, U>: From<Address<T, U>>,
60-
Address<T, U>: Copy,
102+
Self: Into<Address<usize, U>>,
61103
{
62104
/// Returns a raw pointer to its inner type
63105
///
64106
/// # Safety
65107
/// Behavior is undefined, if the pointer is used and
66108
/// is not aligned or points to uninitialized memory.
67-
pub fn as_ptr(&self) -> *const U {
68-
Address::<usize, U>::from(*self).0 as *const U
109+
#[inline]
110+
pub fn as_ptr(self) -> *const U {
111+
self.into().0 as *const U
69112
}
70113

71114
/// Returns a raw pointer to its inner type
72115
///
73116
/// # Safety
74117
/// Behavior is undefined, if the pointer is used and
75118
/// is not aligned or points to uninitialized memory.
76-
pub fn as_mut_ptr(&self) -> *mut U {
77-
Address::<usize, U>::from(*self).0 as *mut U
78-
}
79-
}
80-
81-
impl<T: Copy, U> fmt::Pointer for Address<T, U>
82-
where
83-
Address<usize, U>: From<Address<T, U>>,
84-
Address<T, U>: Copy,
85-
{
86-
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87-
write!(f, "{:p}", self.as_ptr())
119+
#[inline]
120+
pub fn as_mut_ptr(self) -> *mut U {
121+
self.into().0 as *mut U
88122
}
89123
}
90124

91125
pub struct AlignmentError;
92126

93127
impl<T, U> Address<T, U>
94128
where
95-
Offset<usize, ()>: Into<Offset<T, ()>>,
96-
T: Rem<T, Output = T>,
97-
T: Zero,
98-
T: PartialEq,
129+
Self: Into<Address<usize, U>>,
130+
Self: From<Address<usize, U>>,
99131
{
100132
/// Try casting an existing `Address` into an `Address` of a different type
101133
///
102-
/// Succeeds only, if they have the same alignment
134+
/// Succeeds only, if they have compatible alignment
103135
#[inline]
104136
pub fn try_cast<V>(self) -> Result<Address<T, V>, AlignmentError> {
105-
let align: T = Offset::from_items(align_of::<V>()).into().items();
106-
if self.0 % align != T::ZERO {
137+
let addr = self.into();
138+
139+
if addr.0 % align_of::<V>() != 0 {
107140
return Err(AlignmentError);
108141
}
109-
Ok(Address(self.0, PhantomData))
142+
143+
Ok(Address(Self::from(addr).0, PhantomData))
110144
}
111145
}
112146

src/offset.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,30 @@ use core::ops::*;
1818
#[repr(transparent)]
1919
pub struct Offset<T, U>(T, PhantomData<U>);
2020

21+
impl<T: core::fmt::Binary, U> core::fmt::Binary for Offset<T, U> {
22+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23+
core::fmt::Binary::fmt(&self.0, f)
24+
}
25+
}
26+
27+
impl<T: core::fmt::Display, U> core::fmt::Display for Offset<T, U> {
28+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29+
core::fmt::Display::fmt(&self.0, f)
30+
}
31+
}
32+
33+
impl<T: core::fmt::LowerHex, U> core::fmt::LowerHex for Offset<T, U> {
34+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35+
core::fmt::LowerHex::fmt(&self.0, f)
36+
}
37+
}
38+
39+
impl<T: core::fmt::UpperHex, U> core::fmt::UpperHex for Offset<T, U> {
40+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41+
core::fmt::UpperHex::fmt(&self.0, f)
42+
}
43+
}
44+
2145
#[cfg(feature = "const-default")]
2246
impl<T: Zero, U> const_default::ConstDefault for Offset<T, U> {
2347
const DEFAULT: Self = Self(T::ZERO, PhantomData);

0 commit comments

Comments
 (0)