1 // Bitcoin Hashes Library
2 // Written in 2018 by
3 // Andrew Poelstra <apoelstra@wpsoftware.net>
4 //
5 // To the extent possible under law, the author(s) have dedicated all
6 // copyright and related and neighboring rights to this software to
7 // the public domain worldwide. This software is distributed without
8 // any warranty.
9 //
10 // You should have received a copy of the CC0 Public Domain Dedication
11 // along with this software.
12 // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13 //
14
15 //! # Hex encoding and decoding
16 //!
17
18 #[cfg(any(feature = "std", feature = "alloc"))]
19 use alloc::{string::String, vec::Vec};
20 #[cfg(feature = "alloc")]
21 use alloc::format;
22
23 use core::{fmt, str};
24 use Hash;
25
26 /// Hex decoding error
27 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28 pub enum Error {
29 /// non-hexadecimal character
30 InvalidChar(u8),
31 /// purported hex string had odd length
32 OddLengthString(usize),
33 /// tried to parse fixed-length hash from a string with the wrong type (expected, got)
34 InvalidLength(usize, usize),
35 }
36
37 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 match *self {
40 Error::InvalidChar(ch) => write!(f, "invalid hex character {}", ch),
41 Error::OddLengthString(ell) => write!(f, "odd hex string length {}", ell),
42 Error::InvalidLength(ell, ell2) => write!(f, "bad hex string length {} (expected {})", ell2, ell),
43 }
44 }
45 }
46
47 /// Trait for objects that can be serialized as hex strings
48 #[cfg(any(test, feature = "std", feature = "alloc"))]
49 pub trait ToHex {
50 /// Hex representation of the object
to_hex(&self) -> String51 fn to_hex(&self) -> String;
52 }
53
54 /// Trait for objects that can be deserialized from hex strings
55 pub trait FromHex: Sized {
56 /// Produce an object from a byte iterator
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator57 fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
58 where I: Iterator<Item=Result<u8, Error>> +
59 ExactSizeIterator +
60 DoubleEndedIterator;
61
62 /// Produce an object from a hex string
from_hex(s: &str) -> Result<Self, Error>63 fn from_hex(s: &str) -> Result<Self, Error> {
64 Self::from_byte_iter(HexIterator::new(s)?)
65 }
66 }
67
68 #[cfg(any(test, feature = "std", feature = "alloc"))]
69 impl<T: fmt::LowerHex> ToHex for T {
70 /// Outputs the hash in hexadecimal form
to_hex(&self) -> String71 fn to_hex(&self) -> String {
72 format!("{:x}", self)
73 }
74 }
75
76 impl<T: Hash> FromHex for T {
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator,77 fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
78 where I: Iterator<Item=Result<u8, Error>> +
79 ExactSizeIterator +
80 DoubleEndedIterator,
81 {
82 let inner;
83 if Self::DISPLAY_BACKWARD {
84 inner = T::Inner::from_byte_iter(iter.rev())?;
85 } else {
86 inner = T::Inner::from_byte_iter(iter)?;
87 }
88 Ok(Hash::from_inner(inner))
89 }
90 }
91
92 /// Iterator over a hex-encoded string slice which decodes hex and yields bytes.
93 pub struct HexIterator<'a> {
94 /// The `Bytes` iterator whose next two bytes will be decoded to yield
95 /// the next byte.
96 iter: str::Bytes<'a>,
97 }
98
99 impl<'a> HexIterator<'a> {
100 /// Constructs a new `HexIterator` from a string slice. If the string is of
101 /// odd length it returns an error.
new(s: &'a str) -> Result<HexIterator<'a>, Error>102 pub fn new(s: &'a str) -> Result<HexIterator<'a>, Error> {
103 if s.len() % 2 != 0 {
104 Err(Error::OddLengthString(s.len()))
105 } else {
106 Ok(HexIterator { iter: s.bytes() })
107 }
108 }
109 }
110
chars_to_hex(hi: u8, lo: u8) -> Result<u8, Error>111 fn chars_to_hex(hi: u8, lo: u8) -> Result<u8, Error> {
112 let hih = (hi as char)
113 .to_digit(16)
114 .ok_or(Error::InvalidChar(hi))?;
115 let loh = (lo as char)
116 .to_digit(16)
117 .ok_or(Error::InvalidChar(lo))?;
118
119 let ret = (hih << 4) + loh;
120 Ok(ret as u8)
121 }
122
123 impl<'a> Iterator for HexIterator<'a> {
124 type Item = Result<u8, Error>;
125
next(&mut self) -> Option<Result<u8, Error>>126 fn next(&mut self) -> Option<Result<u8, Error>> {
127 let hi = self.iter.next()?;
128 let lo = self.iter.next().unwrap();
129 Some(chars_to_hex(hi, lo))
130 }
131
size_hint(&self) -> (usize, Option<usize>)132 fn size_hint(&self) -> (usize, Option<usize>) {
133 let (min, max) = self.iter.size_hint();
134 (min / 2, max.map(|x| x /2))
135 }
136 }
137
138 impl<'a> DoubleEndedIterator for HexIterator<'a> {
next_back(&mut self) -> Option<Result<u8, Error>>139 fn next_back(&mut self) -> Option<Result<u8, Error>> {
140 let lo = self.iter.next_back()?;
141 let hi = self.iter.next_back().unwrap();
142 Some(chars_to_hex(hi, lo))
143 }
144 }
145
146 impl<'a> ExactSizeIterator for HexIterator<'a> {}
147
148 /// Output hex into an object implementing `fmt::Write`, which is usually more
149 /// efficient than going through a `String` using `ToHex`.
format_hex(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result150 pub fn format_hex(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
151 let prec = f.precision().unwrap_or(2 * data.len());
152 let width = f.width().unwrap_or(2 * data.len());
153 for _ in (2 * data.len())..width {
154 f.write_str("0")?;
155 }
156 for ch in data.iter().take(prec / 2) {
157 write!(f, "{:02x}", *ch)?;
158 }
159 if prec < 2 * data.len() && prec % 2 == 1 {
160 write!(f, "{:x}", data[prec / 2] / 16)?;
161 }
162 Ok(())
163 }
164
165 /// Output hex in reverse order; used for Sha256dHash whose standard hex encoding
166 /// has the bytes reversed.
format_hex_reverse(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result167 pub fn format_hex_reverse(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
168 let prec = f.precision().unwrap_or(2 * data.len());
169 let width = f.width().unwrap_or(2 * data.len());
170 for _ in (2 * data.len())..width {
171 f.write_str("0")?;
172 }
173 for ch in data.iter().rev().take(prec / 2) {
174 write!(f, "{:02x}", *ch)?;
175 }
176 if prec < 2 * data.len() && prec % 2 == 1 {
177 write!(f, "{:x}", data[data.len() - 1 - prec / 2] / 16)?;
178 }
179 Ok(())
180 }
181
182 #[cfg(any(test, feature = "alloc", feature = "std"))]
183 impl ToHex for [u8] {
to_hex(&self) -> String184 fn to_hex(&self) -> String {
185 use core::fmt::Write;
186 let mut ret = String::with_capacity(2 * self.len());
187 for ch in self {
188 write!(ret, "{:02x}", ch).expect("writing to string");
189 }
190 ret
191 }
192 }
193
194 #[cfg(any(test, feature = "std", feature = "alloc"))]
195 impl FromHex for Vec<u8> {
from_byte_iter<I>(iter: I) -> Result<Self, Error> where I: Iterator<Item=Result<u8, Error>> + ExactSizeIterator + DoubleEndedIterator,196 fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
197 where I: Iterator<Item=Result<u8, Error>> +
198 ExactSizeIterator +
199 DoubleEndedIterator,
200 {
201 iter.collect()
202 }
203 }
204
205 macro_rules! impl_fromhex_array {
206 ($len:expr) => {
207 impl FromHex for [u8; $len] {
208 fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
209 where I: Iterator<Item=Result<u8, Error>> +
210 ExactSizeIterator +
211 DoubleEndedIterator,
212 {
213 if iter.len() == $len {
214 let mut ret = [0; $len];
215 for (n, byte) in iter.enumerate() {
216 ret[n] = byte?;
217 }
218 Ok(ret)
219 } else {
220 Err(Error::InvalidLength(2 * $len, 2 * iter.len()))
221 }
222 }
223 }
224 }
225 }
226
227 impl_fromhex_array!(2);
228 impl_fromhex_array!(4);
229 impl_fromhex_array!(6);
230 impl_fromhex_array!(8);
231 impl_fromhex_array!(10);
232 impl_fromhex_array!(12);
233 impl_fromhex_array!(14);
234 impl_fromhex_array!(16);
235 impl_fromhex_array!(20);
236 impl_fromhex_array!(24);
237 impl_fromhex_array!(28);
238 impl_fromhex_array!(32);
239 impl_fromhex_array!(33);
240 impl_fromhex_array!(64);
241 impl_fromhex_array!(65);
242 impl_fromhex_array!(128);
243 impl_fromhex_array!(256);
244 impl_fromhex_array!(384);
245 impl_fromhex_array!(512);
246
247 #[cfg(test)]
248 mod tests {
249 use super::*;
250
251 use core::fmt;
252
253 #[test]
hex_roundtrip()254 fn hex_roundtrip() {
255 let expected = "0123456789abcdef";
256 let expected_up = "0123456789ABCDEF";
257
258 let parse: Vec<u8> = FromHex::from_hex(expected).expect("parse lowercase string");
259 assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
260 let ser = parse.to_hex();
261 assert_eq!(ser, expected);
262
263 let parse: Vec<u8> = FromHex::from_hex(expected_up).expect("parse uppercase string");
264 assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
265 let ser = parse.to_hex();
266 assert_eq!(ser, expected);
267
268 let parse: [u8; 8] = FromHex::from_hex(expected_up).expect("parse uppercase string");
269 assert_eq!(parse, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
270 let ser = parse.to_hex();
271 assert_eq!(ser, expected);
272 }
273
274 #[test]
hex_truncate()275 fn hex_truncate() {
276 struct HexBytes(Vec<u8>);
277 impl fmt::LowerHex for HexBytes {
278 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279 format_hex(&self.0, f)
280 }
281 }
282
283 let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
284
285 assert_eq!(
286 format!("{:x}", bytes),
287 "0102030405060708090a"
288 );
289
290 for i in 0..20 {
291 assert_eq!(
292 format!("{:.prec$x}", bytes, prec = i),
293 &"0102030405060708090a"[0..i]
294 );
295 }
296
297 assert_eq!(
298 format!("{:25x}", bytes),
299 "000000102030405060708090a"
300 );
301 assert_eq!(
302 format!("{:26x}", bytes),
303 "0000000102030405060708090a"
304 );
305 }
306
307 #[test]
hex_truncate_rev()308 fn hex_truncate_rev() {
309 struct HexBytes(Vec<u8>);
310 impl fmt::LowerHex for HexBytes {
311 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312 format_hex_reverse(&self.0, f)
313 }
314 }
315
316 let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
317
318 assert_eq!(
319 format!("{:x}", bytes),
320 "0a090807060504030201"
321 );
322
323 for i in 0..20 {
324 assert_eq!(
325 format!("{:.prec$x}", bytes, prec = i),
326 &"0a090807060504030201"[0..i]
327 );
328 }
329
330 assert_eq!(
331 format!("{:25x}", bytes),
332 "000000a090807060504030201"
333 );
334 assert_eq!(
335 format!("{:26x}", bytes),
336 "0000000a090807060504030201"
337 );
338 }
339
340 #[test]
hex_error()341 fn hex_error() {
342 let oddlen = "0123456789abcdef0";
343 let badchar1 = "Z123456789abcdef";
344 let badchar2 = "012Y456789abcdeb";
345 let badchar3 = "«23456789abcdef";
346
347 assert_eq!(
348 Vec::<u8>::from_hex(oddlen),
349 Err(Error::OddLengthString(17))
350 );
351 assert_eq!(
352 <[u8; 4]>::from_hex(oddlen),
353 Err(Error::OddLengthString(17))
354 );
355 assert_eq!(
356 <[u8; 8]>::from_hex(oddlen),
357 Err(Error::OddLengthString(17))
358 );
359 assert_eq!(
360 Vec::<u8>::from_hex(badchar1),
361 Err(Error::InvalidChar(b'Z'))
362 );
363 assert_eq!(
364 Vec::<u8>::from_hex(badchar2),
365 Err(Error::InvalidChar(b'Y'))
366 );
367 assert_eq!(
368 Vec::<u8>::from_hex(badchar3),
369 Err(Error::InvalidChar(194))
370 );
371 }
372 }
373
374