// Copyright (c) 2013-2014 The Rust Project Developers. // Copyright (c) 2015-2020 The rust-hex Developers. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Encoding and decoding hex strings. //! //! For most cases, you can simply use the [`decode`], [`encode`] and //! [`encode_upper`] functions. If you need a bit more control, use the traits //! [`ToHex`] and [`FromHex`] instead. //! //! # Example //! //! ``` //! # #[cfg(not(feature = "alloc"))] //! # let mut output = [0; 0x18]; //! # //! # #[cfg(not(feature = "alloc"))] //! # hex::encode_to_slice(b"Hello world!", &mut output).unwrap(); //! # //! # #[cfg(not(feature = "alloc"))] //! # let hex_string = ::core::str::from_utf8(&output).unwrap(); //! # //! # #[cfg(feature = "alloc")] //! let hex_string = hex::encode("Hello world!"); //! //! println!("{}", hex_string); // Prints "48656c6c6f20776f726c6421" //! //! # assert_eq!(hex_string, "48656c6c6f20776f726c6421"); //! ```
/// Encoding values as hex string. /// /// This trait is implemented for all `T` which implement `AsRef<[u8]>`. This /// includes `String`, `str`, `Vec<u8>` and `[u8]`. /// /// # Example /// /// ``` /// use hex::ToHex; /// /// println!("{}", "Hello world!".encode_hex::<String>()); /// # assert_eq!("Hello world!".encode_hex::<String>(), "48656c6c6f20776f726c6421".to_string()); /// ``` /// /// *Note*: instead of using this trait, you might want to use [`encode()`]. pubtrait ToHex { /// Encode the hex strict representing `self` into the result. Lower case /// letters are used (e.g. `f9b4ca`) fn encode_hex<T: iter::FromIterator<char>>(&self) -> T;
/// Encode the hex strict representing `self` into the result. Upper case /// letters are used (e.g. `F9B4CA`) fn encode_hex_upper<T: iter::FromIterator<char>>(&self) -> T;
}
impl<T: AsRef<[u8]>> ToHex for T { fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
encode_to_iter(HEX_CHARS_LOWER, self.as_ref())
}
fn encode_hex_upper<U: iter::FromIterator<char>>(&self) -> U {
encode_to_iter(HEX_CHARS_UPPER, self.as_ref())
}
}
/// Types that can be decoded from a hex string. /// /// This trait is implemented for `Vec<u8>` and small `u8`-arrays. /// /// # Example /// /// ``` /// use core::str; /// use hex::FromHex; /// /// let buffer = <[u8; 12]>::from_hex("48656c6c6f20776f726c6421")?; /// let string = str::from_utf8(&buffer).expect("invalid buffer length"); /// /// println!("{}", string); // prints "Hello world!" /// # assert_eq!("Hello world!", string); /// # Ok::<(), hex::FromHexError>(()) /// ``` pubtrait FromHex: Sized { type Error;
/// Creates an instance of type `Self` from the given hex string, or fails /// with a custom error type. /// /// Both, upper and lower case characters are valid and can even be /// mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error>;
}
// Helper macro to implement the trait for a few fixed sized arrays. Once Rust // has type level integers, this should be removed.
macro_rules! from_hex_array_impl {
($($len:expr)+) => {$( impl FromHex for [u8; $len] { type Error = FromHexError;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> { letmut out = [0_u8; $len];
decode_to_slice(hex, &mut out as &mut [u8])?;
Ok(out)
}
}
)+}
}
/// Encodes `data` as hex string using lowercase characters. /// /// Lowercase characters are used (e.g. `f9b4ca`). The resulting string's /// length is always even, each byte in `data` is always encoded using two hex /// digits. Thus, the resulting string contains exactly twice as many bytes as /// the input data. /// /// # Example /// /// ``` /// assert_eq!(hex::encode("Hello world!"), "48656c6c6f20776f726c6421"); /// assert_eq!(hex::encode(vec![1, 2, 3, 15, 16]), "0102030f10"); /// ``` #[must_use] #[cfg(feature = "alloc")] pubfn encode<T: AsRef<[u8]>>(data: T) -> String {
data.encode_hex()
}
/// Encodes `data` as hex string using uppercase characters. /// /// Apart from the characters' casing, this works exactly like `encode()`. /// /// # Example /// /// ``` /// assert_eq!(hex::encode_upper("Hello world!"), "48656C6C6F20776F726C6421"); /// assert_eq!(hex::encode_upper(vec![1, 2, 3, 15, 16]), "0102030F10"); /// ``` #[must_use] #[cfg(feature = "alloc")] pubfn encode_upper<T: AsRef<[u8]>>(data: T) -> String {
data.encode_hex_upper()
}
/// Decodes a hex string into raw bytes. /// /// Both, upper and lower case characters are valid in the input string and can /// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). /// /// # Example /// /// ``` /// assert_eq!( /// hex::decode("48656c6c6f20776f726c6421"), /// Ok("Hello world!".to_owned().into_bytes()) /// ); /// /// assert_eq!(hex::decode("123"), Err(hex::FromHexError::OddLength)); /// assert!(hex::decode("foo").is_err()); /// ``` #[cfg(feature = "alloc")] pubfn decode<T: AsRef<[u8]>>(data: T) -> Result<Vec<u8>, FromHexError> {
FromHex::from_hex(data)
}
/// Decode a hex string into a mutable bytes slice. /// /// Both, upper and lower case characters are valid in the input string and can /// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). /// /// # Example /// /// ``` /// let mut bytes = [0u8; 4]; /// assert_eq!(hex::decode_to_slice("6b697769", &mut bytes as &mut [u8]), Ok(())); /// assert_eq!(&bytes, b"kiwi"); /// ``` pubfn decode_to_slice<T: AsRef<[u8]>>(data: T, out: &mut [u8]) -> Result<(), FromHexError> { let data = data.as_ref();
if data.len() % 2 != 0 { return Err(FromHexError::OddLength);
} if data.len() / 2 != out.len() { return Err(FromHexError::InvalidStringLength);
}
for (i, byte) in out.iter_mut().enumerate() {
*byte = val(data[2 * i], 2 * i)? << 4 | val(data[2 * i + 1], 2 * i + 1)?;
}
// the inverse of `val`. #[inline] #[must_use] fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) { let high = table[((byte & 0xf0) >> 4) as usize]; let low = table[(byte & 0x0f) as usize];
(high, low)
}
/// Encodes some bytes into a mutable slice of bytes. /// /// The output buffer, has to be able to hold at least `input.len() * 2` bytes, /// otherwise this function will return an error. /// /// # Example /// /// ``` /// # use hex::FromHexError; /// # fn main() -> Result<(), FromHexError> { /// let mut bytes = [0u8; 4 * 2]; /// /// hex::encode_to_slice(b"kiwi", &mut bytes)?; /// assert_eq!(&bytes, b"6b697769"); /// # Ok(()) /// # } /// ``` pubfn encode_to_slice<T: AsRef<[u8]>>(input: T, output: &mut [u8]) -> Result<(), FromHexError> { if input.as_ref().len() * 2 != output.len() { return Err(FromHexError::InvalidStringLength);
}
for (byte, (i, j)) in input
.as_ref()
.iter()
.zip(generate_iter(input.as_ref().len() * 2))
{ let (high, low) = byte2hex(*byte, HEX_CHARS_LOWER);
output[i] = high;
output[j] = low;
}
Ok(())
}
#[cfg(test)] mod test { usesuper::*; #[cfg(feature = "alloc")] use alloc::string::ToString; use pretty_assertions::assert_eq;
#[test] #[cfg(feature = "alloc")] fn test_gen_iter() { let result = vec![(0, 1), (2, 3)];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.