gpt4 book ai didi

rust - 在 Rust 中使用以前借用的结果

转载 作者:行者123 更新时间:2023-11-29 08:34:45 25 4
gpt4 key购买 nike

<分区>

我想用之前的 Ok 的内容来增强错误消息,如果那是之前的 Result,但我没有找到明显的解决方法它。为了演示这个问题,我编写了以下函数来模拟我的问题的关键要素:

type SResult<T> = std::result::Result<T, Vec<String>>;

fn main_loop(input: impl BufRead,
mut output: impl Write,
mut outerr: impl Write) -> SResult<()> {
for (index, next_line) in input.lines().enumerate() {
let processed = process(next_line.map_err(|e| to_vec(e)), index);
match processed {
Err(ref error) if error.last().unwrap().starts_with("fatal") =>
processed.map(|_| ())?,
Err(ref error) => {
let mut error = error.to_owned();
writeln!(outerr, "Error: {}", error.pop().unwrap());
// Line contents should be printed here
while !error.is_empty() {
writeln!(outerr, "caused by: {}", error.pop().unwrap());
}
},
Ok(ref message) => writeln!(output, "{}", message).map_err(|e| to_vec(e))?
}
}
Ok(())
}

fn process(next_line: SResult<String>, index: usize) -> SResult<String> {
let result = &mut next_line.and_then(eval);
match result {
Err(ref mut error) if error.last().unwrap().starts_with("fatal") =>
chain(result, format!("fatal error at {}", index + 1)),
Err(ref mut error) =>
chain(result, format!("error at {}", index + 1)),
_ => result.to_owned()
}
}

fn eval<'a>(line: String) -> SResult<String> {
match line.as_ref() {
"first" => Err(vec!["bad line".to_owned()]),
"second" => Ok("good line".to_owned()),
_ => Err(vec!["fatal error".to_owned()])
}
}

函数to_vecchain对应于我的.into()和error-chain的.chain_err实际问题,减少依赖:

fn to_vec(error: std::io::Error) -> Vec<String> {
vec![format!("{}", error)]
}

fn chain(result: &mut SResult<String>, message: String) -> SResult<String> {
match result {
Ok(_) => result.to_owned(),
Err(ref mut error) => {
error.push(message);
Err(error.to_owned())
}
}
}

我的目标是打印您在 main_loop 函数中看到注释的实际错误行。上面的代码可以通过这个测试来测试:

#[test]
fn test_case() {
let data = ["first", "second", "third"].join("\n");
let input = Cursor::new(data);
let mut output = Vec::<u8>::with_capacity(1024);
let mut error = Vec::<u8>::with_capacity(1024);
let result = main_loop(input, &mut output, &mut error);
let output_as_text = std::str::from_utf8(&output).unwrap();
let error_as_text = std::str::from_utf8(&error).unwrap();
let mut error_message = result.unwrap_err();
error_message.reverse();
assert_eq!(output_as_text, "good line\n");
assert_eq!(error_message.join("\n"), "fatal error at 3\nfatal error");
assert_eq!(error_as_text, "Error: error at 1\ncaused by: bad line\n");
}

想要的东西将通过将最后两个断言更改为此来测试:

    assert_eq!(error_message.join("\n"), "fatal error at 3\nline: 'third'\nfatal error");
assert_eq!(error_as_text, "Error: error at 1\nline: 'first'\ncaused by: bad line\n");

请注意,因为在解码行(错误的 unicode)时可能会出错,并非所有错误都会有行,尽管它们都有 编号线。

main_loop 上打印出错误时,我尝试打印该行,并且我尝试在 process 中提取并重新使用结果。我可以将 and_then(eval) 更改为 and_then(|line| { let r = eval(line); match r/* etc */}),但那将是就像我添加行号时一样麻烦——这种麻烦反射(reflect)了错误链的问题,错误链是用于错误处理的箱子。

是否有 Ruster 老手知道的模式可以使这更简单?

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com