1use crate::pagination::ResultPagination;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5#[derive(Debug, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct ApiResult<T> {
18 pub success: bool,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub data: Option<T>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub list: Option<Vec<T>>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub message: Option<String>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub code: Option<i32>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub pagination: Option<ResultPagination>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub extra: Option<Value>,
31}
32
33impl<T> ApiResult<T> {
34 pub fn value(v: T) -> Self {
36 ApiResult {
37 success: true,
38 data: Some(v),
39 list: None,
40 message: None,
41 code: None,
42 pagination: None,
43 extra: None,
44 }
45 }
46
47 pub fn list(v: Vec<T>) -> Self {
49 ApiResult {
50 success: true,
51 data: None,
52 list: Some(v),
53 message: None,
54 code: None,
55 pagination: None,
56 extra: None,
57 }
58 }
59
60 pub fn fail(message: &str) -> Self {
62 Self::failure(message)
63 }
64
65 pub fn failure(message: &str) -> Self {
67 ApiResult {
68 success: false,
69 data: None,
70 list: None,
71 message: Some(message.to_string()),
72 code: None,
73 pagination: None,
74 extra: None,
75 }
76 }
77
78 pub fn success() -> Self {
80 ApiResult {
81 success: true,
82 data: None,
83 list: None,
84 message: None,
85 code: None,
86 pagination: None,
87 extra: None,
88 }
89 }
90
91 pub fn with_extra(mut self, key: &str, value: Value) -> Self {
100 match self.extra {
101 Some(ref mut v) => {
102 v[key] = value;
103 }
104 None => {
105 let mut v = serde_json::Map::new();
106 v.insert(key.to_string(), value);
107 self.extra = Some(v.into());
108 }
109 }
110 self
111 }
112
113 pub fn with_code(mut self, code: i32) -> Self {
115 self.code = Some(code);
116 self
117 }
118
119 pub fn with_pagination(mut self, pagination: ResultPagination) -> Self {
121 self.pagination = Some(pagination);
122 self
123 }
124
125 pub fn with_message(mut self, message: &str) -> Self {
127 self.message = Some(message.to_string());
128 self
129 }
130}
131
132impl<T, E> Into<Result<ApiResult<T>, E>> for ApiResult<T> {
134 fn into(self) -> Result<ApiResult<T>, E> {
135 Ok(self)
136 }
137}
138
139pub type DefaultResult<T> = Result<T, Box<dyn std::error::Error>>;
141
142pub type AnyhowResult<T> = Result<T, anyhow::Error>;
144
145pub type EmptyResult = ApiResult<()>;