合并具有相同错误情况的Rust嵌套结果匹配臂

lx0bsm1f  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(113)

我尝试使用嵌套的match臂,它们都使用相同的代码处理Err情况。
这看起来相当重复,如果要做进一步的解析和解 Package ,情况会变得更糟。
有没有办法让Err用例从内臂“冒泡”到外臂,或者对多个不同的、可能嵌套的Err用例应用相同的错误处理?

pub fn get_content_length(
    headers: axum::http::HeaderMap,
) -> Result<usize, (axum::http::StatusCode, String)> {
    let content_length = match headers.get("content-length") {
        Some(header_val) => match header_val.to_str() {
            Ok(header_val) => match header_val.parse::<usize>() {
                Ok(content_length) => content_length,
                Err(e) => {
                    return Err((
                        axum::http::StatusCode::BAD_REQUEST,
                        format!("error parsing header content-length: {}", e.to_string()),
                    ))
                }
            },
            Err(e) => {
                return Err((
                    axum::http::StatusCode::BAD_REQUEST,
                    format!("error parsing header content-length: {}", e.to_string()),
                ))
            }
        },
        None => {
            return Err((
                axum::http::StatusCode::BAD_REQUEST,
                String::from("missing content-length header"),
            ))
        }
    };
    Ok(content_length)
}
v7pvogib

v7pvogib1#

你可以用if-letlet-else结构来简化你的代码。你的例子太大了,我无法展示结构的用法,抱歉。以后的MRE使用playground

pub fn get_content_length_ref(
    headers: axum::http::HeaderMap,
) -> Result<usize, (axum::http::StatusCode, String)> {
    let Some(header_val) = headers.get("content-length") else {
        return Err((
            axum::http::StatusCode::BAD_REQUEST,
            "missing content-length header".to_owned(),
        ));
    };

    let Ok(header_str) = header_val.to_str() else {
        return Err((
            axum::http::StatusCode::BAD_REQUEST,
            "error parsing header to str".to_owned(),
        ));
    };

    let Ok(header_val) = header_str.parse::<usize>() else {
        return Err((
            axum::http::StatusCode::BAD_REQUEST,
            "error parsing header to int".to_owned(),
        ));
    };

    Ok(header_val)
}

但最简单的错误方式-anyhow crate

use anyhow::Context;

pub fn get_content_length(headers: axum::http::HeaderMap) -> anyhow::Result<usize> {
    let header = headers
        .get("content-length")
        .context("missing content-length header")?;
    let header = header.to_str()?;
    Ok(header.parse::<usize>()?)
}

相关问题