Como converter & char para & str em Rust [duplicado]
Dado um argumento & [char], que suponho ser um ou mais decimais em hexadecimal, estou tentando chamar from_str_radix para convertê-lo em bytes. No entanto, from_str_radix espera & str não & char. Existe uma maneira de converter cada & char em & str?
fn convertCharsToBytes(args: &[char]) -> std::vec::Vec<u8> {
let mut bytes:Vec<u8> = Vec::new();
for arg in args {
let byte = u8::from_str_radix(arg, 16); //arg here is invalid as it is a &char, not a &str
match byte {
Ok(value) => bytes.push(value),
Err(error) => {}
}
}
println!("{:?}", bytes);
return bytes;
}
Respostas
Eu acho que isso vai funcionar conforme o esperado
fn convertCharsToBytes(args: &[char]) -> std::vec::Vec<u8> {
let mut bytes:Vec<u8> = Vec::new();
for arg in args {
let byte = u8::from_str_radix(&arg.to_string(), 16);
match byte {
Ok(value) => bytes.push(value),
Err(error) => ()
}
}
println!("{:?}", bytes);
return bytes;
}
&arg.to_string() é uma fatia da string gerada que consiste em um caractere.
Você pode evitar alocações extras fazendo você mesmo a conversão:
let byte = if char > 'a' { char as u32 - 'a' as u32 }
else if char > 'A' { char as u32 - 'A' as u32 }
else { char as u32 - '0' as u32 } as u8;
Além da verificação de erros se você não puder garantir que char é um dígito hexadecimal válido.
Observe, entretanto, que isso (assim como seu código original) converterá cada caractere individualmente. Então, se você chamar com "1a", bytesconterá [0x01, 0x0a]e não [0x1a] .
Um pouco mais rápido:
fn convertCharsToBytes(args: &[char]) -> std::vec::Vec<u8> {
// E.g. 17 is encoded as 0x11 but 10 as 0x0A
// So bytes are always encoded using 2 symbols
assert_eq!(args.len()%2, 0, "Hexes length must be even!");
let mut bytes:Vec<u8> = Vec::with_capacity(args.len()/2);
// To reuse allocation instead calling to_string on every iteration
let mut string = String::new();
for &num in args.chunks_exact(2) {
// To eliminate bounds checks in indexing
// Maybe in future chunks_exact would return &[T;2] instead of &[T]
// but it is inaccessible before const generics
assert_eq!(num.len()==2);
string.clear();
string.push(num[0]);
string.push(num[1]);
let byte = u8::from_str_radix(&string, 16);
match byte {
Ok(value) => bytes.push(value),
Err(_) => panic!("Invalid hex {}!", &string),
}
}
println!("{:?}", bytes);
return bytes;
}
Ou, se você não se importa com o uso de memória extra e dependência de pull :
fn convertCharsToBytes(args: &[char]) -> std::vec::Vec<u8> {
let s: String = args.iter().collect();
let bytes = hex::decode(&s).expect("Failed to parse hex");
println!("{:?}", bytes);
return bytes;
}
UPD: Corrigido erro no primeiro código cortado (esqueci, que um byte é codificado por 1 char). Esse tipo de erro é a razão pela qual você deve usar dependência em vez de codificar a própria solução, já que o crate é testado muito melhor.