easy_hex/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod decode;
4mod encode;
5
6mod fmt;
7mod from_str;
8
9#[cfg(feature = "serde")]
10mod deserialize;
11#[cfg(feature = "serde")]
12mod serialize;
13
14#[cfg(test)]
15mod tests;
16
17use std::ops::{Deref, DerefMut};
18
19#[cfg(feature = "bytemuck")]
20use bytemuck::{Pod, TransparentWrapper, Zeroable};
21
22/// Lowercase hex serialization of bytes `T`.
23///
24/// This is a simple wrapper around a sequence of bytes `T` that will be serialized,
25/// deserialized and formatted as a lowercase hexadecimal string.
26///
27/// The type has a transparent representation, and implements the
28/// relevant `bytemuck` traits, which allows using it even in situations
29/// where you do not have ownership of the `T`.
30#[derive(Copy, Clone, Default, PartialOrd, Ord, Hash, Eq, PartialEq)]
31#[cfg_attr(feature = "bytemuck", derive(TransparentWrapper, Pod, Zeroable))]
32#[cfg_attr(feature = "bytemuck", transparent(T))]
33#[repr(transparent)]
34pub struct Hex<T: ?Sized>(pub T);
35
36/// Uppercase hex serialization of bytes `T`.
37///
38/// This is a simple wrapper around a sequence of bytes `T` that will be serialized,
39/// deserialized and formatted as a uppercase hexadecimal string.
40///
41/// The type has a transparent representation, and implements the
42/// relevant `bytemuck` traits, which allows using it even in situations
43/// where you do not have ownership of the `T`.
44#[derive(Copy, Clone, Default, PartialOrd, Ord, Hash, Eq, PartialEq)]
45#[cfg_attr(feature = "bytemuck", derive(TransparentWrapper, Pod, Zeroable))]
46#[cfg_attr(feature = "bytemuck", transparent(T))]
47#[repr(transparent)]
48pub struct UpperHex<T: ?Sized>(pub T);
49
50macro_rules! impl_basic {
51    ($Hex:ident) => {
52        // --- conversion traits ----------------
53        //
54        // deref
55        impl<T> Deref for $Hex<T>
56        where
57            T: ?Sized,
58        {
59            type Target = T;
60
61            fn deref(&self) -> &Self::Target {
62                &self.0
63            }
64        }
65        impl<T> DerefMut for $Hex<T>
66        where
67            T: ?Sized,
68        {
69            fn deref_mut(&mut self) -> &mut Self::Target {
70                &mut self.0
71            }
72        }
73
74        // .as
75        impl<T, V> AsRef<V> for $Hex<T>
76        where
77            T: ?Sized + AsRef<V>,
78            V: ?Sized,
79        {
80            fn as_ref(&self) -> &V {
81                self.0.as_ref()
82            }
83        }
84        impl<T, V> AsMut<V> for $Hex<T>
85        where
86            T: ?Sized + AsMut<V>,
87            V: ?Sized,
88        {
89            fn as_mut(&mut self) -> &mut V {
90                self.0.as_mut()
91            }
92        }
93
94        // from/into
95        impl<T> From<T> for $Hex<T> {
96            fn from(value: T) -> Self {
97                Self(value)
98            }
99        }
100        #[cfg(feature = "bytemuck")]
101        impl<'a, T> From<&'a T> for &'a $Hex<T>
102        where
103            T: ?Sized,
104        {
105            fn from(value: &'a T) -> Self {
106                TransparentWrapper::wrap_ref(value)
107            }
108        }
109        #[cfg(feature = "bytemuck")]
110        impl<'a, T> From<&'a mut T> for &'a mut $Hex<T>
111        where
112            T: ?Sized,
113        {
114            fn from(value: &'a mut T) -> Self {
115                TransparentWrapper::wrap_mut(value)
116            }
117        }
118    };
119}
120
121impl_basic!(Hex);
122impl_basic!(UpperHex);
123
124// Helper constants to make the usage of bools easier tor ead in thsi crate
125pub(crate) const LOWER: bool = false;
126pub(crate) const UPPER: bool = true;
127
128/// Extension trait to make it more convenient to wrap byte
129/// sequence types with `Hex` and `UpperHex`. All methods this provides
130/// are also available via `From` implementations for `Hex` and `UpperHex`.
131pub trait HexExt {
132    fn into_hex(self) -> Hex<Self>
133    where
134        Self: Sized;
135    #[cfg(feature = "bytemuck")]
136    fn as_hex(&self) -> &Hex<Self>;
137    #[cfg(feature = "bytemuck")]
138    fn as_hex_mut(&mut self) -> &mut Hex<Self>;
139
140    fn into_upper_hex(self) -> UpperHex<Self>
141    where
142        Self: Sized;
143    #[cfg(feature = "bytemuck")]
144    fn as_upper_hex(&self) -> &UpperHex<Self>;
145    #[cfg(feature = "bytemuck")]
146    fn as_upper_hex_mut(&mut self) -> &mut UpperHex<Self>;
147}
148
149impl<T> HexExt for T
150where
151    T: ?Sized,
152{
153    fn into_hex(self) -> Hex<Self>
154    where
155        Self: Sized,
156    {
157        self.into()
158    }
159
160    #[cfg(feature = "bytemuck")]
161    fn as_hex(&self) -> &Hex<Self> {
162        self.into()
163    }
164
165    #[cfg(feature = "bytemuck")]
166    fn as_hex_mut(&mut self) -> &mut Hex<Self> {
167        self.into()
168    }
169
170    fn into_upper_hex(self) -> UpperHex<Self>
171    where
172        Self: Sized,
173    {
174        self.into()
175    }
176
177    #[cfg(feature = "bytemuck")]
178    fn as_upper_hex(&self) -> &UpperHex<Self> {
179        self.into()
180    }
181
182    #[cfg(feature = "bytemuck")]
183    fn as_upper_hex_mut(&mut self) -> &mut UpperHex<Self> {
184        self.into()
185    }
186}
187
188/// Module that contains the serialization and deserialization
189/// functions for `Hex`. Can be used with `#[serde(with = "...")]`.
190#[cfg(feature = "serde")]
191pub mod serde {
192    pub use crate::deserialize::deserialize;
193    pub use crate::serialize::serialize;
194}
195
196/// Module that contains the serialization and deserialization
197/// functions for `UpperHex`. Can be used with `#[serde(with = "...")]`.
198#[cfg(feature = "serde")]
199pub mod serde_upper {
200    pub use crate::deserialize::deserialize;
201    pub use crate::serialize::serialize_upper as serialize;
202}
203
204pub use decode::decode;
205pub use decode::decode_into;
206pub use encode::encode;
207pub use encode::encode_upper;
208pub use hex::FromHexError;