1use serde::Serialize;
2use thiserror::Error;
3use utoipa::ToSchema;
4
5pub type ResultCode = u16;
6
7pub const SUCCESS: ResultCode = 200;
8pub const BAD_REQUEST: ResultCode = 400;
9pub const UNAUTHORIZED: ResultCode = 401;
10pub const FORBIDDEN: ResultCode = 403;
11pub const NOT_FOUND: ResultCode = 404;
12pub const INTERNAL_ERROR: ResultCode = 500;
13pub const SERVICE_UNAVAILABLE: ResultCode = 503;
14
15pub fn default_message(code: ResultCode) -> &'static str {
16 match code {
17 SUCCESS => "SUCCESS",
18 BAD_REQUEST => "Bad request",
19 UNAUTHORIZED => "Unauthorized",
20 FORBIDDEN => "Forbidden",
21 NOT_FOUND => "Resource not found",
22 INTERNAL_ERROR => "Server internal error, please try again later",
23 SERVICE_UNAVAILABLE => "Service unavailable",
24 _ => "Server internal error, please try again later",
25 }
26}
27
28#[derive(Clone, Debug, Serialize, ToSchema)]
29pub struct ResultObject<T> {
30 pub code: ResultCode,
32 pub data: Option<T>,
34 pub count: u64,
36 pub msg: String,
38}
39
40impl<T> ResultObject<T> {
41 pub fn success(data: T) -> Self {
42 Self {
43 code: SUCCESS,
44 data: Some(data),
45 count: 0,
46 msg: default_message(SUCCESS).to_string(),
47 }
48 }
49
50 pub fn success_with_count(data: T, count: u64) -> Self {
51 Self {
52 code: SUCCESS,
53 data: Some(data),
54 count,
55 msg: default_message(SUCCESS).to_string(),
56 }
57 }
58
59 pub fn success_with_message(data: T, msg: impl Into<String>) -> Self {
60 Self {
61 code: SUCCESS,
62 data: Some(data),
63 count: 0,
64 msg: msg.into(),
65 }
66 }
67
68 pub fn failure(error: ServiceError) -> Self {
69 Self {
70 code: error.code,
71 data: None,
72 count: 0,
73 msg: error.message,
74 }
75 }
76}
77
78#[derive(Debug, Error, Clone, ToSchema)]
79#[error("code={code}, message={message}")]
80pub struct ServiceError {
81 pub code: ResultCode,
83 pub message: String,
85}
86
87impl ServiceError {
88 pub fn new(code: ResultCode) -> Self {
89 Self {
90 code,
91 message: default_message(code).to_string(),
92 }
93 }
94
95 pub fn with_message(code: ResultCode, message: impl Into<String>) -> Self {
96 Self {
97 code,
98 message: message.into(),
99 }
100 }
101
102 pub fn bad_request(message: impl Into<String>) -> Self {
103 Self::with_message(BAD_REQUEST, message)
104 }
105
106 pub fn unauthorized(message: impl Into<String>) -> Self {
107 Self::with_message(UNAUTHORIZED, message)
108 }
109
110 pub fn forbidden(message: impl Into<String>) -> Self {
111 Self::with_message(FORBIDDEN, message)
112 }
113
114 pub fn not_found(message: impl Into<String>) -> Self {
115 Self::with_message(NOT_FOUND, message)
116 }
117
118 pub fn internal(message: impl Into<String>) -> Self {
119 Self::with_message(INTERNAL_ERROR, message)
120 }
121
122 pub fn service_unavailable(message: impl Into<String>) -> Self {
123 Self::with_message(SERVICE_UNAVAILABLE, message)
124 }
125}
126
127pub type Result<T> = std::result::Result<T, ServiceError>;
128pub type PlatformError = ServiceError;