1use alloc::string::String;
4
5#[cfg(feature = "schemars")]
6use schemars::JsonSchema;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10
11#[cfg(feature = "std")]
12use std::error::Error as StdError;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17#[cfg_attr(feature = "schemars", derive(JsonSchema))]
18#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
19pub enum ErrorCode {
20 Unknown,
22 InvalidInput,
24 NotFound,
26 Conflict,
28 Timeout,
30 Unauthenticated,
32 PermissionDenied,
34 RateLimited,
36 Unavailable,
38 Internal,
40}
41
42#[derive(Debug, Error)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45#[cfg_attr(feature = "schemars", derive(JsonSchema))]
46#[error("{code:?}: {message}")]
47pub struct GreenticError {
48 pub code: ErrorCode,
50 pub message: String,
52 #[cfg(feature = "std")]
54 #[cfg_attr(feature = "serde", serde(skip, default = "default_source"))]
55 #[cfg_attr(feature = "schemars", schemars(skip))]
56 #[source]
57 source: Option<Box<dyn StdError + Send + Sync>>,
58}
59
60impl GreenticError {
61 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
63 Self {
64 code,
65 message: message.into(),
66 #[cfg(feature = "std")]
67 source: None,
68 }
69 }
70
71 #[cfg(feature = "std")]
73 pub fn with_source<E>(mut self, source: E) -> Self
74 where
75 E: StdError + Send + Sync + 'static,
76 {
77 self.source = Some(Box::new(source));
78 self
79 }
80}
81
82#[cfg(feature = "std")]
83fn default_source() -> Option<Box<dyn StdError + Send + Sync>> {
84 None
85}
86
87#[cfg(feature = "time")]
88impl From<time::error::ComponentRange> for GreenticError {
89 fn from(err: time::error::ComponentRange) -> Self {
90 Self::new(ErrorCode::InvalidInput, err.to_string())
91 }
92}
93
94#[cfg(feature = "time")]
95impl From<time::error::Parse> for GreenticError {
96 fn from(err: time::error::Parse) -> Self {
97 Self::new(ErrorCode::InvalidInput, err.to_string())
98 }
99}
100
101#[cfg(feature = "uuid")]
102impl From<uuid::Error> for GreenticError {
103 fn from(err: uuid::Error) -> Self {
104 Self::new(ErrorCode::InvalidInput, err.to_string())
105 }
106}
107
108pub type GResult<T> = core::result::Result<T, GreenticError>;