1use std::fmt::{Display, Formatter};
2use std::sync::Arc;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Error {
7 Canceled,
9 DeadlineExceeded,
11}
12
13impl Error {
14 pub const fn as_str(self) -> &'static str {
15 match self {
16 Error::Canceled => "context canceled",
17 Error::DeadlineExceeded => "context deadline exceeded",
18 }
19 }
20}
21
22#[derive(Debug, Clone)]
24pub struct ContextError {
25 kind: Error,
26 cause: Option<Arc<dyn std::error::Error + Send + Sync>>,
27}
28
29impl ContextError {
30 pub const fn new(kind: Error) -> Self {
31 Self { kind, cause: None }
32 }
33
34 pub fn with_cause(
35 kind: Error,
36 cause: Option<Arc<dyn std::error::Error + Send + Sync>>,
37 ) -> Self {
38 Self { kind, cause }
39 }
40
41 pub const fn kind(&self) -> Error {
42 self.kind
43 }
44
45 pub fn cause(&self) -> Option<&Arc<dyn std::error::Error + Send + Sync>> {
46 self.cause.as_ref()
47 }
48}
49
50impl Display for ContextError {
51 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52 if let Some(cause) = &self.cause {
53 write!(f, "{}: {cause}", self.kind.as_str())
54 } else {
55 f.write_str(self.kind.as_str())
56 }
57 }
58}
59
60impl std::error::Error for ContextError {
61 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
62 self.cause
63 .as_ref()
64 .map(|c| &**c as &(dyn std::error::Error + 'static))
65 }
66}
67
68pub const CANCELLED: ContextError = ContextError::new(Error::Canceled);
70pub const DEADLINE_EXCEEDED: ContextError = ContextError::new(Error::DeadlineExceeded);
71
72impl From<Error> for ContextError {
73 fn from(kind: Error) -> Self {
74 ContextError::new(kind)
75 }
76}