use std::borrow::Cow;
use schemars::JsonSchema;
use schemars::r#gen::SchemaGenerator;
use schemars::schema::InstanceType;
use schemars::schema::Metadata;
use schemars::schema::Schema;
use schemars::schema::SchemaObject;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
use time::Date;
use time::OffsetDateTime;
use time::Time;
use time::serde::format_description;
use uuid::Uuid;
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct FormErrorResponse<T> {
pub result: ErrorConstant,
pub error: T,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, JsonSchema)]
#[allow(missing_docs)]
pub enum ErrorConstant {
#[default]
Err,
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct ApiErrorResponse {
#[cfg(feature = "opentelemetry")]
pub trace_id: String,
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema)]
pub enum Never {}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema)]
pub struct SingleUuid {
#[allow(missing_docs)]
pub uuid: Uuid,
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct SingleLink {
#[allow(missing_docs)]
pub link: String,
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema)]
pub struct Optional<T> {
#[allow(missing_docs)]
pub optional: Option<T>,
}
impl<T> Optional<T> {
pub fn some(value: T) -> Self {
Self {
optional: Some(value),
}
}
pub fn none() -> Self {
Self { optional: None }
}
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct List<T> {
#[allow(missing_docs)]
pub list: Vec<T>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct GetPageRequest {
pub limit: u64,
pub offset: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct Page<T> {
pub items: Vec<T>,
pub limit: u64,
pub offset: u64,
pub total: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(tag = "result")]
#[allow(missing_docs)]
pub enum FormResult<T, E> {
Ok { value: T },
Err { error: E },
}
impl<T, E> FormResult<T, E> {
pub fn ok(value: T) -> Self {
Self::Ok { value }
}
pub fn err(error: E) -> Self {
Self::Err { error }
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct SchemaString<T>(pub T);
impl<T> JsonSchema for SchemaString<T> {
fn is_referenceable() -> bool {
<String as JsonSchema>::is_referenceable()
}
fn schema_name() -> String {
<String as JsonSchema>::schema_name()
}
fn schema_id() -> Cow<'static, str> {
<String as JsonSchema>::schema_id()
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
<String as JsonSchema>::json_schema(generator)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct SchemaDateTime(#[serde(with = "time::serde::rfc3339")] pub OffsetDateTime);
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct SchemaTime(pub Time);
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct SchemaDate(#[serde(with = "rfc3339_date")] pub Date);
macro_rules! formatted_string_impl {
($ty:ident, format: $format:literal, example: $example:literal) => {
impl JsonSchema for $ty {
fn is_referenceable() -> bool {
true
}
fn schema_name() -> String {
stringify!($ty).to_owned()
}
fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!($ty))
}
fn json_schema(_: &mut SchemaGenerator) -> Schema {
SchemaObject {
instance_type: Some(InstanceType::String.into()),
format: Some($format.to_owned()),
metadata: Some(Box::new(Metadata {
examples: vec![json!($example)],
..Default::default()
})),
..Default::default()
}
.into()
}
}
};
}
formatted_string_impl!(SchemaDateTime, format: "date-time", example: "1970-01-01T00:00:00.0Z");
formatted_string_impl!(SchemaTime, format: "partial-date-time", example: "00:00:00.0");
formatted_string_impl!(SchemaDate, format: "date", example: "1970-01-01");
format_description!(rfc3339_date, Date, "[year]-[month]-[day]");