use crate::naming::RustIdent;
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Module {
pub items: Vec<Item>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum Item {
Struct(Struct),
Enum(Enum),
Alias(Alias),
}
impl Item {
pub fn name(&self) -> &str {
let name = match self {
Item::Struct(s) => s.name.logical(),
Item::Enum(e) => e.name.logical(),
Item::Alias(a) => a.name.logical(),
};
return name;
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Struct {
pub name: RustIdent,
pub doc: Option<String>,
pub deprecated: Option<Deprecation>,
pub fields: Vec<Field>,
pub additional_properties: Option<RustType>,
pub deny_unknown_fields: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Field {
pub name: RustIdent,
pub rename: Option<String>,
pub doc: Option<String>,
pub deprecated: Option<Deprecation>,
pub ty: RustType,
pub required: bool,
pub omit_empty: Option<bool>,
pub serde_skip: bool,
pub default: Option<DefaultValue>,
pub constraints: Option<Constraints>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum Bound {
Int(i64),
Float(f64),
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Constraints {
pub pattern: Option<String>,
pub min_length: Option<usize>,
pub max_length: Option<usize>,
pub minimum: Option<Bound>,
pub maximum: Option<Bound>,
pub exclusive_minimum: bool,
pub exclusive_maximum: bool,
pub folded_minimum: bool,
pub folded_maximum: bool,
pub multiple_of: Option<Bound>,
pub min_items: Option<usize>,
pub max_items: Option<usize>,
pub unique_items: bool,
pub min_properties: Option<usize>,
pub max_properties: Option<usize>,
pub checked_as: Option<RustType>,
}
impl Constraints {
pub fn is_empty(&self) -> bool {
return *self == Self::default();
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum DefaultValue {
Str(String),
Int(i64),
UInt(u64),
Float(f64),
Bool(bool),
Variant(RustIdent),
Empty,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Enum {
pub name: RustIdent,
pub doc: Option<String>,
pub deprecated: Option<Deprecation>,
pub kind: EnumKind,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum EnumKind {
Strings(Vec<StringVariant>),
Integers {
repr: RustType,
variants: Vec<IntegerVariant>,
},
Union(Vec<UnionVariant>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct StringVariant {
pub name: RustIdent,
pub rename: Option<String>,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct IntegerVariant {
pub name: RustIdent,
pub value: i64,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnionVariant {
pub name: RustIdent,
pub ty: RustType,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Alias {
pub name: RustIdent,
pub doc: Option<String>,
pub deprecated: Option<Deprecation>,
pub ty: RustType,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Deprecation {
pub note: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ForeignDerives {
pub debug: bool,
pub clone: bool,
pub partial_eq: bool,
}
impl Default for ForeignDerives {
fn default() -> Self {
return Self {
debug: true,
clone: true,
partial_eq: true,
};
}
}
impl ForeignDerives {
pub(crate) fn is_unconstrained(self) -> bool {
return self.debug && self.clone && self.partial_eq;
}
pub(crate) fn intersect(self, other: Self) -> Self {
return Self {
debug: self.debug && other.debug,
clone: self.clone && other.clone,
partial_eq: self.partial_eq && other.partial_eq,
};
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum RustType {
Bool,
I32,
I64,
U32,
U64,
F64,
String,
Value,
Date,
DateTime,
Uuid,
Bytes,
Vec(Box<RustType>),
Map(Box<RustType>),
Option(Box<RustType>),
Boxed(Box<RustType>),
Named(String),
External { module: String, name: String },
Verbatim {
text: String,
derives: ForeignDerives,
},
}
impl RustType {
pub fn optional(self) -> RustType {
return RustType::Option(Box::new(self));
}
pub fn is_option(&self) -> bool {
return matches!(self, RustType::Option(_));
}
pub fn innermost(&self) -> &RustType {
return match self {
RustType::Option(inner) | RustType::Boxed(inner) => inner.innermost(),
other => other,
};
}
pub fn is_scalar(&self) -> bool {
return matches!(
self,
RustType::Bool
| RustType::I32
| RustType::I64
| RustType::U32
| RustType::U64
| RustType::F64
| RustType::String
);
}
pub fn label(&self) -> String {
return match self {
RustType::Bool => "bool".to_owned(),
RustType::I32 => "i32".to_owned(),
RustType::I64 => "i64".to_owned(),
RustType::U32 => "u32".to_owned(),
RustType::U64 => "u64".to_owned(),
RustType::F64 => "f64".to_owned(),
RustType::String => "String".to_owned(),
RustType::Value => "serde_json::Value".to_owned(),
RustType::Date => "chrono::NaiveDate".to_owned(),
RustType::DateTime => "chrono::DateTime<chrono::Utc>".to_owned(),
RustType::Uuid => "uuid::Uuid".to_owned(),
RustType::Bytes => "Vec<u8>".to_owned(),
RustType::Vec(inner) => format!("Vec<{}>", inner.label()),
RustType::Map(inner) => format!("std::collections::HashMap<String, {}>", inner.label()),
RustType::Option(inner) => format!("Option<{}>", inner.label()),
RustType::Boxed(inner) => format!("Box<{}>", inner.label()),
RustType::Named(name) => name.clone(),
RustType::External { module, name } => format!("{module}::{name}"),
RustType::Verbatim { text, .. } => text.clone(),
};
}
pub fn verbatim(text: impl Into<String>) -> RustType {
return RustType::Verbatim {
text: text.into(),
derives: ForeignDerives::default(),
};
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Body {
pub ty: RustType,
pub kind: BodyKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BodyKind {
Json,
Text,
Form,
Multipart,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Multipart {
pub name: RustIdent,
pub fields: Vec<MultipartField>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MultipartField {
pub wire_name: String,
pub rust_name: RustIdent,
pub ty: RustType,
pub optional: bool,
pub is_file: bool,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum RequestPayload {
Single(Body),
Multipart(Multipart),
Negotiated(NegotiatedBody),
}
#[derive(Debug, Clone, PartialEq)]
pub struct NegotiatedBody {
pub name: RustIdent,
pub variants: Vec<BodyVariant>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BodyVariant {
pub variant: RustIdent,
pub body: Body,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ResponseBody {
Single(Body),
Negotiated(NegotiatedBody),
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Service {
pub operations: Vec<Operation>,
pub security_schemes: Vec<SecurityScheme>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SecurityScheme {
pub key: String,
pub field: RustIdent,
pub kind: SecuritySchemeKind,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum SecuritySchemeKind {
HttpBearer,
HttpBasic,
ApiKeyHeader(String),
ApiKeyQuery(String),
ApiKeyCookie(String),
Unsupported(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Operation {
pub name: RustIdent,
pub response_enum: RustIdent,
pub doc: Option<String>,
pub method: String,
pub path: String,
pub path_params: Vec<Param>,
pub query: Option<Struct>,
pub headers: Option<Headers>,
pub cookies: Option<Cookies>,
pub request: Option<RequestPayload>,
pub responses: Vec<ResponseCase>,
pub security: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Param {
pub name: RustIdent,
pub ty: RustType,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Headers {
pub name: RustIdent,
pub params: Vec<HeaderParam>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct HeaderParam {
pub name: RustIdent,
pub header_name: String,
pub ty: RustType,
pub required: bool,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Cookies {
pub name: RustIdent,
pub params: Vec<CookieParam>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CookieParam {
pub name: RustIdent,
pub cookie_name: String,
pub ty: RustType,
pub required: bool,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ResponseCase {
pub variant: RustIdent,
pub status: ResponseStatus,
pub body: Option<ResponseBody>,
pub headers: Vec<ResponseHeader>,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ResponseHeader {
pub name: RustIdent,
pub header_name: String,
pub ty: RustType,
pub required: bool,
pub doc: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ResponseStatus {
Fixed(u16),
Default,
Range(u8),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrls {
pub enums: Vec<ServerUrlEnum>,
pub servers: Vec<ServerUrl>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ServerUrl {
Const(ServerUrlConst),
Builder(ServerUrlBuilder),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrlConst {
pub name: RustIdent,
pub doc: Option<String>,
pub url: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrlBuilder {
pub name: RustIdent,
pub doc: Option<String>,
pub url_template: String,
pub params: Vec<ServerUrlParam>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrlParam {
pub ident: RustIdent,
pub placeholder: String,
pub ty: ServerUrlParamType,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ServerUrlParamType {
Str,
Enum(RustIdent),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrlEnum {
pub name: RustIdent,
pub doc: Option<String>,
pub variants: Vec<ServerUrlEnumVariant>,
pub default: Option<RustIdent>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ServerUrlEnumVariant {
pub name: RustIdent,
pub value: String,
}