api_response/
meta.rs

1use std::collections::HashMap;
2
3use chrono::{DateTime, Utc};
4use getset2::Getset2;
5use serde::{Deserialize, Serialize};
6
7use crate::{MaybeString, utils::OrderedHashMap};
8
9/// Default meta type
10#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
11#[derive(Debug, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13#[non_exhaustive]
14pub struct DefaultMeta {
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub request_id: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub user: Option<UserMeta>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub pagination: Option<Pagination>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub rate_limit: Option<RateLimit>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub cost: Option<Cost>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub api_version: Option<String>,
27    #[serde(skip_serializing_if = "HashMap::is_empty", default)]
28    custom: OrderedHashMap<String, String>,
29}
30
31/// The user's permission information and so on.
32#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
33#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35#[getset2(get_ref, set_with)]
36#[non_exhaustive]
37pub struct UserMeta {
38    pub id: String,
39    pub roles: Vec<String>,
40}
41
42/// Pagination information.
43#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
44#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46#[getset2(get_ref(pub), set_with(pub))]
47#[non_exhaustive]
48pub struct Pagination {
49    pub current_page: u32,
50    pub page_size: u32,
51    pub total_pages: u32,
52    pub total_records: u32,
53    pub next_page: Option<u32>,
54    pub prev_page: Option<u32>,
55}
56
57/// Rate limiting information.
58#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
59#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
60#[serde(rename_all = "camelCase")]
61#[getset2(set_with)]
62#[non_exhaustive]
63pub struct RateLimit {
64    pub limit: i32,
65    pub remaining: i32,
66    pub restore_rate: i32,
67    pub reset_at: Option<DateTime<Utc>>,
68}
69
70/// Cost and cost statistics.
71#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
72#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
73#[serde(rename_all = "camelCase")]
74#[getset2(set_with)]
75#[non_exhaustive]
76pub struct Cost {
77    pub actual_cost: u32,
78    pub requested_query_cost: u32,
79    pub execution_time: Option<DateTime<Utc>>,
80}
81
82impl Default for DefaultMeta {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88impl DefaultMeta {
89    #[inline(always)]
90    pub fn new() -> Self {
91        Self {
92            request_id: None,
93            user: None,
94            pagination: None,
95            rate_limit: None,
96            cost: None,
97            api_version: None,
98            custom: OrderedHashMap::default(),
99        }
100    }
101    #[inline(always)]
102    pub fn with_request_id(mut self, request_id: impl Into<MaybeString>) -> Self {
103        self.request_id = request_id.into().option_string();
104        self
105    }
106    #[inline(always)]
107    pub fn with_user(mut self, user: Option<UserMeta>) -> Self {
108        self.user = user;
109        self
110    }
111    #[inline(always)]
112    pub const fn with_pagination(mut self, pagination: Option<Pagination>) -> Self {
113        self.pagination = pagination;
114        self
115    }
116    #[inline(always)]
117    pub const fn with_rate_limit(mut self, rate_limit: Option<RateLimit>) -> Self {
118        self.rate_limit = rate_limit;
119        self
120    }
121    #[inline(always)]
122    pub const fn with_cost(mut self, cost: Option<Cost>) -> Self {
123        self.cost = cost;
124        self
125    }
126    #[inline(always)]
127    pub fn with_api_version(mut self, api_version: impl Into<MaybeString>) -> Self {
128        self.api_version = api_version.into().option_string();
129        self
130    }
131    #[inline(always)]
132    pub fn insert_custom(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
133        self.custom.insert(key.into(), value.into());
134        self
135    }
136    #[inline]
137    pub const fn request_id(&self) -> Option<&String> {
138        self.request_id.as_ref()
139    }
140    pub const fn user(&self) -> Option<&UserMeta> {
141        self.user.as_ref()
142    }
143    pub const fn pagination(&self) -> Option<&Pagination> {
144        self.pagination.as_ref()
145    }
146    pub const fn rate_limit(&self) -> Option<&RateLimit> {
147        self.rate_limit.as_ref()
148    }
149    pub const fn cost(&self) -> Option<&Cost> {
150        self.cost.as_ref()
151    }
152    pub const fn api_version(&self) -> Option<&String> {
153        self.api_version.as_ref()
154    }
155    pub fn custom(&self) -> &HashMap<String, String> {
156        &self.custom
157    }
158    pub fn custom_kv(&self, key: impl AsRef<str>) -> Option<&String> {
159        self.custom.get(key.as_ref())
160    }
161}