diff --git a/Cargo.toml b/Cargo.toml index c1e8ec9..f7856b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ license = "MIT" edition = "2018" [dependencies] +derive_builder = "0.11.2" failure = "0.1" semver = "0.11" serde = { version = "1.0", features = ["derive"] } diff --git a/src/lib.rs b/src/lib.rs index e0fa23f..aeb6776 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,9 @@ use serde::{Deserialize, Serialize}; use std::{fs::File, io::Read, path::Path, result::Result as StdResult}; +#[macro_use] +extern crate derive_builder; + pub mod error; pub mod v2; pub mod v3_0; diff --git a/src/v2/schema.rs b/src/v2/schema.rs index 374b19c..c3e0265 100644 --- a/src/v2/schema.rs +++ b/src/v2/schema.rs @@ -19,8 +19,9 @@ impl Default for Scheme { } /// top level document -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] #[serde(rename_all = "camelCase")] +#[builder(setter(into, strip_option), default)] pub struct Spec { /// The Swagger version of this document. pub swagger: String, @@ -61,8 +62,9 @@ pub struct Spec { pub external_docs: Option>, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] #[serde(rename_all = "lowercase")] +#[builder(setter(into, strip_option), default)] pub struct Tag { pub name: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -71,7 +73,8 @@ pub struct Tag { pub external_docs: Option>, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct ExternalDoc { pub url: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -81,8 +84,9 @@ pub struct ExternalDoc { /// General information about the API. /// /// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#info-object -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] #[serde(rename_all = "lowercase")] +#[builder(setter(into, strip_option), default)] pub struct Info { /// A unique and precise title of the API. #[serde(skip_serializing_if = "Option::is_none")] @@ -100,7 +104,8 @@ pub struct Info { pub version: Option, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Contact { #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, @@ -113,7 +118,8 @@ pub struct Contact { } /// todo x-* properties -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct License { /// The name of the license type. It's encouraged to use an OSI /// compatible license. @@ -126,7 +132,8 @@ pub struct License { } /// todo support x-* properties -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct PathItem { #[serde(skip_serializing_if = "Option::is_none")] pub get: Option, @@ -147,7 +154,8 @@ pub struct PathItem { } /// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] #[serde(rename_all = "lowercase")] pub struct Operation { #[serde(skip_serializing_if = "Option::is_none")] @@ -174,7 +182,8 @@ pub struct Operation { /// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#securityRequirementObject pub type SecurityRequirement = BTreeMap>; -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] #[serde(rename_all = "camelCase")] pub struct Parameter { pub name: String, @@ -199,7 +208,8 @@ pub struct Parameter { default: Option, } -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Response { pub description: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -308,7 +318,8 @@ pub enum Flow { /// the shape and properties of an object. /// /// This may also contain a `$ref` to another definition -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Schema { #[serde(skip_serializing_if = "Option::is_none")] /// [JSON reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) diff --git a/src/v3_0/components.rs b/src/v3_0/components.rs index 45a93d3..a722b7c 100644 --- a/src/v3_0/components.rs +++ b/src/v3_0/components.rs @@ -15,6 +15,12 @@ pub enum ObjectOrReference { }, } +pub trait OrReference { + fn or_ref(self) -> ObjectOrReference where Self: Sized { + ObjectOrReference::Object(self) + } +} + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(untagged)] pub enum BooleanObjectOrReference { @@ -32,7 +38,8 @@ pub enum BooleanObjectOrReference { /// they are explicitly referenced from properties outside the components object. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Components { /// An object to hold reusable Schema Objects. #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/v3_0/schema.rs b/src/v3_0/schema.rs index ab8ba7d..08a97ea 100644 --- a/src/v3_0/schema.rs +++ b/src/v3_0/schema.rs @@ -1,6 +1,7 @@ //! Schema specification for [OpenAPI 3.0.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md) use crate::v3_0::extension::Extensions; +use crate::v3_0::components::OrReference; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; use url::Url; @@ -24,7 +25,8 @@ impl Spec { } /// top level document -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Spec { /// This string MUST be the [semantic version number](https://semver.org/spec/v2.0.0.html) /// of the @@ -86,7 +88,8 @@ pub struct Spec { /// /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] // #[serde(rename_all = "lowercase")] pub struct Info { /// The title of the application. @@ -112,7 +115,8 @@ pub struct Info { /// Contact information for the exposed API. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Contact { #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, @@ -130,7 +134,8 @@ pub struct Contact { /// License information for the exposed API. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct License { /// The license name used for the API. pub name: String, @@ -144,7 +149,8 @@ pub struct License { /// An object representing a Server. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Server { /// A URL to the target host. This URL supports Server Variables and MAY be relative, to /// indicate that the host location is relative to the location where the OpenAPI document @@ -163,7 +169,8 @@ pub struct Server { /// An object representing a Server Variable for server URL template substitution. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct ServerVariable { /// The default value to use for substitution, and to send, if an alternate value is not /// supplied. Unlike the Schema Object's default, this value MUST be provided by the consumer. @@ -186,7 +193,8 @@ pub struct ServerVariable { /// constraints](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#securityFiltering). /// The path itself is still exposed to the documentation viewer but they will not know which /// operations and parameters are available. -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct PathItem { /// Allows for an external definition of this path item. The referenced structure MUST be /// in the format of a @@ -253,7 +261,8 @@ pub struct PathItem { /// Describes a single API operation on a path. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] // #[serde(rename_all = "lowercase")] pub struct Operation { /// A list of tags for API documentation control. Tags can be used for logical grouping of @@ -352,7 +361,8 @@ pub struct Operation { /// and [location](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#parameterIn). /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Parameter { /// The name of the parameter. pub name: String, @@ -398,9 +408,11 @@ pub struct Parameter { style: Option, } +impl OrReference for Parameter {} + #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] -enum ParameterStyle { +pub enum ParameterStyle { Matrix, Label, Form, @@ -421,7 +433,8 @@ enum ParameterStyle { /// Unless stated otherwise, the property definitions follow the JSON Schema. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Schema { /// [JSON reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) /// path to another definition @@ -540,8 +553,11 @@ pub struct Schema { /// of the schema if one is not provided. Unlike JSON Schema, the value MUST conform to the /// defined type for the Schema Object defined at the same level. For example, if type is /// `string`, then `default` can be `"foo"` but cannot be `1`. - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, + #[serde( + skip_serializing_if = "Option::is_none", + rename = "default" + )] + pub default_value: Option, /// Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard /// JSON Schema. @@ -572,11 +588,14 @@ pub struct Schema { pub extensions: HashMap, } +impl OrReference for Schema {} + /// Describes a single response from an API Operation, including design-time, static `links` /// to operations based on the response. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Response { /// A short description of the response. /// [CommonMark syntax](http://spec.commonmark.org/) MAY be used for rich text representation. @@ -614,7 +633,8 @@ pub struct Response { /// `header` (for example, [`style`](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#parameterStyle)). /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Header { // FIXME: Is the third change properly implemented? // FIXME: Merge `ObjectOrReference
::Reference` and `ParameterOrRef::Reference` @@ -654,7 +674,8 @@ pub struct Header { /// Describes a single request body. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct RequestBody { /// A brief description of the request body. This could contain examples of use. /// [CommonMark syntax](http://spec.commonmark.org/) MAY be used for rich text representation. @@ -671,6 +692,8 @@ pub struct RequestBody { pub required: Option, } +impl OrReference for RequestBody {} + /// The Link object represents a possible design-time link for a response. /// /// The presence of a link does not guarantee the caller's ability to successfully invoke it, @@ -768,7 +791,8 @@ pub enum Link { /// Each Media Type Object provides schema and examples for the media type identified by its key. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct MediaType { /// The schema defining the type used for the request body. #[serde(skip_serializing_if = "Option::is_none")] @@ -804,7 +828,8 @@ pub enum MediaTypeExample { } /// A single encoding definition applied to a single schema property. -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Encoding { /// The Content-Type for encoding a specific property. Default value depends on the /// property type: for `string` with `format` being `binary` – `application/octet-stream`; @@ -852,7 +877,8 @@ pub struct Encoding { } /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Example { /// Short description for the example. #[serde(skip_serializing_if = "Option::is_none")] @@ -1000,7 +1026,8 @@ pub struct Callback( /// It is not mandatory to have a Tag Object per tag defined in the Operation Object instances. /// /// See . -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default, Builder)] +#[builder(setter(into, strip_option), default)] pub struct Tag { /// The name of the tag. pub name: String,