#![forbid(unsafe_code)]
pub mod diagnostic;
pub mod operation;
#[cfg(any(test, feature = "proptest"))]
pub mod proptest_util;
pub mod security;
pub mod types;
pub mod value;
use serde::{Deserialize, Serialize};
pub use diagnostic::{Diagnostic, FixEdit, FixSuggestion, RelatedInfo, Severity, SpecLocation};
pub use operation::{
Body, BodyContent, Encoding, Header, HttpMethod, Operation, Parameter, ParameterStyle,
Response, ResponseStatus,
};
pub use security::{
ApiKeyLocation, ApiKeyScheme, OAuth2Flow, OAuth2FlowKind, OAuth2Scheme, SecurityRequirement,
SecurityScheme, SecuritySchemeKind,
};
pub use types::{
AdditionalProperties, ArrayConstraints, ArrayType, EnumIntType, EnumIntValue, EnumStringType,
EnumStringValue, IntKind, NamedType, ObjectConstraints, ObjectType, PrimitiveConstraints,
PrimitiveKind, PrimitiveType, Property, TypeDef, TypeRef, NULL_ID,
};
pub use types::{Discriminator, UnionKind, UnionType, UnionVariant};
pub use value::{Value, ValueRef};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Ir {
pub info: ApiInfo,
pub operations: Vec<Operation>,
pub types: Vec<NamedType>,
pub security_schemes: Vec<SecurityScheme>,
pub servers: Vec<Server>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub webhooks: Vec<Webhook>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_docs: Option<ExternalDocs>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tags: Vec<Tag>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub json_schema_dialect: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub self_url: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub values: Vec<Value>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Tag {
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_docs: Option<ExternalDocs>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kind: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExternalDocs {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub url: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Webhook {
pub name: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub operations: Vec<Operation>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Callback {
pub name: String,
pub expression: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub operation_ids: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Link {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub operation_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub operation_id: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub parameters: Vec<(String, ValueRef)>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request_body: Option<ValueRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub server: Option<Server>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct XmlObject {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prefix: Option<String>,
#[serde(default)]
pub attribute: bool,
#[serde(default)]
pub wrapped: bool,
#[serde(default)]
pub text: bool,
#[serde(default)]
pub ordered: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Example {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub value: Option<ValueRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_value: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub data_value: Option<ValueRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub serialized_value: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ApiInfo {
pub title: String,
pub version: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub terms_of_service: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contact: Option<Contact>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license_identifier: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Contact {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Server {
pub url: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub variables: Vec<(String, ServerVariable)>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ServerVariable {
pub default: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub r#enum: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extensions: Vec<(String, ValueRef)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PluginInfo {
pub name: String,
pub version: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
#[cfg(test)]
mod tests {
use super::*;
fn minimal_ir() -> Ir {
Ir {
info: ApiInfo {
title: "test".into(),
version: "0".into(),
description: None,
summary: None,
terms_of_service: None,
contact: None,
license_name: None,
license_url: None,
license_identifier: None,
extensions: vec![],
},
operations: vec![],
types: vec![],
security_schemes: vec![],
servers: vec![],
webhooks: vec![],
external_docs: None,
tags: vec![],
json_schema_dialect: None,
self_url: None,
values: vec![],
}
}
#[test]
fn json_roundtrip_minimal() {
let ir = minimal_ir();
let json = serde_json::to_string(&ir).unwrap();
let back: Ir = serde_json::from_str(&json).unwrap();
pretty_assertions::assert_eq!(ir, back);
}
}