use connectrpc::ConnectError;
mod private {
pub trait Sealed {}
impl<T, E> Sealed for Result<Option<T>, E> {}
}
pub trait ConnectOptionExt<T>: private::Sealed {
fn or_not_found(self, msg: &str) -> Result<T, ConnectError>
where
Self: Sized;
}
impl<T, E> ConnectOptionExt<T> for Result<Option<T>, E>
where
E: Into<ConnectError>,
{
fn or_not_found(self, msg: &str) -> Result<T, ConnectError> {
match self {
Ok(Some(v)) => Ok(v),
Ok(None) => Err(ConnectError::not_found(msg.to_owned())),
Err(e) => Err(e.into()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn some_returns_value() {
let res: Result<Option<u32>, ConnectError> = Ok(Some(42));
assert_eq!(res.or_not_found("gone").unwrap(), 42);
}
#[test]
fn none_returns_not_found() {
let res: Result<Option<u32>, ConnectError> = Ok(None);
let err = res.or_not_found("thing not found").unwrap_err();
let msg = format!("{err:?}");
assert!(
msg.contains("not_found")
|| msg.contains("NotFound")
|| msg.contains("thing not found")
);
}
#[test]
fn err_propagates() {
let res: Result<Option<u32>, ConnectError> = Err(ConnectError::internal("boom"));
assert!(res.or_not_found("whatever").is_err());
}
}