1// Copyright (c) 2013-2014 The Rust Project Developers.
2// Copyright (c) 2015-2020 The rust-hex Developers.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9//! Encoding and decoding hex strings.
10//!
11//! For most cases, you can simply use the [`decode`], [`encode`] and
12//! [`encode_upper`] functions. If you need a bit more control, use the traits
13//! [`ToHex`] and [`FromHex`] instead.
14//!
15//! # Example
16//!
17//! ```
18//! # #[cfg(not(feature = "alloc"))]
19//! # let mut output = [0; 0x18];
20//! #
21//! # #[cfg(not(feature = "alloc"))]
22//! # hex::encode_to_slice(b"Hello world!", &mut output).unwrap();
23//! #
24//! # #[cfg(not(feature = "alloc"))]
25//! # let hex_string = ::core::str::from_utf8(&output).unwrap();
26//! #
27//! # #[cfg(feature = "alloc")]
28//! let hex_string = hex::encode("Hello world!");
29//!
30//! println!("{}", hex_string); // Prints "48656c6c6f20776f726c6421"
31//!
32//! # assert_eq!(hex_string, "48656c6c6f20776f726c6421");
33//! ```
34
35#![doc(html_root_url = "https://docs.rs/hex/0.4.3")]
36#![cfg_attr(not(feature = "std"), no_std)]
37#![cfg_attr(docsrs, feature(doc_cfg))]
38#![allow(clippy::unreadable_literal)]
39
40#[cfg(feature = "alloc")]
41extern crate alloc;
42#[cfg(feature = "alloc")]
43use alloc::{string::String, vec::Vec};
44
45use core::iter;
46
47mod error;
48pub use crate::error::FromHexError;
49
50#[cfg(feature = "serde")]
51#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
52pub mod serde;
53#[cfg(feature = "serde")]
54pub use crate::serde::deserialize;
55#[cfg(all(feature = "alloc", feature = "serde"))]
56pub use crate::serde::{serialize, serialize_upper};
57
58/// Encoding values as hex string.
59///
60/// This trait is implemented for all `T` which implement `AsRef<[u8]>`. This
61/// includes `String`, `str`, `Vec<u8>` and `[u8]`.
62///
63/// # Example
64///
65/// ```
66/// use hex::ToHex;
67///
68/// println!("{}", "Hello world!".encode_hex::<String>());
69/// # assert_eq!("Hello world!".encode_hex::<String>(), "48656c6c6f20776f726c6421".to_string());
70/// ```
71///
72/// *Note*: instead of using this trait, you might want to use [`encode()`].
73pub trait ToHex {
74 /// Encode the hex strict representing `self` into the result. Lower case
75 /// letters are used (e.g. `f9b4ca`)
76 fn encode_hex<T: iter::FromIterator<char>>(&self) -> T;
77
78 /// Encode the hex strict representing `self` into the result. Upper case
79 /// letters are used (e.g. `F9B4CA`)
80 fn encode_hex_upper<T: iter::FromIterator<char>>(&self) -> T;
81}
82
83const HEX_CHARS_LOWER: &[u8; 16] = b"0123456789abcdef";
84const HEX_CHARS_UPPER: &[u8; 16] = b"0123456789ABCDEF";
85
86struct BytesToHexChars<'a> {
87 inner: ::core::slice::Iter<'a, u8>,
88 table: &'static [u8; 16],
89 next: Option<char>,
90}
91
92impl<'a> BytesToHexChars<'a> {
93 fn new(inner: &'a [u8], table: &'static [u8; 16]) -> BytesToHexChars<'a> {
94 BytesToHexChars {
95 inner: inner.iter(),
96 table,
97 next: None,
98 }
99 }
100}
101
102impl<'a> Iterator for BytesToHexChars<'a> {
103 type Item = char;
104
105 fn next(&mut self) -> Option<Self::Item> {
106 match self.next.take() {
107 Some(current: char) => Some(current),
108 None => self.inner.next().map(|byte: &u8| {
109 let current: char = self.table[(byte >> 4) as usize] as char;
110 self.next = Some(self.table[(byte & 0x0F) as usize] as char);
111 current
112 }),
113 }
114 }
115
116 fn size_hint(&self) -> (usize, Option<usize>) {
117 let length: usize = self.len();
118 (length, Some(length))
119 }
120}
121
122impl<'a> iter::ExactSizeIterator for BytesToHexChars<'a> {
123 fn len(&self) -> usize {
124 let mut length: usize = self.inner.len() * 2;
125 if self.next.is_some() {
126 length += 1;
127 }
128 length
129 }
130}
131
132#[inline]
133fn encode_to_iter<T: iter::FromIterator<char>>(table: &'static [u8; 16], source: &[u8]) -> T {
134 BytesToHexChars::new(inner:source, table).collect()
135}
136
137impl<T: AsRef<[u8]>> ToHex for T {
138 fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
139 encode_to_iter(HEX_CHARS_LOWER, self.as_ref())
140 }
141
142 fn encode_hex_upper<U: iter::FromIterator<char>>(&self) -> U {
143 encode_to_iter(HEX_CHARS_UPPER, self.as_ref())
144 }
145}
146
147/// Types that can be decoded from a hex string.
148///
149/// This trait is implemented for `Vec<u8>` and small `u8`-arrays.
150///
151/// # Example
152///
153/// ```
154/// use core::str;
155/// use hex::FromHex;
156///
157/// let buffer = <[u8; 12]>::from_hex("48656c6c6f20776f726c6421")?;
158/// let string = str::from_utf8(&buffer).expect("invalid buffer length");
159///
160/// println!("{}", string); // prints "Hello world!"
161/// # assert_eq!("Hello world!", string);
162/// # Ok::<(), hex::FromHexError>(())
163/// ```
164pub trait FromHex: Sized {
165 type Error;
166
167 /// Creates an instance of type `Self` from the given hex string, or fails
168 /// with a custom error type.
169 ///
170 /// Both, upper and lower case characters are valid and can even be
171 /// mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings).
172 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error>;
173}
174
175fn val(c: u8, idx: usize) -> Result<u8, FromHexError> {
176 match c {
177 b'A'..=b'F' => Ok(c - b'A' + 10),
178 b'a'..=b'f' => Ok(c - b'a' + 10),
179 b'0'..=b'9' => Ok(c - b'0'),
180 _ => Err(FromHexError::InvalidHexCharacter {
181 c: c as char,
182 index: idx,
183 }),
184 }
185}
186
187#[cfg(feature = "alloc")]
188impl FromHex for Vec<u8> {
189 type Error = FromHexError;
190
191 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
192 let hex: &[u8] = hex.as_ref();
193 if hex.len() % 2 != 0 {
194 return Err(FromHexError::OddLength);
195 }
196
197 heximpl Iterator>.chunks(chunk_size:2)
198 .enumerate()
199 .map(|(i: usize, pair: &[u8])| Ok(val(c:pair[0], idx:2 * i)? << 4 | val(c:pair[1], idx:2 * i + 1)?))
200 .collect()
201 }
202}
203
204// Helper macro to implement the trait for a few fixed sized arrays. Once Rust
205// has type level integers, this should be removed.
206macro_rules! from_hex_array_impl {
207 ($($len:expr)+) => {$(
208 impl FromHex for [u8; $len] {
209 type Error = FromHexError;
210
211 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
212 let mut out = [0_u8; $len];
213 decode_to_slice(hex, &mut out as &mut [u8])?;
214 Ok(out)
215 }
216 }
217 )+}
218}
219
220from_hex_array_impl! {
221 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
222 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
223 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
224 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
225 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
226 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
227 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
228 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
229 160 192 200 224 256 384 512 768 1024 2048 4096 8192 16384 32768
230}
231
232#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
233from_hex_array_impl! {
234 65536 131072 262144 524288 1048576 2097152 4194304 8388608
235 16777216 33554432 67108864 134217728 268435456 536870912
236 1073741824 2147483648
237}
238
239#[cfg(target_pointer_width = "64")]
240from_hex_array_impl! {
241 4294967296
242}
243
244/// Encodes `data` as hex string using lowercase characters.
245///
246/// Lowercase characters are used (e.g. `f9b4ca`). The resulting string's
247/// length is always even, each byte in `data` is always encoded using two hex
248/// digits. Thus, the resulting string contains exactly twice as many bytes as
249/// the input data.
250///
251/// # Example
252///
253/// ```
254/// assert_eq!(hex::encode("Hello world!"), "48656c6c6f20776f726c6421");
255/// assert_eq!(hex::encode(vec![1, 2, 3, 15, 16]), "0102030f10");
256/// ```
257#[must_use]
258#[cfg(feature = "alloc")]
259pub fn encode<T: AsRef<[u8]>>(data: T) -> String {
260 data.encode_hex()
261}
262
263/// Encodes `data` as hex string using uppercase characters.
264///
265/// Apart from the characters' casing, this works exactly like `encode()`.
266///
267/// # Example
268///
269/// ```
270/// assert_eq!(hex::encode_upper("Hello world!"), "48656C6C6F20776F726C6421");
271/// assert_eq!(hex::encode_upper(vec![1, 2, 3, 15, 16]), "0102030F10");
272/// ```
273#[must_use]
274#[cfg(feature = "alloc")]
275pub fn encode_upper<T: AsRef<[u8]>>(data: T) -> String {
276 data.encode_hex_upper()
277}
278
279/// Decodes a hex string into raw bytes.
280///
281/// Both, upper and lower case characters are valid in the input string and can
282/// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings).
283///
284/// # Example
285///
286/// ```
287/// assert_eq!(
288/// hex::decode("48656c6c6f20776f726c6421"),
289/// Ok("Hello world!".to_owned().into_bytes())
290/// );
291///
292/// assert_eq!(hex::decode("123"), Err(hex::FromHexError::OddLength));
293/// assert!(hex::decode("foo").is_err());
294/// ```
295#[cfg(feature = "alloc")]
296pub fn decode<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, FromHexError> {
297 FromHex::from_hex(data)
298}
299
300/// Decode a hex string into a mutable bytes slice.
301///
302/// Both, upper and lower case characters are valid in the input string and can
303/// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings).
304///
305/// # Example
306///
307/// ```
308/// let mut bytes = [0u8; 4];
309/// assert_eq!(hex::decode_to_slice("6b697769", &mut bytes as &mut [u8]), Ok(()));
310/// assert_eq!(&bytes, b"kiwi");
311/// ```
312pub fn decode_to_slice<T: AsRef<[u8]>>(data: T, out: &mut [u8]) -> Result<(), FromHexError> {
313 let data: &[u8] = data.as_ref();
314
315 if data.len() % 2 != 0 {
316 return Err(FromHexError::OddLength);
317 }
318 if data.len() / 2 != out.len() {
319 return Err(FromHexError::InvalidStringLength);
320 }
321
322 for (i: usize, byte: &mut u8) in out.iter_mut().enumerate() {
323 *byte = val(c:data[2 * i], idx:2 * i)? << 4 | val(c:data[2 * i + 1], idx:2 * i + 1)?;
324 }
325
326 Ok(())
327}
328
329// generates an iterator like this
330// (0, 1)
331// (2, 3)
332// (4, 5)
333// (6, 7)
334// ...
335#[inline]
336fn generate_iter(len: usize) -> impl Iterator<Item = (usize, usize)> {
337 (0..len).step_by(step:2).zip((0..len).skip(1).step_by(step:2))
338}
339
340// the inverse of `val`.
341#[inline]
342#[must_use]
343fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) {
344 let high: u8 = table[((byte & 0xf0) >> 4) as usize];
345 let low: u8 = table[(byte & 0x0f) as usize];
346
347 (high, low)
348}
349
350/// Encodes some bytes into a mutable slice of bytes.
351///
352/// The output buffer, has to be able to hold at least `input.len() * 2` bytes,
353/// otherwise this function will return an error.
354///
355/// # Example
356///
357/// ```
358/// # use hex::FromHexError;
359/// # fn main() -> Result<(), FromHexError> {
360/// let mut bytes = [0u8; 4 * 2];
361///
362/// hex::encode_to_slice(b"kiwi", &mut bytes)?;
363/// assert_eq!(&bytes, b"6b697769");
364/// # Ok(())
365/// # }
366/// ```
367pub fn encode_to_slice<T: AsRef<[u8]>>(input: T, output: &mut [u8]) -> Result<(), FromHexError> {
368 if input.as_ref().len() * 2 != output.len() {
369 return Err(FromHexError::InvalidStringLength);
370 }
371
372 for (byte: &u8, (i: usize, j: usize)) in inputIter<'_, u8>
373 .as_ref()
374 .iter()
375 .zip(generate_iter(len:input.as_ref().len() * 2))
376 {
377 let (high: u8, low: u8) = byte2hex(*byte, HEX_CHARS_LOWER);
378 output[i] = high;
379 output[j] = low;
380 }
381
382 Ok(())
383}
384
385#[cfg(test)]
386mod test {
387 use super::*;
388 #[cfg(feature = "alloc")]
389 use alloc::string::ToString;
390 use pretty_assertions::assert_eq;
391
392 #[test]
393 #[cfg(feature = "alloc")]
394 fn test_gen_iter() {
395 let result = vec![(0, 1), (2, 3)];
396
397 assert_eq!(generate_iter(5).collect::<Vec<_>>(), result);
398 }
399
400 #[test]
401 fn test_encode_to_slice() {
402 let mut output_1 = [0; 4 * 2];
403 encode_to_slice(b"kiwi", &mut output_1).unwrap();
404 assert_eq!(&output_1, b"6b697769");
405
406 let mut output_2 = [0; 5 * 2];
407 encode_to_slice(b"kiwis", &mut output_2).unwrap();
408 assert_eq!(&output_2, b"6b69776973");
409
410 let mut output_3 = [0; 100];
411
412 assert_eq!(
413 encode_to_slice(b"kiwis", &mut output_3),
414 Err(FromHexError::InvalidStringLength)
415 );
416 }
417
418 #[test]
419 fn test_decode_to_slice() {
420 let mut output_1 = [0; 4];
421 decode_to_slice(b"6b697769", &mut output_1).unwrap();
422 assert_eq!(&output_1, b"kiwi");
423
424 let mut output_2 = [0; 5];
425 decode_to_slice(b"6b69776973", &mut output_2).unwrap();
426 assert_eq!(&output_2, b"kiwis");
427
428 let mut output_3 = [0; 4];
429
430 assert_eq!(
431 decode_to_slice(b"6", &mut output_3),
432 Err(FromHexError::OddLength)
433 );
434 }
435
436 #[test]
437 #[cfg(feature = "alloc")]
438 fn test_encode() {
439 assert_eq!(encode("foobar"), "666f6f626172");
440 }
441
442 #[test]
443 #[cfg(feature = "alloc")]
444 fn test_decode() {
445 assert_eq!(
446 decode("666f6f626172"),
447 Ok(String::from("foobar").into_bytes())
448 );
449 }
450
451 #[test]
452 #[cfg(feature = "alloc")]
453 pub fn test_from_hex_okay_str() {
454 assert_eq!(Vec::from_hex("666f6f626172").unwrap(), b"foobar");
455 assert_eq!(Vec::from_hex("666F6F626172").unwrap(), b"foobar");
456 }
457
458 #[test]
459 #[cfg(feature = "alloc")]
460 pub fn test_from_hex_okay_bytes() {
461 assert_eq!(Vec::from_hex(b"666f6f626172").unwrap(), b"foobar");
462 assert_eq!(Vec::from_hex(b"666F6F626172").unwrap(), b"foobar");
463 }
464
465 #[test]
466 #[cfg(feature = "alloc")]
467 pub fn test_invalid_length() {
468 assert_eq!(Vec::from_hex("1").unwrap_err(), FromHexError::OddLength);
469 assert_eq!(
470 Vec::from_hex("666f6f6261721").unwrap_err(),
471 FromHexError::OddLength
472 );
473 }
474
475 #[test]
476 #[cfg(feature = "alloc")]
477 pub fn test_invalid_char() {
478 assert_eq!(
479 Vec::from_hex("66ag").unwrap_err(),
480 FromHexError::InvalidHexCharacter { c: 'g', index: 3 }
481 );
482 }
483
484 #[test]
485 #[cfg(feature = "alloc")]
486 pub fn test_empty() {
487 assert_eq!(Vec::from_hex("").unwrap(), b"");
488 }
489
490 #[test]
491 #[cfg(feature = "alloc")]
492 pub fn test_from_hex_whitespace() {
493 assert_eq!(
494 Vec::from_hex("666f 6f62617").unwrap_err(),
495 FromHexError::InvalidHexCharacter { c: ' ', index: 4 }
496 );
497 }
498
499 #[test]
500 pub fn test_from_hex_array() {
501 assert_eq!(
502 <[u8; 6] as FromHex>::from_hex("666f6f626172"),
503 Ok([0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72])
504 );
505
506 assert_eq!(
507 <[u8; 5] as FromHex>::from_hex("666f6f626172"),
508 Err(FromHexError::InvalidStringLength)
509 );
510 }
511
512 #[test]
513 #[cfg(feature = "alloc")]
514 fn test_to_hex() {
515 assert_eq!(
516 [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex::<String>(),
517 "666f6f626172".to_string(),
518 );
519
520 assert_eq!(
521 [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex_upper::<String>(),
522 "666F6F626172".to_string(),
523 );
524 }
525}
526