How can I convert a hex string to a u8 slice?

Viewed 21895

I have a string that looks like this "090A0B0C" and I would like to convert it to a slice that looks something like this [9, 10, 11, 12]. How would I best go about doing that?

I don't want to convert a single hex char tuple to a single integer value. I want to convert a string consisting of multiple hex char tuples to a slice of multiple integer values.

2 Answers

You can also implement hex encoding and decoding yourself, in case you want to avoid the dependency on the hex crate:

use std::{fmt::Write, num::ParseIntError};

pub fn decode_hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
    (0..s.len())
        .step_by(2)
        .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
        .collect()
}

pub fn encode_hex(bytes: &[u8]) -> String {
    let mut s = String::with_capacity(bytes.len() * 2);
    for &b in bytes {
        write!(&mut s, "{:02x}", b).unwrap();
    }
    s
}

Note that the decode_hex() function panics if the string length is odd. I've made a version with better error handling and an optimised encoder available on the playground.

You could use the hex crate for that. The decode function looks like it does what you want:

fn main() {
    let input = "090A0B0C";

    let decoded = hex::decode(input).expect("Decoding failed");

    println!("{:?}", decoded);
}

The above will print [9, 10, 11, 12]. Note that decode returns a heap allocated Vec<u8>, if you want to decode into an array you'd want to use the decode_to_slice function

fn main() {
    let input = "090A0B0C";

    let mut decoded = [0; 4];
    hex::decode_to_slice(input, &mut decoded).expect("Decoding failed");

    println!("{:?}", decoded);
}

or the FromHex trait:

use hex::FromHex;

fn main() {
    let input = "090A0B0C";

    let decoded = <[u8; 4]>::from_hex(input).expect("Decoding failed");

    println!("{:?}", decoded);
}
Related