diff --git a/bin/rust-server-petstore.sh b/bin/rust-server-petstore.sh index e0a459d59e7..80893bd3eb8 100755 --- a/bin/rust-server-petstore.sh +++ b/bin/rust-server-petstore.sh @@ -38,4 +38,8 @@ for spec_path in modules/openapi-generator/src/test/resources/*/rust-server/* ; $@" java $JAVA_OPTS -jar $executable $args + + if [ $? -ne 0 ]; then + exit $? + fi done diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 8dde5473738..ebb9536e34c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -615,10 +615,6 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } for (CodegenParameter param : op.headerParams) { - // If a header uses UUIDs, we need to import the UUID package. - if (param.dataType.equals(uuidType)) { - additionalProperties.put("apiUsesUuid", true); - } processParam(param, op); // Give header params a name in camel case. CodegenParameters don't have a nameInCamelCase property. @@ -925,7 +921,15 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { String modelName = entry.getKey(); CodegenModel model = entry.getValue(); + if (uuidType.equals(model.dataType)) { + additionalProperties.put("apiUsesUuid", true); + } + for (CodegenProperty prop : model.vars) { + if (prop.dataType.equals(uuidType)) { + additionalProperties.put("apiUsesUuid", true); + } + String xmlName = modelXmlNames.get(prop.dataType); if (xmlName != null) { prop.vendorExtensions.put("itemXmlName", xmlName); @@ -1132,6 +1136,11 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { private void processParam(CodegenParameter param, CodegenOperation op) { String example = null; + // If a parameter uses UUIDs, we need to import the UUID package. + if (param.dataType.equals(uuidType)) { + additionalProperties.put("apiUsesUuid", true); + } + if (param.isString) { param.vendorExtensions.put("formatString", "\\\"{}\\\""); example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()"; diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index 2bd053e1b69..8dd7eea26eb 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -9,42 +9,69 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", {{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}} {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = [{{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition +{{#apiUsesUuid}} +uuid = {version = "0.5", features = ["serde", "v4"]} +{{/apiUsesUuid}} +{{#usesXml}} +# TODO: this should be updated to point at the official crate once +# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"} +{{/usesXml}} + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific +{{#usesUrlEncodedForm}}serde_urlencoded = {version = "0.5.1", optional = true}{{/usesUrlEncodedForm}} + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream -{{#usesXml}}serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}{{/usesXml}} + +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" +{{^apiUsesUuid}} +uuid = {version = "0.5", features = ["serde", "v4"]} +{{/apiUsesUuid}} + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/modules/openapi-generator/src/main/resources/rust-server/README.mustache b/modules/openapi-generator/src/main/resources/rust-server/README.mustache index 5dd9da66c19..57146ddc4ca 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/README.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/README.mustache @@ -5,22 +5,20 @@ {{/appDescription}} ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: [README]((https://openapi-generator.tech)) - API version: {{{appVersion}}} -{{^hideGenerationTimestamp}} -- Build date: {{{generatedDate}}} -{{/hideGenerationTimestamp}} -{{#infoUrl}} -For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) -{{/infoUrl}} +{{^hideGenerationTimestamp}}- Build date: {{{generatedDate}}}{{/hideGenerationTimestamp}} + +{{#infoUrl}}For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}){{/infoUrl}} This autogenerated project defines an API crate `{{{packageName}}}` which contains: * An `Api` trait defining the API in Rust. @@ -29,15 +27,17 @@ This autogenerated project defines an API crate `{{{packageName}}}` which contai * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `{{{packageName}}}`: -* The example server starts up a web server using the `{{{packageName}}}` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `{{{packageName}}}` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `{{{packageName}}}` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `{{{packageName}}}` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -52,14 +52,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ```{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} @@ -73,43 +73,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `{{{packageName}}}` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "{{{packageName}}}" ]`. -* Add `{{{packageName}}} = {version = "{{{appVersion}}}", path = "{{{packageName}}}"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `{{{packageName}}}/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp {{{packageName}}}/examples/server.rs src/main.rs -cp {{{packageName}}}/examples/server_lib/mod.rs src/lib.rs -cp {{{packageName}}}/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache index f09a9c09a6e..c15b9e32ddb 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache @@ -12,10 +12,10 @@ extern crate serde_urlencoded; {{#apiUsesMultipart}} extern crate multipart; {{/apiUsesMultipart}} - {{#apiUsesUuid}} -use uuid; +extern crate uuid; {{/apiUsesUuid}} + use hyper; use hyper::header::{Headers, ContentType}; use hyper::Uri; diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-client.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-client.mustache index 00b3ef95924..4657024c625 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-client.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-client.mustache @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server.mustache index eb68fedc54d..03b0cca619a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server.mustache @@ -20,7 +20,9 @@ extern crate futures; extern crate chrono; #[macro_use] extern crate error_chain; -{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}} +{{#apiUsesUuid}} +extern crate uuid; +{{/apiUsesUuid}} use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache index 3245228d9d1..89bf5d89224 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache @@ -6,9 +6,11 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; -{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}} use swagger; use swagger::{Has, XSpanIdString}; +{{#apiUsesUuid}} +use uuid; +{{/apiUsesUuid}} use {{{externCrateName}}}::{Api, ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, {{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache index b1c055176ff..1c3b44f4b54 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -1,40 +1,53 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}} -{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}} -extern crate futures; -extern crate chrono; + #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; +{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}} +extern crate futures; +extern crate chrono; +extern crate swagger; +{{#apiUsesUuid}} +extern crate uuid; +{{/apiUsesUuid}} + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = "{{{basePathWithoutHost}}}"; pub const API_VERSION: &'static str = "{{{appVersion}}}"; diff --git a/modules/openapi-generator/src/main/resources/rust-server/models.mustache b/modules/openapi-generator/src/main/resources/rust-server/models.mustache index 2de3e517ca3..a3c31dbb53e 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/models.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/models.mustache @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; {{#usesXml}} use serde_xml_rs; @@ -16,7 +15,9 @@ use std::collections::HashMap; use models; use swagger; use std::string::ParseError; - +{{#apiUsesUuid}} +use uuid; +{{/apiUsesUuid}} {{#models}}{{#model}} {{#description}}/// {{{description}}} @@ -25,7 +26,8 @@ use std::string::ParseError; /// which helps with FFI. #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]{{#xmlName}} +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))]{{#xmlName}} #[serde(rename = "{{{xmlName}}}")]{{/xmlName}} pub enum {{{classname}}} { {{#allowableValues}}{{#enumVars}} #[serde(rename = {{{value}}})] @@ -50,6 +52,7 @@ impl ::std::str::FromStr for {{{classname}}} { } } {{/isEnum}}{{^isEnum}}{{#dataType}}{{! newtype}}#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] {{#xmlName}}#[serde(rename = "{{{xmlName}}}")]{{/xmlName}} pub struct {{{classname}}}({{{dataType}}}); @@ -97,6 +100,7 @@ where } {{/itemXmlName}}{{/vendorExtensions}}{{! vec}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct {{{classname}}}({{#vendorExtensions}}{{#itemXmlName}}#[serde(serialize_with = "wrap_in_{{{itemXmlName}}}")]{{/itemXmlName}}{{/vendorExtensions}}Vec<{{{arrayModelType}}}>); impl ::std::convert::From> for {{{classname}}} { @@ -157,7 +161,8 @@ impl ::std::ops::DerefMut for {{{classname}}} { } } -{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]{{#xmlName}} +{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]{{#xmlName}} #[serde(rename = "{{{xmlName}}}")]{{/xmlName}} pub struct {{{classname}}} { {{#vars}}{{#description}} /// {{{description}}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache index afe2744e04d..1806ac1208b 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache @@ -8,7 +8,7 @@ extern crate mime; extern crate chrono; extern crate percent_encoding; extern crate url; -{{^apiUsesUuid}} +{{#apiUsesUuid}} extern crate uuid; {{/apiUsesUuid}} {{#apiUsesMultipart}} @@ -32,9 +32,6 @@ use serde_json; {{#usesXml}} use serde_xml_rs; {{/usesXml}} -{{#apiUsesUuid}} -use uuid; -{{/apiUsesUuid}} #[allow(unused_imports)] use std::collections::{HashMap, BTreeMap}; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml index 8f4afb08ae7..742d7fd21f8 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml @@ -7,42 +7,59 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific + + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" +uuid = {version = "0.5", features = ["serde", "v4"]} + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/samples/server/petstore/rust-server/output/multipart-v3/README.md b/samples/server/petstore/rust-server/output/multipart-v3/README.md index d9a4abd69a5..3e91d461ca3 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/README.md +++ b/samples/server/petstore/rust-server/output/multipart-v3/README.md @@ -3,10 +3,11 @@ API under test ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: @@ -14,6 +15,9 @@ To see how to make this your own, look here: - API version: 1.0.7 + + + This autogenerated project defines an API crate `multipart-v3` which contains: * An `Api` trait defining the API in Rust. * Data types representing the underlying data model. @@ -21,15 +25,17 @@ This autogenerated project defines an API crate `multipart-v3` which contains: * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `multipart-v3`: -* The example server starts up a web server using the `multipart-v3` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `multipart-v3` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `multipart-v3` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `multipart-v3` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ``` @@ -65,43 +71,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `multipart-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "multipart-v3" ]`. -* Add `multipart-v3 = {version = "1.0.7", path = "multipart-v3"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `multipart-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp multipart-v3/examples/server.rs src/main.rs -cp multipart-v3/examples/server_lib/mod.rs src/lib.rs -cp multipart-v3/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/client.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/client.rs index 0421908af77..c4dcae3ed8c 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/client.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/client.rs @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server.rs index 2bd095f7a96..e6e3506099b 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server.rs @@ -21,7 +21,6 @@ extern crate chrono; #[macro_use] extern crate error_chain; - use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; use openssl::error::ErrorStack; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server_lib/server.rs index b9488562ed3..82b6ee7938a 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server_lib/server.rs @@ -6,7 +6,6 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; - use swagger; use swagger::{Has, XSpanIdString}; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs index 8d553034d0c..4004ab61778 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs @@ -1,40 +1,50 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; - -extern crate futures; -extern crate chrono; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; + +extern crate futures; +extern crate chrono; +extern crate swagger; + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "1.0.7"; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs index a1821ae32d1..02bf593bca6 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; use serde::ser::Serializer; @@ -10,8 +9,8 @@ use swagger; use std::string::ParseError; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct MultipartRequest { #[serde(rename = "string_field")] pub string_field: String, @@ -42,6 +41,7 @@ impl MultipartRequest { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct MultipartRequestObjectField { #[serde(rename = "field_a")] pub field_a: String, diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs index fcdebca1781..ddd86a025ad 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs @@ -8,7 +8,6 @@ extern crate mime; extern crate chrono; extern crate percent_encoding; extern crate url; -extern crate uuid; extern crate multipart; use std::sync::Arc; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml index 3b00d15503a..a402ec1472c 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml @@ -7,42 +7,62 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition +uuid = {version = "0.5", features = ["serde", "v4"]} +# TODO: this should be updated to point at the official crate once +# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"} + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific + + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream -serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true} + +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/samples/server/petstore/rust-server/output/openapi-v3/README.md b/samples/server/petstore/rust-server/output/openapi-v3/README.md index 9ae32692382..41c5b72f3d6 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/README.md +++ b/samples/server/petstore/rust-server/output/openapi-v3/README.md @@ -3,10 +3,11 @@ API under test ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: @@ -14,6 +15,9 @@ To see how to make this your own, look here: - API version: 1.0.7 + + + This autogenerated project defines an API crate `openapi-v3` which contains: * An `Api` trait defining the API in Rust. * Data types representing the underlying data model. @@ -21,15 +25,17 @@ This autogenerated project defines an API crate `openapi-v3` which contains: * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `openapi-v3`: -* The example server starts up a web server using the `openapi-v3` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `openapi-v3` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `openapi-v3` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `openapi-v3` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ``` @@ -71,43 +77,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `openapi-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "openapi-v3" ]`. -* Add `openapi-v3 = {version = "1.0.7", path = "openapi-v3"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `openapi-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp openapi-v3/examples/server.rs src/main.rs -cp openapi-v3/examples/server_lib/mod.rs src/lib.rs -cp openapi-v3/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs index 35aec947f48..c40e4351e80 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server.rs index a13062a00f4..679eb81c84e 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server.rs @@ -20,7 +20,7 @@ extern crate futures; extern crate chrono; #[macro_use] extern crate error_chain; - +extern crate uuid; use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs index ed9633e9c03..63a0e16b882 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs @@ -6,9 +6,9 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; - use swagger; use swagger::{Has, XSpanIdString}; +use uuid; use openapi_v3::{Api, ApiError, RequiredOctetStreamPutResponse, diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs index 55d94240ebf..ab41852ba3c 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs @@ -6,6 +6,7 @@ extern crate openssl; extern crate mime; extern crate chrono; extern crate url; +extern crate uuid; use hyper; use hyper::header::{Headers, ContentType}; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs index 8b28ecdfc73..81ad86847b7 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs @@ -1,40 +1,51 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate serde_xml_rs; -extern crate futures; -extern crate chrono; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; +extern crate serde_xml_rs; +extern crate futures; +extern crate chrono; +extern crate swagger; +extern crate uuid; + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "1.0.7"; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs index 303637592d4..c0d6a9b6026 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; use serde_xml_rs; use serde::ser::Serializer; @@ -9,7 +8,7 @@ use std::collections::{HashMap, BTreeMap}; use models; use swagger; use std::string::ParseError; - +use uuid; // Utility function for wrapping list elements when serializing xml @@ -22,6 +21,7 @@ where } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct AnotherXmlArray(#[serde(serialize_with = "wrap_in_snake_another_xml_inner")]Vec); impl ::std::convert::From> for AnotherXmlArray { @@ -93,6 +93,7 @@ impl AnotherXmlArray { } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "snake_another_xml_inner")] pub struct AnotherXmlInner(String); @@ -140,6 +141,7 @@ impl AnotherXmlInner { /// An XML object #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "snake_another_xml_object")] pub struct AnotherXmlObject { #[serde(rename = "inner_string")] @@ -176,6 +178,7 @@ impl AnotherXmlObject { /// An XML object #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "camelDuplicateXmlObject")] pub struct DuplicateXmlObject { #[serde(rename = "inner_string")] @@ -217,6 +220,7 @@ impl DuplicateXmlObject { /// Test a model containing a UUID #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct UuidObject(uuid::Uuid); @@ -266,6 +270,7 @@ where } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct XmlArray(#[serde(serialize_with = "wrap_in_camelXmlInner")]Vec); impl ::std::convert::From> for XmlArray { @@ -337,6 +342,7 @@ impl XmlArray { } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "camelXmlInner")] pub struct XmlInner(String); @@ -384,6 +390,7 @@ impl XmlInner { /// An XML object #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "camelXmlObject")] pub struct XmlObject { #[serde(rename = "innerString")] diff --git a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml index 31607737856..aa2e7ac6abe 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml @@ -7,42 +7,59 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific + + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" +uuid = {version = "0.5", features = ["serde", "v4"]} + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/samples/server/petstore/rust-server/output/ops-v3/README.md b/samples/server/petstore/rust-server/output/ops-v3/README.md index 68b5984c610..c38c48a1648 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/README.md +++ b/samples/server/petstore/rust-server/output/ops-v3/README.md @@ -3,10 +3,11 @@ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: @@ -14,6 +15,9 @@ To see how to make this your own, look here: - API version: 0.0.1 + + + This autogenerated project defines an API crate `ops-v3` which contains: * An `Api` trait defining the API in Rust. * Data types representing the underlying data model. @@ -21,15 +25,17 @@ This autogenerated project defines an API crate `ops-v3` which contains: * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `ops-v3`: -* The example server starts up a web server using the `ops-v3` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `ops-v3` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `ops-v3` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `ops-v3` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ``` @@ -101,43 +107,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `ops-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "ops-v3" ]`. -* Add `ops-v3 = {version = "0.0.1", path = "ops-v3"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `ops-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp ops-v3/examples/server.rs src/main.rs -cp ops-v3/examples/server_lib/mod.rs src/lib.rs -cp ops-v3/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/client.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/client.rs index 1f440afafba..2cfb02dad28 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/client.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/client.rs @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server.rs index d17f981ccf0..c3b37229176 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server.rs @@ -21,7 +21,6 @@ extern crate chrono; #[macro_use] extern crate error_chain; - use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; use openssl::error::ErrorStack; diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server_lib/server.rs index b4bae26a2ce..1d493838629 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server_lib/server.rs @@ -6,7 +6,6 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; - use swagger; use swagger::{Has, XSpanIdString}; diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs index 44f00e73b1c..befc6f31595 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs @@ -1,40 +1,50 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; - -extern crate futures; -extern crate chrono; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; + +extern crate futures; +extern crate chrono; +extern crate swagger; + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "0.0.1"; diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/models.rs b/samples/server/petstore/rust-server/output/ops-v3/src/models.rs index a9cf8c096c9..22245506295 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/models.rs @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; use serde::ser::Serializer; @@ -9,4 +8,3 @@ use models; use swagger; use std::string::ParseError; - diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs index e21eeae6165..267efa7a217 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs @@ -8,7 +8,6 @@ extern crate mime; extern crate chrono; extern crate percent_encoding; extern crate url; -extern crate uuid; use std::sync::Arc; use std::marker::PhantomData; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml index ced1aff2460..eacf8e96ff4 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml @@ -7,42 +7,62 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde_urlencoded", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = ["serde_urlencoded", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition +uuid = {version = "0.5", features = ["serde", "v4"]} +# TODO: this should be updated to point at the official crate once +# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"} + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific +serde_urlencoded = {version = "0.5.1", optional = true} + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream -serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true} + +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md index 16e356dd086..66807d94320 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md @@ -3,10 +3,11 @@ This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: @@ -14,6 +15,9 @@ To see how to make this your own, look here: - API version: 1.0.0 + + + This autogenerated project defines an API crate `petstore-with-fake-endpoints-models-for-testing` which contains: * An `Api` trait defining the API in Rust. * Data types representing the underlying data model. @@ -21,15 +25,17 @@ This autogenerated project defines an API crate `petstore-with-fake-endpoints-mo * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `petstore-with-fake-endpoints-models-for-testing`: -* The example server starts up a web server using the `petstore-with-fake-endpoints-models-for-testing` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `petstore-with-fake-endpoints-models-for-testing` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `petstore-with-fake-endpoints-models-for-testing` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `petstore-with-fake-endpoints-models-for-testing` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ``` @@ -96,43 +102,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `petstore-with-fake-endpoints-models-for-testing` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "petstore-with-fake-endpoints-models-for-testing" ]`. -* Add `petstore-with-fake-endpoints-models-for-testing = {version = "1.0.0", path = "petstore-with-fake-endpoints-models-for-testing"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `petstore-with-fake-endpoints-models-for-testing/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp petstore-with-fake-endpoints-models-for-testing/examples/server.rs src/main.rs -cp petstore-with-fake-endpoints-models-for-testing/examples/server_lib/mod.rs src/lib.rs -cp petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client.rs index b5803ba34c3..bcf3e0d67d3 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client.rs @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server.rs index 0f2aba9655b..5703909c217 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server.rs @@ -20,7 +20,7 @@ extern crate futures; extern crate chrono; #[macro_use] extern crate error_chain; - +extern crate uuid; use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs index f0ee591cf95..f76a7dfa875 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs @@ -6,9 +6,9 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; - use swagger; use swagger::{Has, XSpanIdString}; +use uuid; use petstore_with_fake_endpoints_models_for_testing::{Api, ApiError, TestSpecialTagsResponse, diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs index 1f8c143d76a..14b71f70b52 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs @@ -8,6 +8,7 @@ extern crate chrono; extern crate url; extern crate serde_urlencoded; extern crate multipart; +extern crate uuid; use hyper; use hyper::header::{Headers, ContentType}; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs index 479be7ad652..12922f83ebb 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs @@ -1,40 +1,51 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate serde_xml_rs; -extern crate futures; -extern crate chrono; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; +extern crate serde_xml_rs; +extern crate futures; +extern crate chrono; +extern crate swagger; +extern crate uuid; + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = "/v2"; pub const API_VERSION: &'static str = "1.0.0"; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs index e915e0d1114..b52c13d0259 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; use serde_xml_rs; use serde::ser::Serializer; @@ -9,10 +8,11 @@ use std::collections::{HashMap, BTreeMap}; use models; use swagger; use std::string::ParseError; - +use uuid; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct AdditionalPropertiesClass { #[serde(rename = "map_property")] #[serde(skip_serializing_if="Option::is_none")] @@ -43,6 +43,7 @@ impl AdditionalPropertiesClass { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct Animal { #[serde(rename = "className")] pub class_name: String, @@ -72,6 +73,7 @@ impl Animal { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct AnimalFarm(Vec); impl ::std::convert::From> for AnimalFarm { @@ -143,6 +145,7 @@ impl AnimalFarm { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ApiResponse { #[serde(rename = "code")] #[serde(skip_serializing_if="Option::is_none")] @@ -178,6 +181,7 @@ impl ApiResponse { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ArrayOfArrayOfNumberOnly { #[serde(rename = "ArrayArrayNumber")] #[serde(skip_serializing_if="Option::is_none")] @@ -203,6 +207,7 @@ impl ArrayOfArrayOfNumberOnly { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ArrayOfNumberOnly { #[serde(rename = "ArrayNumber")] #[serde(skip_serializing_if="Option::is_none")] @@ -228,6 +233,7 @@ impl ArrayOfNumberOnly { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ArrayTest { #[serde(rename = "array_of_string")] #[serde(skip_serializing_if="Option::is_none")] @@ -269,6 +275,7 @@ impl ArrayTest { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct Capitalization { #[serde(rename = "smallCamel")] #[serde(skip_serializing_if="Option::is_none")] @@ -320,6 +327,7 @@ impl Capitalization { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct Cat { #[serde(rename = "className")] pub class_name: String, @@ -354,6 +362,7 @@ impl Cat { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct CatAllOf { #[serde(rename = "declawed")] #[serde(skip_serializing_if="Option::is_none")] @@ -379,6 +388,7 @@ impl CatAllOf { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Category")] pub struct Category { #[serde(rename = "id")] @@ -411,6 +421,7 @@ impl Category { /// Model for testing model with \"_class\" property #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ClassModel { #[serde(rename = "_class")] #[serde(skip_serializing_if="Option::is_none")] @@ -436,6 +447,7 @@ impl ClassModel { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct Client { #[serde(rename = "client")] #[serde(skip_serializing_if="Option::is_none")] @@ -461,6 +473,7 @@ impl Client { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct Dog { #[serde(rename = "className")] pub class_name: String, @@ -495,6 +508,7 @@ impl Dog { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct DogAllOf { #[serde(rename = "breed")] #[serde(skip_serializing_if="Option::is_none")] @@ -520,6 +534,7 @@ impl DogAllOf { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct EnumArrays { // Note: inline enums are not fully supported by openapi-generator #[serde(rename = "just_symbol")] @@ -562,7 +577,8 @@ impl EnumArrays { /// which helps with FFI. #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))] pub enum EnumClass { #[serde(rename = "_abc")] _ABC, @@ -604,6 +620,7 @@ impl EnumClass { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct EnumTest { // Note: inline enums are not fully supported by openapi-generator #[serde(rename = "enum_string")] @@ -652,6 +669,7 @@ impl EnumTest { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct FormatTest { #[serde(rename = "integer")] #[serde(skip_serializing_if="Option::is_none")] @@ -733,6 +751,7 @@ impl FormatTest { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct HasOnlyReadOnly { #[serde(rename = "bar")] #[serde(skip_serializing_if="Option::is_none")] @@ -763,6 +782,7 @@ impl HasOnlyReadOnly { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct List { #[serde(rename = "123-list")] #[serde(skip_serializing_if="Option::is_none")] @@ -788,6 +808,7 @@ impl List { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct MapTest { #[serde(rename = "map_map_of_string")] #[serde(skip_serializing_if="Option::is_none")] @@ -825,6 +846,7 @@ impl MapTest { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct MixedPropertiesAndAdditionalPropertiesClass { #[serde(rename = "uuid")] #[serde(skip_serializing_if="Option::is_none")] @@ -861,6 +883,7 @@ impl MixedPropertiesAndAdditionalPropertiesClass { /// Model for testing model name starting with number #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Name")] pub struct Model200Response { #[serde(rename = "name")] @@ -893,6 +916,7 @@ impl Model200Response { /// Model for testing reserved words #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Return")] pub struct ModelReturn { #[serde(rename = "return")] @@ -920,6 +944,7 @@ impl ModelReturn { /// Model for testing model name same as property name #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Name")] pub struct Name { #[serde(rename = "name")] @@ -960,6 +985,7 @@ impl Name { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct NumberOnly { #[serde(rename = "JustNumber")] #[serde(skip_serializing_if="Option::is_none")] @@ -985,6 +1011,7 @@ impl NumberOnly { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Order")] pub struct Order { #[serde(rename = "id")] @@ -1038,6 +1065,7 @@ impl Order { } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct OuterBoolean(bool); @@ -1078,6 +1106,7 @@ impl OuterBoolean { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct OuterComposite { #[serde(rename = "my_number")] #[serde(skip_serializing_if="Option::is_none")] @@ -1117,7 +1146,8 @@ impl OuterComposite { /// which helps with FFI. #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))] pub enum OuterEnum { #[serde(rename = "placed")] PLACED, @@ -1159,6 +1189,7 @@ impl OuterEnum { } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct OuterNumber(f64); @@ -1199,6 +1230,7 @@ impl OuterNumber { } #[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct OuterString(String); @@ -1245,6 +1277,7 @@ impl OuterString { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Pet")] pub struct Pet { #[serde(rename = "id")] @@ -1296,6 +1329,7 @@ impl Pet { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ReadOnlyFirst { #[serde(rename = "bar")] #[serde(skip_serializing_if="Option::is_none")] @@ -1326,6 +1360,7 @@ impl ReadOnlyFirst { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "$special[model.name]")] pub struct SpecialModelName { #[serde(rename = "$special[property.name]")] @@ -1352,6 +1387,7 @@ impl SpecialModelName { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "Tag")] pub struct Tag { #[serde(rename = "id")] @@ -1383,6 +1419,7 @@ impl Tag { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] #[serde(rename = "User")] pub struct User { #[serde(rename = "id")] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml index bfae24310b9..ebdcacacf1b 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml +++ b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml @@ -7,42 +7,59 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] -server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] +client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"] +server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"] +conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [dependencies] -# Required by example server. -# +# Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -hyper = {version = "0.11", optional = true} -hyper-tls = {version = "0.1.2", optional = true} swagger = "2" - -# Not required by example server. -# lazy_static = "0.2" log = "0.3.0" mime = "0.2.6" -multipart = {version = "0.13.3"} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +multipart = "0.13.3" serde = "1.0" serde_derive = "1.0" +serde_json = "1.0" + +# Crates included if required by the API definition + +# Common between server and client features +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +native-tls = {version = "0.1.4", optional = true} +openssl = {version = "0.9.14", optional = true} serde_ignored = {version = "0.0.4", optional = true} -serde_json = {version = "1.0", optional = true} -serde_urlencoded = {version = "0.5.1", optional = true} tokio-core = {version = "0.1.6", optional = true} +url = {version = "1.5", optional = true} + +# Client-specific + + +# Server-specific +percent-encoding = {version = "1.0.0", optional = true} +regex = {version = "0.2", optional = true} tokio-proto = {version = "0.1.1", optional = true} tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]} -url = {version = "1.5", optional = true} -uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} -# ToDo: this should be updated to point at the official crate once -# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +# Other optional crates +frunk = { version = "0.3.0", optional = true } +frunk_derives = { version = "0.3.0", optional = true } +frunk_core = { version = "0.3.0", optional = true } +frunk-enum-derive = { version = "0.2.0", optional = true } +frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" error-chain = "0.12" +uuid = {version = "0.5", features = ["serde", "v4"]} + +[[example]] +name = "client" +required-features = ["client"] + +[[example]] +name = "server" +required-features = ["server"] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/README.md b/samples/server/petstore/rust-server/output/rust-server-test/README.md index 7a1e577f2e4..3b00be8fb08 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/README.md +++ b/samples/server/petstore/rust-server/output/rust-server-test/README.md @@ -3,10 +3,11 @@ This spec is for testing rust-server-specific things ## Overview + This client/server was generated by the [openapi-generator] -(https://openapi-generator.tech) project. -By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. -- +(https://openapi-generator.tech) project. By using the +[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote +server, you can easily generate a server stub. To see how to make this your own, look here: @@ -14,6 +15,9 @@ To see how to make this your own, look here: - API version: 2.3.4 + + + This autogenerated project defines an API crate `rust-server-test` which contains: * An `Api` trait defining the API in Rust. * Data types representing the underlying data model. @@ -21,15 +25,17 @@ This autogenerated project defines an API crate `rust-server-test` which contain * A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation. It also contains an example server and client which make use of `rust-server-test`: -* The example server starts up a web server using the `rust-server-test` router, - and supplies a trivial implementation of `Api` which returns failure for every operation. -* The example client provides a CLI which lets you invoke any single operation on the - `rust-server-test` client by passing appropriate arguments on the command line. + +* The example server starts up a web server using the `rust-server-test` + router, and supplies a trivial implementation of `Api` which returns failure + for every operation. +* The example client provides a CLI which lets you invoke + any single operation on the `rust-server-test` client by passing appropriate + arguments on the command line. You can use the example server and client as a basis for your own code. See below for [more detail on implementing a server](#writing-a-server). - ## Examples Run examples with: @@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example: cargo run --example client -- --help ``` -### Running the server +### Running the example server To run the server, follow these simple steps: ``` cargo run --example server ``` -### Running a client +### Running the example client To run a client, follow one of the following simple steps: ``` @@ -69,43 +75,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam cargo run --example server -- --https ``` -This will use the keys/certificates from the examples directory. Note that the server chain is signed with -`CN=localhost`. +This will use the keys/certificates from the examples directory. Note that the +server chain is signed with `CN=localhost`. +## Using the generated library -## Writing a server +The generated library has a few optional features that can be activated through Cargo. -The server example is designed to form the basis for implementing your own server. Simply follow these steps. +* `server` + * This defaults to enabled and creates the basic skeleton of a server implementation based on hyper + * To create the server stack you'll need to provide an implementation of the API trait to provide the server function. +* `client` + * This defaults to enabled and creates the basic skeleton of a client implementation based on hyper + * The constructed client implements the API trait by making remote API call. +* `conversions` + * This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types. -* Set up a new Rust project, e.g., with `cargo init --bin`. -* Insert `rust-server-test` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "rust-server-test" ]`. -* Add `rust-server-test = {version = "2.3.4", path = "rust-server-test"}` under `[dependencies]` in the root `Cargo.toml`. -* Copy the `[dependencies]` and `[dev-dependencies]` from `rust-server-test/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section. - * Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments. - * Remove `"optional = true"` from each of these lines if present. - -Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time: -``` -cp rust-server-test/examples/server.rs src/main.rs -cp rust-server-test/examples/server_lib/mod.rs src/lib.rs -cp rust-server-test/examples/server_lib/server.rs src/server.rs -``` - -Now - -* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate. -* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment. -* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate. -* Run `cargo build` to check it builds. -* Run `cargo fmt` to reformat the code. -* Commit the result before making any further changes (lest format changes get confused with your own updates). - -Now replace the implementations in `src/server.rs` with your own code as required. - -## Updating your server to track API changes - -Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation. -Alternatively, implement the now-missing methods based on the compiler's error messages. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`. ## Documentation for API Endpoints diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/client.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/client.rs index d43e0fea7f9..8df0e5e5ebe 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/client.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/client.rs @@ -7,9 +7,9 @@ extern crate futures; #[macro_use] extern crate swagger; #[allow(unused_extern_crates)] -extern crate uuid; extern crate clap; extern crate tokio_core; +extern crate uuid; use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server.rs index ab9887d7ef0..54954f20269 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server.rs @@ -21,7 +21,6 @@ extern crate chrono; #[macro_use] extern crate error_chain; - use openssl::x509::X509_FILETYPE_PEM; use openssl::ssl::{SslAcceptorBuilder, SslMethod}; use openssl::error::ErrorStack; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server_lib/server.rs index 38aa0d05c4e..4e7c5e59254 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server_lib/server.rs @@ -6,7 +6,6 @@ use futures::{self, Future}; use chrono; use std::collections::HashMap; use std::marker::PhantomData; - use swagger; use swagger::{Has, XSpanIdString}; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs index b8d7ed225b3..75f5f8966e4 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs @@ -1,40 +1,50 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; - -extern crate futures; -extern crate chrono; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate mime; +#[macro_use] +extern crate serde_derive; -// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. #[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate hyper; - -extern crate swagger; - +#[cfg(any(feature = "client", feature = "server"))] #[macro_use] extern crate url; +// Crates for conversion support +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_derives; +#[cfg(feature = "conversion")] +#[macro_use] +extern crate frunk_enum_derive; +#[cfg(feature = "conversion")] +extern crate frunk_core; + +extern crate mime; +extern crate serde; +extern crate serde_json; + +extern crate futures; +extern crate chrono; +extern crate swagger; + use futures::Stream; use std::io::Error; #[allow(unused_imports)] use std::collections::HashMap; -pub use futures::Future; - #[cfg(any(feature = "client", feature = "server"))] mod mimetypes; +#[deprecated(note = "Import swagger-rs directly")] pub use swagger::{ApiError, ContextWrapper}; +#[deprecated(note = "Import futures directly")] +pub use futures::Future; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "2.3.4"; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs index ee9a16a375f..85910268a36 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs @@ -1,6 +1,5 @@ #![allow(unused_imports, unused_qualifications, unused_extern_crates)] extern crate chrono; -extern crate uuid; use serde::ser::Serializer; @@ -10,8 +9,8 @@ use swagger; use std::string::ParseError; - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ANullableContainer { #[serde(rename = "NullableThing")] #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] @@ -36,6 +35,7 @@ impl ANullableContainer { /// An additionalPropertiesObject #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct AdditionalPropertiesObject { } @@ -48,6 +48,7 @@ impl AdditionalPropertiesObject { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct InlineObject { #[serde(rename = "id")] pub id: String, @@ -70,6 +71,7 @@ impl InlineObject { /// An object of objects #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ObjectOfObjects { #[serde(rename = "inner")] #[serde(skip_serializing_if="Option::is_none")] @@ -87,6 +89,7 @@ impl ObjectOfObjects { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[cfg_attr(feature = "conversion", derive(LabelledGeneric))] pub struct ObjectOfObjectsInner { #[serde(rename = "required_thing")] pub required_thing: String, diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs index 0d20d4c8103..eae8b97db41 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs @@ -8,7 +8,6 @@ extern crate mime; extern crate chrono; extern crate percent_encoding; extern crate url; -extern crate uuid; use std::sync::Arc; use std::marker::PhantomData;