Coverage Report

Created: 2026-01-22 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hex-0.4.3/src/lib.rs
Line
Count
Source
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")]
41
extern crate alloc;
42
#[cfg(feature = "alloc")]
43
use alloc::{string::String, vec::Vec};
44
45
use core::iter;
46
47
mod error;
48
pub use crate::error::FromHexError;
49
50
#[cfg(feature = "serde")]
51
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
52
pub mod serde;
53
#[cfg(feature = "serde")]
54
pub use crate::serde::deserialize;
55
#[cfg(all(feature = "alloc", feature = "serde"))]
56
pub 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()`].
73
pub 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
83
const HEX_CHARS_LOWER: &[u8; 16] = b"0123456789abcdef";
84
const HEX_CHARS_UPPER: &[u8; 16] = b"0123456789ABCDEF";
85
86
struct BytesToHexChars<'a> {
87
    inner: ::core::slice::Iter<'a, u8>,
88
    table: &'static [u8; 16],
89
    next: Option<char>,
90
}
91
92
impl<'a> BytesToHexChars<'a> {
93
238k
    fn new(inner: &'a [u8], table: &'static [u8; 16]) -> BytesToHexChars<'a> {
94
238k
        BytesToHexChars {
95
238k
            inner: inner.iter(),
96
238k
            table,
97
238k
            next: None,
98
238k
        }
99
238k
    }
100
}
101
102
impl<'a> Iterator for BytesToHexChars<'a> {
103
    type Item = char;
104
105
2.55M
    fn next(&mut self) -> Option<Self::Item> {
106
2.55M
        match self.next.take() {
107
1.15M
            Some(current) => Some(current),
108
1.39M
            None => self.inner.next().map(|byte| {
109
1.15M
                let current = self.table[(byte >> 4) as usize] as char;
110
1.15M
                self.next = Some(self.table[(byte & 0x0F) as usize] as char);
111
1.15M
                current
112
1.15M
            }),
113
        }
114
2.55M
    }
115
116
238k
    fn size_hint(&self) -> (usize, Option<usize>) {
117
238k
        let length = self.len();
118
238k
        (length, Some(length))
119
238k
    }
120
}
121
122
impl<'a> iter::ExactSizeIterator for BytesToHexChars<'a> {
123
238k
    fn len(&self) -> usize {
124
238k
        let mut length = self.inner.len() * 2;
125
238k
        if self.next.is_some() {
126
0
            length += 1;
127
238k
        }
128
238k
        length
129
238k
    }
130
}
131
132
#[inline]
133
238k
fn encode_to_iter<T: iter::FromIterator<char>>(table: &'static [u8; 16], source: &[u8]) -> T {
134
238k
    BytesToHexChars::new(source, table).collect()
135
238k
}
hex::encode_to_iter::<alloc::string::String>
Line
Count
Source
133
238k
fn encode_to_iter<T: iter::FromIterator<char>>(table: &'static [u8; 16], source: &[u8]) -> T {
134
238k
    BytesToHexChars::new(source, table).collect()
135
238k
}
Unexecuted instantiation: hex::encode_to_iter::<_>
136
137
impl<T: AsRef<[u8]>> ToHex for T {
138
238k
    fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
139
238k
        encode_to_iter(HEX_CHARS_LOWER, self.as_ref())
140
238k
    }
Unexecuted instantiation: <[u8; 16] as hex::ToHex>::encode_hex::<alloc::string::String>
<[u8; 1] as hex::ToHex>::encode_hex::<alloc::string::String>
Line
Count
Source
138
155k
    fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
139
155k
        encode_to_iter(HEX_CHARS_LOWER, self.as_ref())
140
155k
    }
<[u8; 12] as hex::ToHex>::encode_hex::<alloc::string::String>
Line
Count
Source
138
83.6k
    fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
139
83.6k
        encode_to_iter(HEX_CHARS_LOWER, self.as_ref())
140
83.6k
    }
Unexecuted instantiation: <&[u8] as hex::ToHex>::encode_hex::<alloc::string::String>
Unexecuted instantiation: <&alloc::vec::Vec<u8> as hex::ToHex>::encode_hex::<alloc::string::String>
Unexecuted instantiation: <_ as hex::ToHex>::encode_hex::<_>
141
142
0
    fn encode_hex_upper<U: iter::FromIterator<char>>(&self) -> U {
143
0
        encode_to_iter(HEX_CHARS_UPPER, self.as_ref())
144
0
    }
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
/// ```
164
pub 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
175
2.16M
fn val(c: u8, idx: usize) -> Result<u8, FromHexError> {
176
2.16M
    match c {
177
390k
        b'A'..=b'F' => Ok(c - b'A' + 10),
178
389k
        b'a'..=b'f' => Ok(c - b'a' + 10),
179
1.77M
        b'0'..=b'9' => Ok(c - b'0'),
180
138
        _ => Err(FromHexError::InvalidHexCharacter {
181
138
            c: c as char,
182
138
            index: idx,
183
138
        }),
184
    }
185
2.16M
}
186
187
#[cfg(feature = "alloc")]
188
impl FromHex for Vec<u8> {
189
    type Error = FromHexError;
190
191
223k
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
192
223k
        let hex = hex.as_ref();
193
223k
        if hex.len() % 2 != 0 {
194
20
            return Err(FromHexError::OddLength);
195
223k
        }
196
197
223k
        hex.chunks(2)
198
223k
            .enumerate()
199
1.08M
            .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?))
<alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<&[u8]>::{closure#0}
Line
Count
Source
199
939k
            .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?))
<alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<&str>::{closure#0}
Line
Count
Source
199
145k
            .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?))
Unexecuted instantiation: <alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<_>::{closure#0}
200
223k
            .collect()
201
223k
    }
<alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<&[u8]>
Line
Count
Source
191
78.4k
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
192
78.4k
        let hex = hex.as_ref();
193
78.4k
        if hex.len() % 2 != 0 {
194
16
            return Err(FromHexError::OddLength);
195
78.3k
        }
196
197
78.3k
        hex.chunks(2)
198
78.3k
            .enumerate()
199
78.3k
            .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?))
200
78.3k
            .collect()
201
78.4k
    }
<alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<&str>
Line
Count
Source
191
145k
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
192
145k
        let hex = hex.as_ref();
193
145k
        if hex.len() % 2 != 0 {
194
4
            return Err(FromHexError::OddLength);
195
145k
        }
196
197
145k
        hex.chunks(2)
198
145k
            .enumerate()
199
145k
            .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?))
200
145k
            .collect()
201
145k
    }
Unexecuted instantiation: <alloc::vec::Vec<u8> as hex::FromHex>::from_hex::<_>
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.
206
macro_rules! from_hex_array_impl {
207
    ($($len:expr)+) => {$(
208
        impl FromHex for [u8; $len] {
209
            type Error = FromHexError;
210
211
0
            fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
212
0
                let mut out = [0_u8; $len];
213
0
                decode_to_slice(hex, &mut out as &mut [u8])?;
214
0
                Ok(out)
215
0
            }
Unexecuted instantiation: <[u8; 60] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 61] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 62] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 63] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 64] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 65] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 66] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 67] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 68] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 69] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 96] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 97] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 98] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 99] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 100] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 101] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 102] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 103] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 104] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 105] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 106] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 107] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 108] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 109] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 110] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 111] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 112] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 113] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 114] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 115] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 116] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 117] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 118] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 119] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 120] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 121] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 70] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 71] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 72] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 73] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 74] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 75] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 76] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 77] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 78] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 79] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 80] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 81] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 82] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 83] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 84] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 85] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 86] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 87] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 88] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 89] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 90] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 91] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 92] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 93] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 94] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 95] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 122] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 123] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 124] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 125] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 126] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 127] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 128] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 160] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 192] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 200] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 2147483648] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 4294967296] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 224] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 256] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 384] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 512] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 768] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 1024] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 2048] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 4096] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 8192] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 16384] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 32768] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 65536] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 131072] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 262144] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 524288] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 1048576] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 2097152] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 4194304] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 8388608] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 16777216] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 33554432] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 67108864] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 134217728] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 268435456] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 536870912] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 1073741824] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 1] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 2] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 3] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 4] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 5] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 6] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 7] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 34] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 35] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 36] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 37] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 38] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 39] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 40] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 41] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 42] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 43] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 44] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 45] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 46] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 47] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 48] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 49] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 50] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 51] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 52] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 53] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 54] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 55] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 56] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 57] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 58] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 59] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 8] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 9] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 10] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 11] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 12] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 13] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 14] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 15] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 16] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 17] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 18] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 19] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 20] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 21] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 22] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 23] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 24] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 25] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 26] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 27] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 28] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 29] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 30] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 31] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 32] as hex::FromHex>::from_hex::<_>
Unexecuted instantiation: <[u8; 33] as hex::FromHex>::from_hex::<_>
216
        }
