Rust 使用以前借用的工具会导致生锈

Rust 使用以前借用的工具会导致生锈,rust,Rust,我想用以前的Ok的内容来增强错误消息,如果这是以前的结果,但我没有找到明显的方法。为了演示这个问题,我编写了以下函数来赞扬我的问题的关键要素: type SResult<T> = std::result::Result<T, Vec<String>>; fn main_loop(input: impl BufRead, mut output: impl Write, mut outerr: impl Write

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

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()])
    }
}
我的目标是打印在
main\u循环
函数中看到注释时出现错误的实际行。上述代码可通过此测试进行测试:

#[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");
}
请注意,因为在解码行(错误的unicode)时可能会出现错误,所以并非所有错误都有行,尽管它们都有行的编号

主循环
上打印错误时,我尝试打印该行,并尝试在
过程
中提取并重新使用结果。我可以将
和_then(eval)
更改为
和_then(| line |{let r=eval(line);match r/*etc*/})
,但这和添加行号一样麻烦——这种麻烦反映了错误链的问题,板条箱用于错误处理


有没有一个老手知道的模式可以让这更简单?

只需在
中打印行,然后

let result = next_line
    .and_then(|line| {
        re_encode_json(&line, bin_queries, text_queries)
            .map_err(|e| {
                println!("Error while processing {}", line);
                e
            })
    });
或者,如果要存储该行以备以后使用:

let result = next_line
    .and_then(|line| {
        re_encode_json(&line, bin_queries, text_queries)
            .map_err(|e| { Error::with_chain (e, line) })
    });

我认为如果您可以减少代码量并使其成为一个可编译的示例,那么它将更加有用。TBF我还是不明白你想在这里实现什么。最终目标是什么?
Result::Err
中不同级别的错误类型?您希望如何使用返回的错误?它应该是
e
,而不是
Err(e)
,但这是一个我没有想到的好答案。不幸的是,这在错误的时刻打印了行,并且它不可测试。我可以创建一个新的错误来存储它并链接它,但随后我遇到了与行号链接相同的问题。
let result = next_line
    .and_then(|line| {
        re_encode_json(&line, bin_queries, text_queries)
            .map_err(|e| {
                println!("Error while processing {}", line);
                e
            })
    });
let result = next_line
    .and_then(|line| {
        re_encode_json(&line, bin_queries, text_queries)
            .map_err(|e| { Error::with_chain (e, line) })
    });