Skip to main content

px_types/
lib.rs

1use serde::{Deserialize, Serialize};
2
3#[must_use]
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5pub struct SingleResponse<T> {
6    pub data: T,
7    pub message: String,
8}
9
10impl<T> SingleResponse<T> {
11    pub fn new(data: T, message: impl Into<String>) -> Self {
12        Self {
13            data,
14            message: message.into(),
15        }
16    }
17}
18
19#[must_use]
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
21pub struct ListResponse<T> {
22    pub data: Vec<T>,
23    pub pagination: PaginationMeta,
24}
25
26impl<T> ListResponse<T> {
27    pub fn new(data: Vec<T>, pagination: PaginationMeta) -> Self {
28        Self { data, pagination }
29    }
30}
31
32#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
33pub struct PaginationMeta {
34    pub page: u32,
35    pub size: u32,
36    pub total: u64,
37}
38
39impl PaginationMeta {
40    pub fn new(page: u32, size: u32, total: u64) -> Self {
41        Self { page, size, total }
42    }
43}
44
45#[cfg(test)]
46#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn single_response_serializes() {
52        let r = SingleResponse::new(42_i32, "ok");
53        let json = serde_json::to_string(&r).expect("serialize");
54        assert!(json.contains("\"data\":42"));
55        assert!(json.contains("\"message\":\"ok\""));
56    }
57
58    #[test]
59    fn list_response_carries_pagination() {
60        let r = ListResponse::new(vec![1_i32, 2, 3], PaginationMeta::new(0, 3, 3));
61        assert_eq!(r.data.len(), 3);
62        assert_eq!(r.pagination.total, 3);
63    }
64}