#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Status {
Ok,
Cancelled,
Unknown,
InvalidArgument,
DeadlineExceeded,
NotFound,
AlreadyExists,
PermissionDenied,
ResourceExhausted,
FailedPrecondition,
Aborted,
OutOfRange,
Unimplemented,
Internal,
Unavailable,
DataLoss,
Unauthenticated,
}
impl Status {
#[must_use]
pub const fn code(self) -> u8 {
match self {
Self::Ok => 0,
Self::Cancelled => 1,
Self::Unknown => 2,
Self::InvalidArgument => 3,
Self::DeadlineExceeded => 4,
Self::NotFound => 5,
Self::AlreadyExists => 6,
Self::PermissionDenied => 7,
Self::ResourceExhausted => 8,
Self::FailedPrecondition => 9,
Self::Aborted => 10,
Self::OutOfRange => 11,
Self::Unimplemented => 12,
Self::Internal => 13,
Self::Unavailable => 14,
Self::DataLoss => 15,
Self::Unauthenticated => 16,
}
}
#[must_use]
pub const fn from_code(v: u8) -> Option<Self> {
match v {
0 => Some(Self::Ok),
1 => Some(Self::Cancelled),
2 => Some(Self::Unknown),
3 => Some(Self::InvalidArgument),
4 => Some(Self::DeadlineExceeded),
5 => Some(Self::NotFound),
6 => Some(Self::AlreadyExists),
7 => Some(Self::PermissionDenied),
8 => Some(Self::ResourceExhausted),
9 => Some(Self::FailedPrecondition),
10 => Some(Self::Aborted),
11 => Some(Self::OutOfRange),
12 => Some(Self::Unimplemented),
13 => Some(Self::Internal),
14 => Some(Self::Unavailable),
15 => Some(Self::DataLoss),
16 => Some(Self::Unauthenticated),
_ => None,
}
}
#[must_use]
pub const fn is_ok(self) -> bool {
matches!(self, Self::Ok)
}
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::Ok => "OK",
Self::Cancelled => "CANCELLED",
Self::Unknown => "UNKNOWN",
Self::InvalidArgument => "INVALID_ARGUMENT",
Self::DeadlineExceeded => "DEADLINE_EXCEEDED",
Self::NotFound => "NOT_FOUND",
Self::AlreadyExists => "ALREADY_EXISTS",
Self::PermissionDenied => "PERMISSION_DENIED",
Self::ResourceExhausted => "RESOURCE_EXHAUSTED",
Self::FailedPrecondition => "FAILED_PRECONDITION",
Self::Aborted => "ABORTED",
Self::OutOfRange => "OUT_OF_RANGE",
Self::Unimplemented => "UNIMPLEMENTED",
Self::Internal => "INTERNAL",
Self::Unavailable => "UNAVAILABLE",
Self::DataLoss => "DATA_LOSS",
Self::Unauthenticated => "UNAUTHENTICATED",
}
}
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn all_17_codes_round_trip_via_numeric() {
for n in 0..=16u8 {
let s = Status::from_code(n).expect("ok");
assert_eq!(s.code(), n);
}
}
#[test]
fn unknown_codes_yield_none() {
assert_eq!(Status::from_code(17), None);
assert_eq!(Status::from_code(255), None);
}
#[test]
fn ok_is_only_status_with_is_ok_true() {
assert!(Status::Ok.is_ok());
for n in 1..=16u8 {
let s = Status::from_code(n).unwrap_or(Status::Ok);
assert!(!s.is_ok() || s.code() == 0);
}
}
#[test]
fn well_known_codes_match_spec_values() {
assert_eq!(Status::Ok.code(), 0);
assert_eq!(Status::Cancelled.code(), 1);
assert_eq!(Status::DeadlineExceeded.code(), 4);
assert_eq!(Status::NotFound.code(), 5);
assert_eq!(Status::Unimplemented.code(), 12);
assert_eq!(Status::Unavailable.code(), 14);
assert_eq!(Status::Unauthenticated.code(), 16);
}
#[test]
fn names_use_screaming_snake_case() {
assert_eq!(Status::Ok.name(), "OK");
assert_eq!(Status::DeadlineExceeded.name(), "DEADLINE_EXCEEDED");
assert_eq!(Status::FailedPrecondition.name(), "FAILED_PRECONDITION");
}
}