Rust,如果大量结果都正常则执行某些操作,或者返回所有错误的向量

问题描述 投票:0回答:1

我正在尝试解析一些用户输入,输入存储在一个结构中,其中有很多选项/结果(以处理用户输入之前未初始化的数据),当用户提交它时,它需要进入一个所有值都已知的结构。

我希望能够获得包含任何错误的向量,以便我可以向用户提供有关输入的所有错误(而不仅仅是第一个错误)的反馈。但是,我找不到一个好的方法来做到这一点。

struct Test {
    x: i32,
    y: String,
}

#[derive(Debug)]
enum Errors {
    OneIsNone,
    TwoIsNone,
}

我目前的做法是:

fn main() -> Result<Test, Vec<Errors>> {
    let option1 = Some(5);
    let option2 = None;

    let mut errors = Vec::new();

    let x: i32;
    match option1 {
        Some(value) => x = value,
        None => errors.push(Errors::OneIsNone),
    };

    let y: String;
    match option2 {
        Some(value) => y = value,
        None => errors.push(Errors::TwoIsNone),
    }

    if errors.len() != 0 {
        return Err(errors)
    }

    Ok(
        Test {
            x,
            y
        }
    )
}

这不起作用,因为如果代码到达

Ok
块,编译器无法告诉 x 和 y 必须初始化。

在这种情况下,我可以直接展开匹配两个结果,但对于具有大量字段的结构来说,这种方法将变得极其笨拙。

基本上我想要一种方法来获取大量结果并将它们解析为一个结构(如果它们都给出

Ok()
)或返回包含所有错误的向量,否则即如何在
中实现
unwrap_or_errors

fn main() -> Result<Test, Vec<Errors>> {
    let option1 = Some(5);
    let option2 = None;

    let mut errors = Vec::new();
    

    let x = match option1 {
        Some(val) => Ok(val),
        None => Err(Errors::OneIsNone),
    };

    let y =  match option2 {
        Some(val) => Ok(val),
        None => Err(Errors::TwoIsNone),
    };

    
    if errors.len() != 0 {
        return Err(errors)
    }

    Test::unwrap_or_errors(x, y)?
}
rust struct error-handling
1个回答
0
投票

您可以对成功案例使用元组模式匹配,对失败案例使用迭代器扁平化:

struct Test {
    x: i32,
    y: String,
}

impl Test {
    fn unwrap_or_errors(
        x: Result<i32, Errors>,
        y: Result<String, Errors>,
    ) -> Result<Self, Vec<Errors>> {
        match (x, y) {
            (Ok(x), Ok(y)) => Ok(Self { x, y }),
            (x, y) => Err([x.err(), y.err()]
                .into_iter()
                .flatten()
                .collect()),
        }
    }
}

#[derive(Debug)]
enum Errors {
    OneIsNone,
    TwoIsNone,
}

fn new() -> Result<Test, Vec<Errors>> {
    let option1 = Some(5);
    let option2 = None;

    let x = match option1 {
        Some(val) => Ok(val),
        None => Err(Errors::OneIsNone),
    };

    let y = match option2 {
        Some(val) => Ok(val),
        None => Err(Errors::TwoIsNone),
    };

    Test::unwrap_or_errors(x, y)
}
© www.soinside.com 2019 - 2024. All rights reserved.