use std::collections::HashMap;
use chrono::{DateTime, Utc};
use getset2::Getset2;
use serde::{Deserialize, Serialize};
use crate::{MaybeString, utils::OrderedHashMap};
#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct DefaultMeta {
#[serde(skip_serializing_if = "Option::is_none")]
pub request_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<UserMeta>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pagination: Option<Pagination>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rate_limit: Option<RateLimit>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cost: Option<Cost>,
#[serde(skip_serializing_if = "Option::is_none")]
pub api_version: Option<String>,
#[serde(skip_serializing_if = "HashMap::is_empty", default)]
custom: OrderedHashMap<String, String>,
}
#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[getset2(get_ref, set_with)]
#[non_exhaustive]
pub struct UserMeta {
pub id: String,
pub roles: Vec<String>,
}
#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[getset2(get_ref(pub), set_with(pub))]
#[non_exhaustive]
pub struct Pagination {
pub current_page: u32,
pub page_size: u32,
pub total_pages: u32,
pub total_records: u32,
pub next_page: Option<u32>,
pub prev_page: Option<u32>,
}
#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[getset2(set_with)]
#[non_exhaustive]
pub struct RateLimit {
pub limit: i32,
pub remaining: i32,
pub restore_rate: i32,
pub reset_at: Option<DateTime<Utc>>,
}
#[cfg_attr(feature = "salvo", derive(salvo::prelude::ToSchema))]
#[derive(Default, Getset2, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[getset2(set_with)]
#[non_exhaustive]
pub struct Cost {
pub actual_cost: u32,
pub requested_query_cost: u32,
pub execution_time: Option<DateTime<Utc>>,
}
impl Default for DefaultMeta {
fn default() -> Self {
Self::new()
}
}
impl DefaultMeta {
#[inline(always)]
pub fn new() -> Self {
Self {
request_id: None,
user: None,
pagination: None,
rate_limit: None,
cost: None,
api_version: None,
custom: OrderedHashMap::default(),
}
}
#[inline(always)]
pub fn with_request_id(mut self, request_id: impl Into<MaybeString>) -> Self {
self.request_id = request_id.into().option_string();
self
}
#[inline(always)]
pub fn with_user(mut self, user: Option<UserMeta>) -> Self {
self.user = user;
self
}
#[inline(always)]
pub const fn with_pagination(mut self, pagination: Option<Pagination>) -> Self {
self.pagination = pagination;
self
}
#[inline(always)]
pub const fn with_rate_limit(mut self, rate_limit: Option<RateLimit>) -> Self {
self.rate_limit = rate_limit;
self
}
#[inline(always)]
pub const fn with_cost(mut self, cost: Option<Cost>) -> Self {
self.cost = cost;
self
}
#[inline(always)]
pub fn with_api_version(mut self, api_version: impl Into<MaybeString>) -> Self {
self.api_version = api_version.into().option_string();
self
}
#[inline(always)]
pub fn insert_custom(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.custom.insert(key.into(), value.into());
self
}
#[inline]
pub const fn request_id(&self) -> Option<&String> {
self.request_id.as_ref()
}
pub const fn user(&self) -> Option<&UserMeta> {
self.user.as_ref()
}
pub const fn pagination(&self) -> Option<&Pagination> {
self.pagination.as_ref()
}
pub const fn rate_limit(&self) -> Option<&RateLimit> {
self.rate_limit.as_ref()
}
pub const fn cost(&self) -> Option<&Cost> {
self.cost.as_ref()
}
pub const fn api_version(&self) -> Option<&String> {
self.api_version.as_ref()
}
pub fn custom(&self) -> &HashMap<String, String> {
&self.custom
}
pub fn custom_kv(&self, key: impl AsRef<str>) -> Option<&String> {
self.custom.get(key.as_ref())
}
}