Я пытаюсь записать обобщенную c строку в числовую функцию в Rust, где поддерживаются следующие типы: i16
, i32
, i64
, u32
, u64
, f32
и f64
. Первоначально у меня было это:
fn str_to_num<N>(s: &str, default_res: N) -> N
where
N: FromStr,
{
if let Ok(n) = N::from_str(s) {
return n;
}
default_res
}
И это работало нормально, пока меня не попросили поддержать также шестнадцатеричные строки. Поскольку мы хотим анализировать только шестнадцатеричные строки как целые числа, у меня теперь есть две версии функции:
use std::convert::TryFrom;
use std::str::FromStr;
fn str_to_num_with_hex<N>(s: &str, default_res: N) -> N
where
N: FromStr + TryFrom<u64>,
{
if s.starts_with("0x") || s.starts_with("0X") {
if let Ok(n) = u64::from_str_radix(&s[2..], 16) {
if let Ok(n) = N::try_from(n) {
return n;
}
}
}
return str_to_num(s, default_res);
}
fn str_to_num<N>(s: &str, default_res: N) -> N
where
N: FromStr,
{
if let Ok(n) = N::from_str(s) {
return n;
}
default_res
}
Однако при тестировании функции с шестнадцатеричной строкой, которая вписывается в u64
, но не в i64
Кажется, что TryFrom
и as
ведут себя по-разному. Есть ли способ достичь семантики as
в сочетании с генериками?
fn main() {
let hex = "0xB85991EE5DA2B557";
let unsigned_long: u64 = str_to_num_with_hex(hex, 0);
let signed_long: i64 = str_to_num_with_hex(hex, 0);
println!("{}", unsigned_long); // prints 13283809028865176919
println!("{}", signed_long); // prints 0
println!("{}", unsigned_long as i64); // prints -5162935044844374697
}