217
    )+}
218
}
219
220
from_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"))]
233
from_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")]
240
from_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")]
259
238k
pub fn encode<T: AsRef<[u8]>>(data: T) -> String {
260
238k
    data.encode_hex()
261
238k
}
Unexecuted instantiation: hex::encode::<[u8; 16]>
hex::encode::<[u8; 1]>
Line
Count
Source
259
155k
pub fn encode<T: AsRef<[u8]>>(data: T) -> String {
260
155k
    data.encode_hex()
261
155k
}
hex::encode::<[u8; 12]>
Line
Count
Source
259
83.6k
pub fn encode<T: AsRef<[u8]>>(data: T) -> String {
260
83.6k
    data.encode_hex()
261
83.6k
}
Unexecuted instantiation: hex::encode::<&alloc::vec::Vec<u8>>
Unexecuted instantiation: hex::encode::<&[u8]>
Unexecuted instantiation: hex::encode::<_>
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")]
275
0
pub fn encode_upper<T: AsRef<[u8]>>(data: T) -> String {
276
0
    data.encode_hex_upper()
277
0
}
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")]
296
223k
pub fn decode<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, FromHexError> {
297
223k
    FromHex::from_hex(data)
298
223k
}
hex::decode::<&[u8]>
Line
Count
Source
296
78.4k
pub fn decode<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, FromHexError> {
297
78.4k
    FromHex::from_hex(data)
298
78.4k
}
hex::decode::<&str>
Line
Count
Source
296
145k
pub fn decode<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, FromHexError> {
297
145k
    FromHex::from_hex(data)
298
145k
}
Unexecuted instantiation: hex::decode::<_>
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
/// ```
312
0
pub fn decode_to_slice<T: AsRef<[u8]>>(data: T, out: &mut [u8]) -> Result<(), FromHexError> {
313
0
    let data = data.as_ref();
314
315
0
    if data.len() % 2 != 0 {
316
0
        return Err(FromHexError::OddLength);
317
0
    }
318
0
    if data.len() / 2 != out.len() {
319
0
        return Err(FromHexError::InvalidStringLength);
320
0
    }
321
322
0
    for (i, byte) in out.iter_mut().enumerate() {
323
0
        *byte = val(data[2 * i], 2 * i)? << 4 | val(data[2 * i + 1], 2 * i + 1)?;
324
    }
325
326
0
    Ok(())
327
0
}
328
329
// generates an iterator like this
330
// (0, 1)
331
// (2, 3)
332
// (4, 5)
333
// (6, 7)
334
// ...
335
#[inline]
336
0
fn generate_iter(len: usize) -> impl Iterator<Item = (usize, usize)> {
337
0
    (0..len).step_by(2).zip((0..len).skip(1).step_by(2))
338
0
}
339
340
// the inverse of `val`.
341
#[inline]
342
#[must_use]
343
0
fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) {
344
0
    let high = table[((byte & 0xf0) >> 4) as usize];
345
0
    let low = table[(byte & 0x0f) as usize];
346
347
0
    (high, low)
348
0
}
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
/// ```
367
0
pub fn encode_to_slice<T: AsRef<[u8]>>(input: T, output: &mut [u8]) -> Result<(), FromHexError> {
368
0
    if input.as_ref().len() * 2 != output.len() {
369
0
        return Err(FromHexError::InvalidStringLength);
370
0
    }
371
372
0
    for (byte, (i, j)) in input
373
0
        .as_ref()
374
0
        .iter()
375
0
        .zip(generate_iter(input.as_ref().len() * 2))
376
0
    {
377
0
        let (high, low) = byte2hex(*byte, HEX_CHARS_LOWER);
378
0
        output[i] = high;
379
0
        output[j] = low;
380
0
    }
381
382
0
    Ok(())
383
0
}
384
385
#[cfg(test)]
386
mod 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
}