In most cases, you want to parse more than one hex byte at once. In those cases, use the hex crate.
parse this into an integer
You want to use from_str_radix. It's implemented on the integer types.
use std::i64;
fn main() {
let z = i64::from_str_radix("1f", 16);
println!("{:?}", z);
}
If your strings actually have the 0x prefix, then you will need to skip over them. The best way to do that is via trim_start_matches or strip_prefix:
use std::i64;
fn main() {
let raw = "0x1f";
let without_prefix = raw.trim_start_matches("0x");
let z = i64::from_str_radix(without_prefix, 16);
println!("{:?}", z);
}
Answer from Shepmaster on Stack OverflowIn most cases, you want to parse more than one hex byte at once. In those cases, use the hex crate.
parse this into an integer
You want to use from_str_radix. It's implemented on the integer types.
use std::i64;
fn main() {
let z = i64::from_str_radix("1f", 16);
println!("{:?}", z);
}
If your strings actually have the 0x prefix, then you will need to skip over them. The best way to do that is via trim_start_matches or strip_prefix:
use std::i64;
fn main() {
let raw = "0x1f";
let without_prefix = raw.trim_start_matches("0x");
let z = i64::from_str_radix(without_prefix, 16);
println!("{:?}", z);
}
strip_prefix was mentioned earlier, and actually isn't as much trouble to use as it might seem at a casual glance. It can be nested and does the expected thing. Playground Link
fn trimhex(s: &str) -> &str {
s.strip_prefix("0x").unwrap_or(s.strip_prefix("0X").unwrap_or(s))
}
fn main() {
println!("{}", trimhex("0123"));
println!("{}", trimhex("0x01"));
println!("{}", trimhex("0X23"));
// only the first leading 0[xX] is removed
println!("{}", trimhex("0x0x45"));
println!("{}", trimhex("0x0X67"));
println!("{}", trimhex("0X0x89"));
println!("{}", trimhex("0X0Xab"));
}
How to easily translate hex string into usize or bytes
Converting &str that contains a decimal or hex representation to a decimal in a generic way
Hex Leading 0 issue
The zeo disappears, because you reserve space for 16 hex chars only, but u require 64 hex chars. Please also verify if sha256 has can really be stored in an u64 integer!
More on reddit.comrust - How can I convert a hex string to a u8 slice? - Stack Overflow
pub fn hex_to_u64(b: &[u8]) -> Option<u64> {
let a = std::str::from_utf8(b).ok()?;
u64::from_str_radix(a, 16).ok()
}
pub fn parse_sha256_to_u64(str: &str) -> Option<[u64; 4]> {
if str.len() != 64 { return None; }
let mut out = [0u64; 4];
for (chunk, slot) in str.as_bytes().chunks(16).zip(out.iter_mut()) {
*slot = hex_to_u64(chunk)?;
}
Some(out)
}
// Impl in Struct U64;4
pub fn to_hex_string(&self) -> String{
return format!("{:016x}", ByteBuf(self.as_ref()));
}
// That's the string
let contractClientId = "02f101658f665a6e3677995a5a19f37a3f9670b75970305e898459479961249f";
// I convert it to U64;4
let contractClientId_u8 = parse_sha256_to_u64(contractClientId).unwrap();
// Now I convert it back to a String ("Hex" String)
println!("INSURANCE CLIENT ID HASH: {}", contractClientId_u8.to_hex_string());
// Result is 2f101658f665a6e3677995a5a19f37a3f9670b75970305e898459479961249fcan anyone help me fix this issue? I don't know why the 0 disappear :/
I need to do Hex (String) -> U64;4 -> Hex (String)
It needs to be 02f101658f665a6e3677995a5a19f37a3f9670b75970305e898459479961249f, not 2f101658f665a6e3677995a5a19f37a3f9670b75970305e898459479961249f
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);
}