#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[non_exhaustive]
pub enum GrpcStatus {
Ok = 0,
Cancelled = 1,
Unknown = 2,
InvalidArgument = 3,
DeadlineExceeded = 4,
NotFound = 5,
AlreadyExists = 6,
PermissionDenied = 7,
ResourceExhausted = 8,
FailedPrecondition = 9,
Aborted = 10,
OutOfRange = 11,
Unimplemented = 12,
Internal = 13,
Unavailable = 14,
DataLoss = 15,
Unauthenticated = 16,
}
impl GrpcStatus {
pub fn from_u8(v: u8) -> Self {
match v {
0 => Self::Ok,
1 => Self::Cancelled,
2 => Self::Unknown,
3 => Self::InvalidArgument,
4 => Self::DeadlineExceeded,
5 => Self::NotFound,
6 => Self::AlreadyExists,
7 => Self::PermissionDenied,
8 => Self::ResourceExhausted,
9 => Self::FailedPrecondition,
10 => Self::Aborted,
11 => Self::OutOfRange,
12 => Self::Unimplemented,
13 => Self::Internal,
14 => Self::Unavailable,
15 => Self::DataLoss,
16 => Self::Unauthenticated,
_ => Self::Unknown,
}
}
}
impl std::fmt::Display for GrpcStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Ok => write!(f, "OK"),
Self::Cancelled => write!(f, "CANCELLED"),
Self::Unknown => write!(f, "UNKNOWN"),
Self::InvalidArgument => write!(f, "INVALID_ARGUMENT"),
Self::DeadlineExceeded => write!(f, "DEADLINE_EXCEEDED"),
Self::NotFound => write!(f, "NOT_FOUND"),
Self::AlreadyExists => write!(f, "ALREADY_EXISTS"),
Self::PermissionDenied => write!(f, "PERMISSION_DENIED"),
Self::ResourceExhausted => write!(f, "RESOURCE_EXHAUSTED"),
Self::FailedPrecondition => write!(f, "FAILED_PRECONDITION"),
Self::Aborted => write!(f, "ABORTED"),
Self::OutOfRange => write!(f, "OUT_OF_RANGE"),
Self::Unimplemented => write!(f, "UNIMPLEMENTED"),
Self::Internal => write!(f, "INTERNAL"),
Self::Unavailable => write!(f, "UNAVAILABLE"),
Self::DataLoss => write!(f, "DATA_LOSS"),
Self::Unauthenticated => write!(f, "UNAUTHENTICATED"),
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum GrpcError {
H2(ringline_h2::H2Error),
InvalidMessage(String),
MaxSizeExceeded(String),
NotReady,
}
impl std::fmt::Display for GrpcError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::H2(e) => write!(f, "h2: {e}"),
Self::InvalidMessage(s) => write!(f, "invalid grpc message: {s}"),
Self::MaxSizeExceeded(s) => write!(f, "max size exceeded: {s}"),
Self::NotReady => write!(f, "connection not ready"),
}
}
}
impl std::error::Error for GrpcError {}
impl From<ringline_h2::H2Error> for GrpcError {
fn from(e: ringline_h2::H2Error) -> Self {
Self::H2(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn status_round_trip() {
for code in 0..=16u8 {
let status = GrpcStatus::from_u8(code);
assert_eq!(status as u8, code);
}
}
#[test]
fn unknown_status_code() {
assert_eq!(GrpcStatus::from_u8(99), GrpcStatus::Unknown);
assert_eq!(GrpcStatus::from_u8(255), GrpcStatus::Unknown);
}
#[test]
fn status_display() {
assert_eq!(GrpcStatus::Ok.to_string(), "OK");
assert_eq!(GrpcStatus::Internal.to_string(), "INTERNAL");
assert_eq!(GrpcStatus::Unauthenticated.to_string(), "UNAUTHENTICATED");
}
#[test]
fn error_display() {
let err = GrpcError::NotReady;
assert_eq!(err.to_string(), "connection not ready");
let err = GrpcError::InvalidMessage("bad prefix".into());
assert_eq!(err.to_string(), "invalid grpc message: bad prefix");
}
}