I need a function to check a value (type: i64).
If a value has not been exceeded then the function has to return an error.
I have to pass to the function _data_type.
How to improve this function?
fn check_integer<T, D>(value: T, _data_type: D) -> Result<(), String>
where
T: ToPrimitive + Bounded + std::cmp::PartialOrd + Copy,
D: Bounded + ToPrimitive
{
let max = D::max_value().to_u64().unwrap();
let v_u64 = value.to_u64().unwrap();
if v_u64 > max {
return Err("Overload - value is too bigger".to_string());
}
Ok(())
}
You could consider use something like TryInto to do the trick
use std::convert::TryInto;
use std::fmt;
fn check_integer<D, T>(value: T) -> Result<(), String>
where
T: TryInto<D>,
T::Error: fmt::Display,
{
value.try_into().map(|_| ()).map_err(|e| format!("{}", e))
}
fn main() {
let x = 1025;
let res = check_integer::<u8, _>(x);
println!("{:?}", res);
assert_eq!(res.is_err(), true);
let x = 255;
let res = check_integer::<u8, _>(x);
println!("{:?}", res);
assert_eq!(res.is_err(), false);
}
Err("out of range integral type conversion attempted")
Ok(())
Also, you don’t need to pass an unused argument; instead specify the type on the function call with ::<…> as shown above.
Finally, one could question your choice of API here. What’s the reason to do the check_integer test? In case it is to make sure that a conversion succeeds, better just do the conversion directly than offering the check_function separately.
Note that my code above is probably suboptimal in case the type D is more complicated, e.g. if it allocates something. In such a case there could be too much overhead – if it’s just used for simple integer type like u8 then it’s fine.
You could also use Box<dyn Error> or anyhow::Error instead of String. (Example.) Or keep the custom error type for each conversion in place (which would, for integral types from std result in a TryFromIntError).