use std::io;
#[derive(Debug, thiserror::Error)]
pub enum SyncError {
#[error("{0}")]
IdentityMismatch(String),
#[error("{0}")]
ApplyInProgress(String),
#[error("{0}")]
ApplyStateRequiresRepair(String),
#[error("{0}")]
UntrustedApplyBoundary(String),
#[error("{0}")]
InvalidRequest(String),
#[error("{0}")]
CorruptState(String),
}
impl SyncError {
fn kind(&self) -> io::ErrorKind {
match self {
SyncError::IdentityMismatch(_) | SyncError::InvalidRequest(_) => {
io::ErrorKind::InvalidInput
}
SyncError::ApplyInProgress(_)
| SyncError::ApplyStateRequiresRepair(_)
| SyncError::UntrustedApplyBoundary(_)
| SyncError::CorruptState(_) => io::ErrorKind::InvalidData,
}
}
}
impl From<SyncError> for io::Error {
fn from(err: SyncError) -> io::Error {
io::Error::new(err.kind(), err)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn all_variants() -> Vec<SyncError> {
vec![
SyncError::IdentityMismatch("m".into()),
SyncError::ApplyInProgress("m".into()),
SyncError::ApplyStateRequiresRepair("m".into()),
SyncError::UntrustedApplyBoundary("m".into()),
SyncError::InvalidRequest("m".into()),
SyncError::CorruptState("m".into()),
]
}
#[test]
fn conversion_preserves_kind_and_text_and_type() {
for variant in all_variants() {
let kind = variant.kind();
let text = variant.to_string();
let io_err: io::Error = variant.into();
assert_eq!(io_err.kind(), kind);
assert_eq!(io_err.to_string(), text, "Display must not change");
assert!(
io_err
.get_ref()
.and_then(|e| e.downcast_ref::<SyncError>())
.is_some(),
"the typed error must survive the io::Error boundary"
);
}
}
#[test]
fn kinds_match_the_historical_sites() {
use io::ErrorKind::{InvalidData, InvalidInput};
let expect = [
(SyncError::IdentityMismatch("m".into()), InvalidInput),
(SyncError::ApplyInProgress("m".into()), InvalidData),
(SyncError::ApplyStateRequiresRepair("m".into()), InvalidData),
(SyncError::UntrustedApplyBoundary("m".into()), InvalidData),
(SyncError::InvalidRequest("m".into()), InvalidInput),
(SyncError::CorruptState("m".into()), InvalidData),
];
for (variant, kind) in expect {
let io_err: io::Error = variant.into();
assert_eq!(io_err.kind(), kind);
}
}
}