我有一些函数会在失败时返回不同的错误类型。
首先我有一个构建器,其中包含此方法:
#[derive(Debug)]
pub enum BuilderError {
ElementMissing(&'static str),
}
pub fn spawn(self) -> Result<ServiceStatus, BuilderError>
因此失败时会返回BuildError
。
现在,我有另一个函数会返回另一个错误:
#[derive(Debug)]
pub enum XmlError {
XmlCreationFailed(writer::Error),
ConversionToUtf8(FromUtf8Error),
}
pub fn create_xml(service_status: super::ServiceStatus) -> Result<String, XmlError>
我的想法是使用构建器创建一个ServiceStatus
对象,并使用它来创建一个带有create_xml
函数的XML字符串。
为此,我有这段代码:
#[derive(Debug)]
pub enum WebserviceError {
XmlError(XmlError),
BuilderError(BuilderError),
}
impl std::error::Error for WebserviceError {
...
}
impl From<XmlError> for WebserviceError {
fn from(error: XmlError) -> WebserviceError {
WebserviceError::XmlError(error)
}
}
impl From<BuilderError> for WebserviceError {
fn from(error: BuilderError) -> WebserviceError {
WebserviceError::BuilderError(error)
}
}
fn test() -> Result<String, status::WebserviceError> {
...
let service_status = builder.spawn()?;
let xml = status::create_xml(service_status)?;
Ok(xml)
}
现在,我认为我可以使用and_then
而不是使用?操作者:
fn test() -> Result<String, status::WebserviceError> {
...
builder
.spawn()
.map_err(status::WebserviceError::BuilderError)
.and_then(|hue| status::create_xml(hue).map_err(status::WebserviceError::XmlError))
}
此解决方案也有效,但现在我需要明确调用map_err
以从BuilderError
或XmlError
转换为WebserviceError
...
所以,我的问题是,我可以做得更好吗?我认为像这样的解决方案是理想的:
fn test() -> Result<String, status::WebserviceError> {
...
builder
.spawn()
.and_then(status::create_xml)
}
答案 0 :(得分:3)
经过一些试验,这是解决方案:
trait CustomAndThen<T, E> {
fn and_then2<U, E2, F: FnOnce(T) -> Result<U, E2>>(self, op: F) -> Result<U, E>
where E: std::convert::From<E2>;
}
impl<T, E> CustomAndThen<T, E> for Result<T, E> {
fn and_then2<U, E2, F: FnOnce(T) -> Result<U, E2>>(self, op: F) -> Result<U, E>
where E: std::convert::From<E2>
{
match self {
Ok(t) => op(t).map_err(From::from),
Err(e) => Err(e),
}
}
}
...
Ok(builder)
.and_then2(status::ServiceStatusBuilder::spawn)
.and_then2(status::create_xml)
这将为and_then
类型创建一个自定义Result
函数,该函数将在其中进行转换,清除代码
答案 1 :(得分:0)
如果您对精确错误并不真正感兴趣,但是最终提出了一些最终错误,则可以使用以下方法:
builder.spawn().ok()
.and_then(|v| status.create_xml(v).ok())
.ok_or_else(|| SomeError('failed to create xml'))