use crate::codec::CodecError;
use crate::store::StoreError;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum RefreshError {
#[error("unknown refresh token")]
Unknown,
#[error("refresh token expired")]
Expired,
#[error("replay detected; chain revoked")]
Replay,
#[error("chain revoked")]
ChainRevoked,
#[error(transparent)]
Store(#[from] StoreError),
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Codec(#[from] CodecError),
#[error(transparent)]
Store(#[from] StoreError),
#[error(transparent)]
Refresh(#[from] RefreshError),
#[error("session revoked")]
Revoked,
#[error("invalid input: {0}")]
InvalidInput(String),
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn codec_error_converts_via_from() {
let e: Error = CodecError::Malformed.into();
assert!(matches!(e, Error::Codec(CodecError::Malformed)));
}
#[test]
fn store_error_converts_via_from() {
let e: Error = StoreError::NotFound.into();
assert!(matches!(e, Error::Store(StoreError::NotFound)));
}
#[test]
fn refresh_error_converts_via_from() {
let e: Error = RefreshError::Replay.into();
assert!(matches!(e, Error::Refresh(RefreshError::Replay)));
let e: Error = RefreshError::from(StoreError::Conflict).into();
assert!(matches!(e, Error::Refresh(RefreshError::Store(StoreError::Conflict))));
}
#[test]
fn question_mark_propagates() {
fn inner() -> Result<()> {
Err(StoreError::Conflict)?
}
assert!(matches!(inner(), Err(Error::Store(StoreError::Conflict))));
}
#[test]
fn invalid_input_displays_message() {
let e = Error::InvalidInput("subject empty".into());
assert_eq!(format!("{e}"), "invalid input: subject empty");
}
#[test]
fn error_is_send_sync_static() {
fn _check<T: Send + Sync + 'static>() {}
_check::<Error>();
}
}