openzeppelin_relayer/models/
api_response.rs

1use serde::{Deserialize, Serialize};
2use utoipa::ToSchema;
3
4#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
5pub struct PaginationMeta {
6    pub current_page: u32,
7    pub per_page: u32,
8    pub total_items: u64,
9}
10
11#[derive(Serialize, Deserialize, ToSchema)]
12pub struct ApiResponse<T> {
13    pub success: bool,
14    pub data: Option<T>,
15    #[schema(nullable = false)]
16    pub error: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    #[schema(nullable = false)]
19    pub pagination: Option<PaginationMeta>,
20}
21
22#[allow(dead_code)]
23impl<T> ApiResponse<T> {
24    pub fn new(data: Option<T>, error: Option<String>, pagination: Option<PaginationMeta>) -> Self {
25        Self {
26            success: error.is_none(),
27            data,
28            error,
29            pagination,
30        }
31    }
32
33    pub fn success(data: T) -> Self {
34        Self {
35            success: true,
36            data: Some(data),
37            error: None,
38            pagination: None,
39        }
40    }
41
42    pub fn error(message: impl Into<String>) -> Self {
43        Self {
44            success: false,
45            data: None,
46            error: Some(message.into()),
47            pagination: None,
48        }
49    }
50
51    pub fn no_data() -> Self {
52        Self {
53            success: true,
54            data: None,
55            error: None,
56            pagination: None,
57        }
58    }
59
60    pub fn paginated(data: T, meta: PaginationMeta) -> Self {
61        Self {
62            success: true,
63            data: Some(data),
64            error: None,
65            pagination: Some(meta),
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_new_with_data() {
76        let data = "test data";
77        let response = ApiResponse::new(Some(data), None, None);
78
79        assert!(response.success);
80        assert_eq!(response.data, Some(data));
81        assert_eq!(response.error, None);
82        assert_eq!(response.pagination, None);
83    }
84
85    #[test]
86    fn test_new_with_error() {
87        let error = "test error";
88        let response: ApiResponse<()> = ApiResponse::new(None, Some(error.to_string()), None);
89
90        assert!(!response.success);
91        assert_eq!(response.data, None);
92        assert_eq!(response.error, Some(error.to_string()));
93        assert_eq!(response.pagination, None);
94    }
95
96    #[test]
97    fn test_success() {
98        let data = "test data";
99        let response = ApiResponse::success(data);
100
101        assert!(response.success);
102        assert_eq!(response.data, Some(data));
103        assert_eq!(response.error, None);
104        assert_eq!(response.pagination, None);
105    }
106
107    #[test]
108    fn test_error() {
109        let error = "test error";
110        let response: ApiResponse<()> = ApiResponse::error(error);
111
112        assert!(!response.success);
113        assert_eq!(response.data, None);
114        assert_eq!(response.error, Some(error.to_string()));
115        assert_eq!(response.pagination, None);
116    }
117
118    #[test]
119    fn test_no_data() {
120        let response: ApiResponse<String> = ApiResponse::no_data();
121
122        assert!(response.success);
123        assert_eq!(response.data, None);
124        assert_eq!(response.error, None);
125        assert_eq!(response.pagination, None);
126    }
127
128    #[test]
129    fn test_paginated() {
130        let data = "test data";
131        let pagination = PaginationMeta {
132            current_page: 1,
133            per_page: 10,
134            total_items: 100,
135        };
136
137        let response = ApiResponse::paginated(data, pagination.clone());
138
139        assert!(response.success);
140        assert_eq!(response.data, Some(data));
141        assert_eq!(response.error, None);
142        assert_eq!(response.pagination, Some(pagination));
143    }
144}