use crate::error::{ Error, ErrorKind, Result };
#[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation, clippy::if_same_then_else)]
pub fn int_to_usize_with_msg<T: Into<i64>>(x: T, msg: &str) -> Result<usize> {
use std::usize;
use std::mem::size_of;
let n: i64 = x.into();
if n < 0 {
Err(Error::new(ErrorKind::IntConversionUnderflow,
format!("{} ({}) is negative", msg, n)))
} else if size_of::<usize>() >= size_of::<i64>() {
Ok(n as usize)
} else if n <= usize::MAX as i64 {
Ok(n as usize)
} else {
Err(Error::new(ErrorKind::IntConversionOverflow,
format!("{} ({}) overflows `usize`", msg, n)))
}
}
#[cfg(test)]
mod tests {
use std::i64;
use super::int_to_usize_with_msg;
use crate::error::{ Error, ErrorKind, Result };
#[test]
fn int_to_usize_works() -> Result<()> {
assert!(int_to_usize_with_msg(-1, "example value")
.unwrap_err()
.to_string()
.contains("example value (-1) is negative"));
assert_eq!(
int_to_usize_with_msg(1, "example value")?,
1
);
let platform_dependent = int_to_usize_with_msg(i64::MAX, "example value");
if cfg!(target_pointer_width = "8") ||
cfg!(target_pointer_width = "16") ||
cfg!(target_pointer_width = "32")
{
assert!(platform_dependent
.unwrap_err()
.to_string()
.contains("overflows usize"));
} else if cfg!(target_pointer_width = "64")
|| cfg!(target_pointer_width = "128")
{
assert_eq!(platform_dependent?, i64::MAX as usize);
} else {
return Err(Error::new(
ErrorKind::IntConversionOverflow,
"exotic pointer width, can't assume correct result"
));
}
Ok(())
}
}