是否有一种习惯用语/简洁的方法可以将`Result `转换为`Result `,其中
我不能使用
在我的情况下,
这会导致编译错误:
虽然这两个错误在语义上看起来相似,但我需要针对每种情况采取不同的回应方式,因此我不能将它们视为一种情况。
E2
实现了From
trait(特质) 以适应E1
?我不能使用
?
运算符因为它无法编译。在我的情况下,
E1
是ParseIntError
,而E2
是自定义的CalcPackageSizeError
错误枚举。use std::error;
use std::fmt;
use std::io;
use std::io::Read;
use std::num::ParseIntError;
#[derive(Debug)]
enum CalcPackageSizeError {
InvalidInput(&'static str),
BadNum(&'static str),
}
impl error::Error for CalcPackageSizeError {}
impl fmt::Display for CalcPackageSizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match *self {
Self::InvalidInput(err_desc) => err_desc,
Self::BadNum(err_desc) => err_desc,
}
)
}
}
impl From<ParseIntError> for CalcPackageSizeError {
fn from(_: ParseIntError) -> Self {
CalcPackageSizeError::BadNum(
"Error in calculating size of one or more of the packages involved.",
)
}
}
fn parse_comma_separated_num(num_str: &str) -> Result<usize, ParseIntError> {
num_str
.chars()
.filter(|char| *char != ',')
.collect::<String>()
.parse::<usize>()
}
fn calc_all_package_size(contents: &str) -> Result<usize, CalcPackageSizeError> {
contents
.split('\n')
.skip(2)
.map(|package_str| {
let amount_str = package_str
.split(' ')
.filter(|element| *element != "")
.nth(1);
if let Some(amt_str) = amount_str {
parse_comma_separated_num(amt_str)?
// match parse_comma_separated_num(amt_str) {
// Ok(amt) => Ok(amt),
// Err(err) => Err(From::from(err)),
// }
} else {
Err(CalcPackageSizeError::InvalidInput("Input not as expected, expected the 2nd spaces-delimited item to be the size (integer)."))
}
})
.sum()
}
fn main() {
let mut wajig_input = String::from(
"Package Size (KB) Status
=================================-==========-============
geoip-database 10,015 installed
aptitude-common 10,099 installed
ieee-data 10,137 installed
hplip-data 10,195 installed
librsvg2-2 10,412 installed
fonts-noto-color-emoji 10,610 installed",
);
// io::stdin().read_to_string(&mut wajig_input).expect("stdin io rarely fails.");
match calc_all_package_size(wajig_input.as_str()) {
Ok(total_size_in_kb) => {
let size_in_mb = total_size_in_kb as f64 / 1024.0;
println!("Total size of packages installed: {} MB", size_in_mb);
}
Err(error) => {
println!("Oops! Encountered some error while calculating packages' size.");
println!("Here's the error: \n {}", error);
println!("\n-- Gracefully exiting..");
}
}
}
这会导致编译错误:
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:59:17
|
52 | / if let Some(amt_str) = amount_str {
53 | | parse_comma_separated_num(amt_str)?
| | ----------------------------------- expected because of this
54 | | // match parse_comma_separated_num(amt_str) {
55 | | // Ok(amt) => Ok(amt),
... |
59 | | Err(CalcPackageSizeError::InvalidInput("Input not as expected, expected the 2nd spaces-delimited item to be the size (integer)."))
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found enum `Result`
60 | | }
| |_____________- `if` and `else` have incompatible types
|
= note: expected type `usize`
found enum `Result<_, CalcPackageSizeError>`
note: return type inferred to be `usize` here
--> src/main.rs:53:17
|
53 | parse_comma_separated_num(amt_str)?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
虽然这两个错误在语义上看起来相似,但我需要针对每种情况采取不同的回应方式,因此我不能将它们视为一种情况。
From <E1> for E2
,要么使用Result::map_err
。 - NetwaveOk(parse_comma_separated_num(amt_str)?)
或parse_comma_separated_num(amt_str).map_err(|e| e.into())
应该可以解决问题。 - JmbOk(x?)
版本。不过当你评论时,我已经在写map_err
版本了;-) - Shepmaster