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 8d53d708fb56..bab781d13302 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 @@ -870,6 +870,16 @@ private void postProcessOperationWithModels(CodegenOperation op, List op.vendorExtensions.put("x-has-request-body", true); } + if (op.allParams.stream() + .anyMatch(p -> p.isArray && !p.isPrimitiveType)) { + op.vendorExtensions.put("x-has-borrowed-params", Boolean.TRUE); + for (CodegenParameter param : op.allParams) { + if (param.isArray) { + param.vendorExtensions.put("x-param-needs-lifetime", Boolean.TRUE); + } + } + } + // The CLI generates a structopt structure for each operation. This can only have a single // use of a short option, which comes from the parameter name, so we need to police // against duplicates 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 dab769c0ec70..a4f19971a18c 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -70,6 +70,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -87,6 +89,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache index cc87e61e036d..4a0f1ada3873 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache @@ -1,5 +1,5 @@ #[allow(clippy::vec_init_then_push)] - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#exts}} {{#x-callback-params}} @@ -7,7 +7,7 @@ {{/x-callback-params}} {{/exts}} {{#allParams}} - param_{{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + param_{{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} context: &C) -> Result<{{{operationId}}}Response, ApiError> { diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache index 0b02ea25a5a1..dfe154824b82 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache @@ -1,7 +1,7 @@ {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#exts}} {{#x-callback-params}} @@ -9,7 +9,7 @@ {{/x-callback-params}} {{/exts}} {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} context: &C) -> Result<{{{operationId}}}Response, ApiError> { 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 806bea022e74..1c5f9ca7e2ee 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -33,6 +35,7 @@ pub use auth::{AuthenticationApi, Claims}; {{/apis}} {{/apiInfo}} /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -43,10 +46,10 @@ pub trait Api { {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} context: &C) -> Result<{{{operationId}}}Response, ApiError>; @@ -57,9 +60,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; @@ -70,10 +78,10 @@ pub trait ApiNoContext { {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} ) -> Result<{{{operationId}}}Response, ApiError>; @@ -109,10 +117,10 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} ) -> Result<{{{operationId}}}Response, ApiError> { @@ -146,6 +154,7 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex {{/apiInfo}} /// Callback API +#[cfg_attr(feature = "mock", automock)] #[async_trait] pub trait CallbackApi { @@ -159,7 +168,7 @@ pub trait CallbackApi { {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#exts}} {{#x-callback-params}} @@ -167,7 +176,7 @@ pub trait CallbackApi { {{/x-callback-params}} {{/exts}} {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} context: &C) -> Result<{{{operationId}}}Response, ApiError>; @@ -181,6 +190,7 @@ pub trait CallbackApi { } /// Callback API without a `Context` +#[cfg_attr(feature = "mock", automock)] #[async_trait] pub trait CallbackApiNoContext { @@ -196,7 +206,7 @@ pub trait CallbackApiNoContext { {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#exts}} {{#x-callback-params}} @@ -204,7 +214,7 @@ pub trait CallbackApiNoContext { {{/x-callback-params}} {{/exts}} {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} ) -> Result<{{{operationId}}}Response, ApiError>; @@ -246,7 +256,7 @@ impl + Send + Sync, C: Clone + Send + Sync> CallbackApiNoConte {{#summary}} /// {{{.}}} {{/summary}} - async fn {{#exts}}{{{x-operation-id}}}{{/exts}}( + async fn {{#exts}}{{{x-operation-id}}}{{/exts}}{{#exts.x-has-borrowed-params}}<'a>{{/exts.x-has-borrowed-params}}( &self, {{#exts}} {{#x-callback-params}} @@ -254,7 +264,7 @@ impl + Send + Sync, C: Clone + Send + Sync> CallbackApiNoConte {{/x-callback-params}} {{/exts}} {{#allParams}} - {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{{dataType}}}{{^required}}>{{/required}}, + {{{paramName}}}: {{^required}}Option<{{/required}}{{#isArray}}&{{/isArray}}{{#exts.x-param-needs-lifetime}}'a {{/exts.x-param-needs-lifetime}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} ) -> Result<{{{operationId}}}Response, ApiError> { 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 67914ca651ff..6fc7852dbcaf 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml @@ -24,6 +24,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -41,6 +43,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" 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 f4d488090a01..eec859f8a4bc 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 @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -39,6 +41,7 @@ pub enum MultipleIdenticalMimeTypesPostResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -66,9 +69,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; diff --git a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml index 1e4463cc6e4c..f62eb1aec947 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml @@ -20,6 +20,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -37,6 +39,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs index 6499665e9aa3..92053dfbca3c 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -27,6 +29,7 @@ pub enum OpGetResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -38,9 +41,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; 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 2fc526d80090..a745850bf03b 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml @@ -23,6 +23,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -40,6 +42,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs index 2215f8da79a2..93926b52645d 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs @@ -176,9 +176,9 @@ use swagger::ApiError; #[async_trait] impl Api for Server where C: Has + Send + Sync { - async fn any_of_get( + async fn any_of_get<'a>( &self, - any_of: Option<&Vec>, + any_of: Option<&'a Vec>, context: &C) -> Result { info!("any_of_get({:?}) - X-Span-ID: {:?}", any_of, context.get().0.clone()); @@ -194,9 +194,9 @@ impl Api for Server where C: Has + Send + Sync Err(ApiError("Api-Error: Operation is NOT implemented".into())) } - async fn complex_query_param_get( + async fn complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, context: &C) -> Result { info!("complex_query_param_get({:?}) - X-Span-ID: {:?}", list_of_strings, context.get().0.clone()); @@ -204,9 +204,9 @@ impl Api for Server where C: Has + Send + Sync } /// Test examples - async fn examples_test( + async fn examples_test<'a>( &self, - ids: Option<&Vec>, + ids: Option<&'a Vec>, context: &C) -> Result { info!("examples_test({:?}) - X-Span-ID: {:?}", ids, context.get().0.clone()); @@ -214,9 +214,9 @@ impl Api for Server where C: Has + Send + Sync } /// Test a Form Post - async fn form_test( + async fn form_test<'a>( &self, - required_array: &Vec, + required_array: &'a Vec, enum_field: models::FormTestRequestEnumField, context: &C) -> Result { @@ -233,9 +233,9 @@ impl Api for Server where C: Has + Send + Sync Err(ApiError("Api-Error: Operation is NOT implemented".into())) } - async fn json_complex_query_param_get( + async fn json_complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, context: &C) -> Result { info!("json_complex_query_param_get({:?}) - X-Span-ID: {:?}", list_of_strings, context.get().0.clone()); 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 c02e279f086c..f10dc0d32b95 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 @@ -439,9 +439,9 @@ impl Api for Client where { #[allow(clippy::vec_init_then_push)] - async fn any_of_get( + async fn any_of_get<'a>( &self, - param_any_of: Option<&Vec>, + param_any_of: Option<&'a Vec>, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -629,9 +629,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn complex_query_param_get( + async fn complex_query_param_get<'a>( &self, - param_list_of_strings: Option<&Vec>, + param_list_of_strings: Option<&'a Vec>, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -702,9 +702,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn examples_test( + async fn examples_test<'a>( &self, - param_ids: Option<&Vec>, + param_ids: Option<&'a Vec>, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -787,9 +787,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn form_test( + async fn form_test<'a>( &self, - param_required_array: &Vec, + param_required_array: &'a Vec, param_enum_field: models::FormTestRequestEnumField, context: &C) -> Result { @@ -949,9 +949,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn json_complex_query_param_get( + async fn json_complex_query_param_get<'a>( &self, - param_list_of_strings: Option<&Vec>, + param_list_of_strings: Option<&'a Vec>, context: &C) -> Result { let mut client_service = self.client_service.clone(); 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 16e1a16f00d2..95b7cfda262b 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 @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -310,12 +312,13 @@ pub enum GetRepoInfoResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { - async fn any_of_get( + async fn any_of_get<'a>( &self, - any_of: Option<&Vec>, + any_of: Option<&'a Vec>, context: &C) -> Result; async fn callback_with_header_post( @@ -323,21 +326,21 @@ pub trait Api { url: String, context: &C) -> Result; - async fn complex_query_param_get( + async fn complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, context: &C) -> Result; /// Test examples - async fn examples_test( + async fn examples_test<'a>( &self, - ids: Option<&Vec>, + ids: Option<&'a Vec>, context: &C) -> Result; /// Test a Form Post - async fn form_test( + async fn form_test<'a>( &self, - required_array: &Vec, + required_array: &'a Vec, enum_field: models::FormTestRequestEnumField, context: &C) -> Result; @@ -346,9 +349,9 @@ pub trait Api { iambool: bool, context: &C) -> Result; - async fn json_complex_query_param_get( + async fn json_complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, context: &C) -> Result; async fn mandatory_request_header_get( @@ -472,15 +475,20 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; - async fn any_of_get( + async fn any_of_get<'a>( &self, - any_of: Option<&Vec>, + any_of: Option<&'a Vec>, ) -> Result; async fn callback_with_header_post( @@ -488,21 +496,21 @@ pub trait ApiNoContext { url: String, ) -> Result; - async fn complex_query_param_get( + async fn complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, ) -> Result; /// Test examples - async fn examples_test( + async fn examples_test<'a>( &self, - ids: Option<&Vec>, + ids: Option<&'a Vec>, ) -> Result; /// Test a Form Post - async fn form_test( + async fn form_test<'a>( &self, - required_array: &Vec, + required_array: &'a Vec, enum_field: models::FormTestRequestEnumField, ) -> Result; @@ -511,9 +519,9 @@ pub trait ApiNoContext { iambool: bool, ) -> Result; - async fn json_complex_query_param_get( + async fn json_complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, ) -> Result; async fn mandatory_request_header_get( @@ -655,9 +663,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex ContextWrapper::context(self) } - async fn any_of_get( + async fn any_of_get<'a>( &self, - any_of: Option<&Vec>, + any_of: Option<&'a Vec>, ) -> Result { let context = self.context().clone(); @@ -673,9 +681,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex self.api().callback_with_header_post(url, &context).await } - async fn complex_query_param_get( + async fn complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, ) -> Result { let context = self.context().clone(); @@ -683,9 +691,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Test examples - async fn examples_test( + async fn examples_test<'a>( &self, - ids: Option<&Vec>, + ids: Option<&'a Vec>, ) -> Result { let context = self.context().clone(); @@ -693,9 +701,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Test a Form Post - async fn form_test( + async fn form_test<'a>( &self, - required_array: &Vec, + required_array: &'a Vec, enum_field: models::FormTestRequestEnumField, ) -> Result { @@ -712,9 +720,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex self.api().get_with_boolean_parameter(iambool, &context).await } - async fn json_complex_query_param_get( + async fn json_complex_query_param_get<'a>( &self, - list_of_strings: Option<&Vec>, + list_of_strings: Option<&'a Vec>, ) -> Result { let context = self.context().clone(); @@ -952,6 +960,7 @@ pub enum CallbackCallbackPostResponse { /// Callback API +#[cfg_attr(feature = "mock", automock)] #[async_trait] pub trait CallbackApi { @@ -969,6 +978,7 @@ pub trait CallbackApi { } /// Callback API without a `Context` +#[cfg_attr(feature = "mock", automock)] #[async_trait] pub trait CallbackApiNoContext { 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 8328f10a786f..b4d7d33e2aed 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml @@ -20,6 +20,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -37,6 +39,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" 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 d41c95464cb2..7067fb30d709 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 @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -243,6 +245,7 @@ pub enum Op9GetResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -397,9 +400,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; 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 9da78bee85e8..cbcd4587bc85 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 @@ -24,6 +24,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -41,6 +43,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs index c9a0e821c0ba..87df5af2b446 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs @@ -286,11 +286,11 @@ impl Api for Server where C: Has + Send + Sync } /// To test enum parameters - async fn test_enum_parameters( + async fn test_enum_parameters<'a>( &self, - enum_header_string_array: Option<&Vec>, + enum_header_string_array: Option<&'a Vec>, enum_header_string: Option, - enum_query_string_array: Option<&Vec>, + enum_query_string_array: Option<&'a Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, @@ -352,9 +352,9 @@ impl Api for Server where C: Has + Send + Sync } /// Finds Pets by status - async fn find_pets_by_status( + async fn find_pets_by_status<'a>( &self, - status: &Vec, + status: &'a Vec, context: &C) -> Result { info!("find_pets_by_status({:?}) - X-Span-ID: {:?}", status, context.get().0.clone()); @@ -362,9 +362,9 @@ impl Api for Server where C: Has + Send + Sync } /// Finds Pets by tags - async fn find_pets_by_tags( + async fn find_pets_by_tags<'a>( &self, - tags: &Vec, + tags: &'a Vec, context: &C) -> Result { info!("find_pets_by_tags({:?}) - X-Span-ID: {:?}", tags, context.get().0.clone()); @@ -476,9 +476,9 @@ impl Api for Server where C: Has + Send + Sync } /// Creates list of users with given input array - async fn create_users_with_array_input( + async fn create_users_with_array_input<'a>( &self, - body: &Vec, + body: &'a Vec, context: &C) -> Result { info!("create_users_with_array_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); @@ -486,9 +486,9 @@ impl Api for Server where C: Has + Send + Sync } /// Creates list of users with given input array - async fn create_users_with_list_input( + async fn create_users_with_list_input<'a>( &self, - body: &Vec, + body: &'a Vec, context: &C) -> Result { info!("create_users_with_list_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); 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 aa28cbe8d55c..27607b69f606 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 @@ -1390,11 +1390,11 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn test_enum_parameters( + async fn test_enum_parameters<'a>( &self, - param_enum_header_string_array: Option<&Vec>, + param_enum_header_string_array: Option<&'a Vec>, param_enum_header_string: Option, - param_enum_query_string_array: Option<&Vec>, + param_enum_query_string_array: Option<&'a Vec>, param_enum_query_string: Option, param_enum_query_integer: Option, param_enum_query_double: Option, @@ -1968,9 +1968,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn find_pets_by_status( + async fn find_pets_by_status<'a>( &self, - param_status: &Vec, + param_status: &'a Vec, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -2076,9 +2076,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn find_pets_by_tags( + async fn find_pets_by_tags<'a>( &self, - param_tags: &Vec, + param_tags: &'a Vec, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -3201,9 +3201,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn create_users_with_array_input( + async fn create_users_with_array_input<'a>( &self, - param_body: &Vec, + param_body: &'a Vec, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -3278,9 +3278,9 @@ impl Api for Client where } #[allow(clippy::vec_init_then_push)] - async fn create_users_with_list_input( + async fn create_users_with_list_input<'a>( &self, - param_body: &Vec, + param_body: &'a Vec, context: &C) -> Result { let mut client_service = self.client_service.clone(); 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 e483f7e1075c..6b31a7ff8152 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 @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -322,6 +324,7 @@ pub enum UpdateUserResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -391,11 +394,11 @@ pub trait Api { context: &C) -> Result; /// To test enum parameters - async fn test_enum_parameters( + async fn test_enum_parameters<'a>( &self, - enum_header_string_array: Option<&Vec>, + enum_header_string_array: Option<&'a Vec>, enum_header_string: Option, - enum_query_string_array: Option<&Vec>, + enum_query_string_array: Option<&'a Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, @@ -433,15 +436,15 @@ pub trait Api { context: &C) -> Result; /// Finds Pets by status - async fn find_pets_by_status( + async fn find_pets_by_status<'a>( &self, - status: &Vec, + status: &'a Vec, context: &C) -> Result; /// Finds Pets by tags - async fn find_pets_by_tags( + async fn find_pets_by_tags<'a>( &self, - tags: &Vec, + tags: &'a Vec, context: &C) -> Result; /// Update an existing pet @@ -509,15 +512,15 @@ pub trait Api { context: &C) -> Result; /// Creates list of users with given input array - async fn create_users_with_array_input( + async fn create_users_with_array_input<'a>( &self, - body: &Vec, + body: &'a Vec, context: &C) -> Result; /// Creates list of users with given input array - async fn create_users_with_list_input( + async fn create_users_with_list_input<'a>( &self, - body: &Vec, + body: &'a Vec, context: &C) -> Result; /// Logs user into the system @@ -554,9 +557,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; @@ -626,11 +634,11 @@ pub trait ApiNoContext { ) -> Result; /// To test enum parameters - async fn test_enum_parameters( + async fn test_enum_parameters<'a>( &self, - enum_header_string_array: Option<&Vec>, + enum_header_string_array: Option<&'a Vec>, enum_header_string: Option, - enum_query_string_array: Option<&Vec>, + enum_query_string_array: Option<&'a Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, @@ -668,15 +676,15 @@ pub trait ApiNoContext { ) -> Result; /// Finds Pets by status - async fn find_pets_by_status( + async fn find_pets_by_status<'a>( &self, - status: &Vec, + status: &'a Vec, ) -> Result; /// Finds Pets by tags - async fn find_pets_by_tags( + async fn find_pets_by_tags<'a>( &self, - tags: &Vec, + tags: &'a Vec, ) -> Result; /// Update an existing pet @@ -744,15 +752,15 @@ pub trait ApiNoContext { ) -> Result; /// Creates list of users with given input array - async fn create_users_with_array_input( + async fn create_users_with_array_input<'a>( &self, - body: &Vec, + body: &'a Vec, ) -> Result; /// Creates list of users with given input array - async fn create_users_with_list_input( + async fn create_users_with_list_input<'a>( &self, - body: &Vec, + body: &'a Vec, ) -> Result; /// Logs user into the system @@ -913,11 +921,11 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// To test enum parameters - async fn test_enum_parameters( + async fn test_enum_parameters<'a>( &self, - enum_header_string_array: Option<&Vec>, + enum_header_string_array: Option<&'a Vec>, enum_header_string: Option, - enum_query_string_array: Option<&Vec>, + enum_query_string_array: Option<&'a Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, @@ -979,9 +987,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Finds Pets by status - async fn find_pets_by_status( + async fn find_pets_by_status<'a>( &self, - status: &Vec, + status: &'a Vec, ) -> Result { let context = self.context().clone(); @@ -989,9 +997,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Finds Pets by tags - async fn find_pets_by_tags( + async fn find_pets_by_tags<'a>( &self, - tags: &Vec, + tags: &'a Vec, ) -> Result { let context = self.context().clone(); @@ -1103,9 +1111,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Creates list of users with given input array - async fn create_users_with_array_input( + async fn create_users_with_array_input<'a>( &self, - body: &Vec, + body: &'a Vec, ) -> Result { let context = self.context().clone(); @@ -1113,9 +1121,9 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex } /// Creates list of users with given input array - async fn create_users_with_list_input( + async fn create_users_with_list_input<'a>( &self, - body: &Vec, + body: &'a Vec, ) -> Result { let context = self.context().clone(); diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml b/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml index 6ab9a74369e1..412357ae89a5 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/Cargo.toml @@ -20,6 +20,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -37,6 +39,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs index def1947605e2..6d76af54f707 100644 --- a/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ping-bearer-auth/src/lib.rs @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -27,6 +29,7 @@ pub enum PingGetResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -37,9 +40,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C; 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 1c6252b9e823..5365ac4fa3bc 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 @@ -20,6 +20,8 @@ cli = [ ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +mock = ["mockall"] + [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } hyper-tls = { version = "0.6", optional = true } @@ -37,6 +39,7 @@ swagger = { version = "7.0.0-rc2", features = ["serdejson", "server", "client", headers = "0.4.0" log = "0.4.27" mime = "0.3" +mockall = { version = "0.13.1", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" 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 9183faf7d34f..170f15a06c60 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 @@ -3,6 +3,8 @@ use async_trait::async_trait; use futures::Stream; +#[cfg(feature = "mock")] +use mockall::automock; use std::error::Error; use std::collections::BTreeSet; use std::task::{Poll, Context}; @@ -80,6 +82,7 @@ pub enum SoloObjectPostResponse { } /// API +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait Api { @@ -131,9 +134,14 @@ pub trait Api { } /// API where `Context` isn't passed on every API call +#[cfg_attr(feature = "mock", automock)] #[async_trait] #[allow(clippy::too_many_arguments, clippy::ptr_arg)] pub trait ApiNoContext { + // The std::task::Context struct houses a reference to std::task::Waker with the lifetime <'a>. + // Adding an anonymous lifetime `'a` to allow mockall to create a mock object with the right lifetimes. + // This is needed because the compiler is unable to determine the lifetimes on F's trait bound + // where F is the closure created by mockall. We use higher-rank trait bounds here to get around this. fn context(&self) -> &C;