From fc90936da67db83a0fe0bd396a05c60849ca20bd Mon Sep 17 00:00:00 2001 From: David Steele Date: Thu, 6 Nov 2025 12:58:07 +0000 Subject: [PATCH] Fixups for rust-server hyper1 support --- .../codegen/languages/RustServerCodegen.java | 26 +- .../RustServerCodegenDeprecated.java | 16 +- .../client-request-body-instance.mustache | 15 +- .../server-request-body-basic.mustache | 3 + .../resources/3_0/rust-server/openapi-v3.yaml | 12 +- .../openapi-v3/.openapi-generator/FILES | 2 + .../output/openapi-v3/README.md | 3 + .../output/openapi-v3/api/openapi.yaml | 12 + .../output/openapi-v3/bin/cli.rs | 6 +- .../docs/FormTestRequestEnumField.md | 9 + .../docs/FormTestRequestGrantType.md | 9 + .../output/openapi-v3/docs/NoTypeObject.md | 9 + .../output/openapi-v3/docs/default_api.md | 12 +- .../output/openapi-v3/examples/client/main.rs | 8 +- .../openapi-v3/examples/server/server.rs | 5 +- .../output/openapi-v3/src/client/mod.rs | 9 +- .../output/openapi-v3/src/lib.rs | 11 +- .../output/openapi-v3/src/models.rs | 258 ++++++++++++++++++ .../output/openapi-v3/src/server/mod.rs | 5 +- .../examples/client/main.rs | 10 +- .../src/server/mod.rs | 2 +- .../multipart-v3/.openapi-generator-ignore | 2 - .../openapi-v3/.openapi-generator/FILES | 2 + .../rust-server/output/openapi-v3/README.md | 3 + .../output/openapi-v3/api/openapi.yaml | 12 + .../rust-server/output/openapi-v3/bin/cli.rs | 6 +- .../docs/FormTestRequestEnumField.md | 9 + .../output/openapi-v3/docs/NoTypeObject.md | 9 + .../output/openapi-v3/docs/default_api.md | 12 +- .../output/openapi-v3/examples/client/main.rs | 7 +- .../openapi-v3/examples/server/server.rs | 5 +- .../output/openapi-v3/src/client/mod.rs | 9 +- .../rust-server/output/openapi-v3/src/lib.rs | 11 +- .../output/openapi-v3/src/models.rs | 258 ++++++++++++++++++ .../output/openapi-v3/src/server/mod.rs | 5 +- .../examples/client/main.rs | 10 +- .../src/server/mod.rs | 2 +- 37 files changed, 734 insertions(+), 70 deletions(-) create mode 100644 samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestEnumField.md create mode 100644 samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestGrantType.md create mode 100644 samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/NoTypeObject.md create mode 100644 samples/server/petstore/rust-server/output/openapi-v3/docs/FormTestRequestEnumField.md create mode 100644 samples/server/petstore/rust-server/output/openapi-v3/docs/NoTypeObject.md 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 7231c50e7623..8d53d708fb56 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 @@ -370,6 +370,16 @@ public String toOperationId(String operationId) { return sanitizeIdentifier(operationId, CasingType.CAMEL_CASE, "call", "method", true); } + @Override + public String toParamName(String name) { + // rust-server doesn't support r# in param name. + if (parameterNameMapping.containsKey(name)) { + return parameterNameMapping.get(name); + } + + return sanitizeIdentifier(name, CasingType.SNAKE_CASE, "param", "parameter", false); + } + @Override public String toEnumValue(String value, String datatype) { // rust-server templates expect value to be in quotes @@ -1229,6 +1239,9 @@ public CodegenModel fromModel(String name, Schema model) { && (mdl.dataType.startsWith("swagger::OneOf") || mdl.dataType.startsWith("swagger::AnyOf"))) { toStringSupport = false; partialOrdSupport = false; + } else if (mdl.dataType != null && mdl.dataType.equals("serde_json::Value")) { + // Value doesn't implement PartialOrd + partialOrdSupport = false; } else if (mdl.getAdditionalPropertiesType() != null) { toStringSupport = false; } else if (model instanceof ComposedSchema) { @@ -1545,7 +1558,18 @@ private void processParam(CodegenParameter param, CodegenOperation op) { } } else { param.vendorExtensions.put("x-format-string", "{:?}"); - if (param.example != null) { + // Check if this is a model-type enum (allowableValues with values list) + if (param.allowableValues != null && param.allowableValues.containsKey("values")) { + List values = (List) param.allowableValues.get("values"); + if (!values.isEmpty()) { + // Use the first enum value as the example. + String firstEnumValue = values.get(0).toString(); + String enumVariant = toEnumVarName(firstEnumValue, param.dataType); + example = param.dataType + "::" + enumVariant; + } else if (param.example != null) { + example = "serde_json::from_str::<" + param.dataType + ">(r#\"" + param.example + "\"#).expect(\"Failed to parse JSON example\")"; + } + } else if (param.example != null) { example = "serde_json::from_str::<" + param.dataType + ">(r#\"" + param.example + "\"#).expect(\"Failed to parse JSON example\")"; } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegenDeprecated.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegenDeprecated.java index 5d17b2416506..49f95f285245 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegenDeprecated.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegenDeprecated.java @@ -1229,6 +1229,9 @@ public CodegenModel fromModel(String name, Schema model) { && (mdl.dataType.startsWith("swagger::OneOf") || mdl.dataType.startsWith("swagger::AnyOf"))) { toStringSupport = false; partialOrdSupport = false; + } else if (mdl.dataType != null && mdl.dataType.equals("serde_json::Value")) { + // Value doesn't implement PartialOrd + partialOrdSupport = false; } else if (mdl.getAdditionalPropertiesType() != null) { toStringSupport = false; } else if (model instanceof ComposedSchema) { @@ -1546,7 +1549,18 @@ private void processParam(CodegenParameter param, CodegenOperation op) { } else { param.vendorExtensions.put("x-format-string", "{:?}"); - if (param.example != null) { + // Check if this is a model-type enum (allowableValues with values list) + if (param.allowableValues != null && param.allowableValues.containsKey("values")) { + List values = (List) param.allowableValues.get("values"); + if (!values.isEmpty()) { + // Use the first enum value as the example. + String firstEnumValue = values.get(0).toString(); + String enumVariant = toEnumVarName(firstEnumValue, param.dataType); + example = param.dataType + "::" + enumVariant; + } else if (param.example != null) { + example = "serde_json::from_str::<" + param.dataType + ">(r#\"" + param.example + "\"#).expect(\"Failed to parse JSON example\")"; + } + } else if (param.example != null) { example = "serde_json::from_str::<" + param.dataType + ">(r#\"" + param.example + "\"#).expect(\"Failed to parse JSON example\")"; } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache index 3ba56fcc3e6f..55806f12df72 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-request-body-instance.mustache @@ -80,12 +80,17 @@ {{/required}} {{#exts}} {{#x-consumes-plain-text}} - {{#isByteArray}} - let body = String::from_utf8(param_body.0).expect("Body was not valid UTF8"); - {{/isByteArray}} - {{^isByteArray}} + {{^isByteArray}} + {{^isBinary}} let body = param_{{{paramName}}}; - {{/isByteArray}} + {{/isBinary}} + {{/isByteArray}} + {{#isByteArray}} + let body = String::from_utf8(param_{{{paramName}}}.0).expect("Body was not valid UTF8"); + {{/isByteArray}} + {{#isBinary}} + let body = String::from_utf8(param_{{{paramName}}}.0).expect("Body was not valid UTF8"); + {{/isBinary}} {{/x-consumes-plain-text}} {{#x-consumes-xml}} let body = param_{{{paramName}}}.as_xml(); diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache index 7372cd7fbd71..9a30f3dac9bb 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-request-body-basic.mustache @@ -28,6 +28,9 @@ {{/x-consumes-plain-text}} {{#x-consumes-plain-text}} + {{#isBinary}} + Some(swagger::ByteArray(body.to_vec())) + {{/isBinary}} {{#isByteArray}} Some(swagger::ByteArray(body.to_vec())) {{/isByteArray}} diff --git a/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml b/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml index cad4929930ea..17b3e06ef359 100644 --- a/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml @@ -500,6 +500,7 @@ paths: summary: Test a Form Post operationId: FormTest requestBody: + required: true content: application/x-www-form-urlencoded: schema: @@ -509,7 +510,13 @@ paths: type: array items: type: string - required: true + enum_field: + type: string + enum: + - one_enum + required: + - requiredArray + - enum_field responses: '200': description: OK @@ -728,6 +735,9 @@ components: NullableObject: type: string nullable: true + NoTypeObject: + title: an object with no type + description: An object with no type NullableTest: type: object required: diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/.openapi-generator/FILES index 5f799d4f657d..9fb0ed88b5fa 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/.openapi-generator/FILES @@ -19,11 +19,13 @@ docs/DuplicateXmlObject.md docs/EnumWithStarObject.md docs/Err.md docs/Error.md +docs/FormTestRequestEnumField.md docs/Model12345AnyOfObject.md docs/Model12345AnyOfObjectAnyOf.md docs/MultigetGet201Response.md docs/MyId.md docs/MyIdList.md +docs/NoTypeObject.md docs/NullableObject.md docs/NullableTest.md docs/ObjectHeader.md diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/README.md b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/README.md index df104ccd672a..df142a3069cc 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/README.md +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/README.md @@ -113,6 +113,7 @@ cargo run --example client XmlOtherPost cargo run --example client XmlOtherPut cargo run --example client XmlPost cargo run --example client XmlPut +cargo run --example client EnumInPathPathParamGet cargo run --example client MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet cargo run --example client CreateRepo cargo run --example client GetRepoInfo @@ -201,11 +202,13 @@ Method | HTTP request | Description - [EnumWithStarObject](docs/EnumWithStarObject.md) - [Err](docs/Err.md) - [Error](docs/Error.md) + - [FormTestRequestEnumField](docs/FormTestRequestEnumField.md) - [Model12345AnyOfObject](docs/Model12345AnyOfObject.md) - [Model12345AnyOfObjectAnyOf](docs/Model12345AnyOfObjectAnyOf.md) - [MultigetGet201Response](docs/MultigetGet201Response.md) - [MyId](docs/MyId.md) - [MyIdList](docs/MyIdList.md) + - [NoTypeObject](docs/NoTypeObject.md) - [NullableObject](docs/NullableObject.md) - [NullableTest](docs/NullableTest.md) - [ObjectHeader](docs/ObjectHeader.md) diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/api/openapi.yaml b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/api/openapi.yaml index 3be49f8eb8d7..bca81ddc7ef0 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/api/openapi.yaml +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/api/openapi.yaml @@ -780,6 +780,9 @@ components: NullableObject: nullable: true type: string + NoTypeObject: + description: An object with no type + title: an object with no type NullableTest: properties: nullable: @@ -847,12 +850,21 @@ components: anyOf: - $ref: "#/components/schemas/StringObject" - $ref: "#/components/schemas/UuidObject" + FormTest_request_enum_field: + enum: + - one_enum + type: string FormTest_request: properties: requiredArray: items: type: string type: array + enum_field: + $ref: "#/components/schemas/FormTest_request_enum_field" + required: + - enum_field + - requiredArray type: object AnyOfObject_anyOf: enum: diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/bin/cli.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/bin/cli.rs index 7557b8978380..28734b8b7fb3 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/bin/cli.rs @@ -112,7 +112,9 @@ enum Operation { /// Test a Form Post FormTest { #[structopt(parse(try_from_str = parse_json), long)] - required_array: Option>, + required_array: Vec, + #[structopt(parse(try_from_str = parse_json))] + enum_field: models::FormTestRequestEnumField, }, GetWithBooleanParameter { /// Let's check apostrophes get encoded properly! @@ -352,11 +354,13 @@ async fn main() -> Result<()> { } Operation::FormTest { required_array, + enum_field, } => { info!("Performing a FormTest request"); let result = client.form_test( required_array.as_ref(), + enum_field, ).await?; debug!("Result: {:?}", result); diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestEnumField.md b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestEnumField.md new file mode 100644 index 000000000000..858a6dbf787d --- /dev/null +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestEnumField.md @@ -0,0 +1,9 @@ +# FormTestRequestEnumField + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestGrantType.md b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestGrantType.md new file mode 100644 index 000000000000..b808ab8f8a6a --- /dev/null +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/FormTestRequestGrantType.md @@ -0,0 +1,9 @@ +# FormTestRequestGrantType + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/NoTypeObject.md b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/NoTypeObject.md new file mode 100644 index 000000000000..599c4b919753 --- /dev/null +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/NoTypeObject.md @@ -0,0 +1,9 @@ +# NoTypeObject + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/default_api.md b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/default_api.md index 60a218dd56d7..237bfe20109d 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/default_api.md +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/docs/default_api.md @@ -159,21 +159,15 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) # **FormTest** -> FormTest(optional) +> FormTest(required_array, enum_field) Test a Form Post ### Required Parameters Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **optional** | **map[string]interface{}** | optional parameters | nil if no parameters - -### Optional Parameters -Optional parameters are passed through a map[string]interface{}. - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **required_array** | [**String**](String.md)| | + **required_array** | [**String**](String.md)| | + **enum_field** | [**FormTest_request_enum_field**](FormTest_request_enum_field.md)| | ### Return type diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/client/main.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/client/main.rs index d32949fa1a78..d4b93615cfd5 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/client/main.rs @@ -92,6 +92,7 @@ fn main() { "XmlOtherPut", "XmlPost", "XmlPut", + "EnumInPathPathParamGet", "MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet", "CreateRepo", "GetRepoInfo", @@ -197,7 +198,8 @@ fn main() { }, Some("FormTest") => { let result = rt.block_on(client.form_test( - Some(&Vec::new()) + &Vec::new(), + models::FormTestRequestEnumField::OneEnum )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, @@ -327,14 +329,12 @@ fn main() { )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, - /* Disabled because there's no example. Some("EnumInPathPathParamGet") => { let result = rt.block_on(client.enum_in_path_path_param_get( - ??? + models::StringEnum::Foo )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, - */ Some("MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet") => { let result = rt.block_on(client.multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get( "path_param_a_example".to_string(), diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/server/server.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/server/server.rs index 43b3f95fb026..b23193f3fe6f 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/examples/server/server.rs @@ -177,10 +177,11 @@ impl Api for Server where C: Has + Send + Sync /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, context: &C) -> Result { - info!("form_test({:?}) - X-Span-ID: {:?}", required_array, context.get().0.clone()); + info!("form_test({:?}, {:?}) - X-Span-ID: {:?}", required_array, enum_field, context.get().0.clone()); Err(ApiError("Api-Error: Operation is NOT implemented".into())) } async fn get_with_boolean_parameter( diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/client/mod.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/client/mod.rs index cd1e6a1d05a4..8e7ed37f37f6 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/client/mod.rs @@ -744,7 +744,8 @@ impl Api for Client where } async fn form_test( &self, - param_required_array: Option<&Vec>, + param_required_array: &Vec, + param_enum_field: models::FormTestRequestEnumField, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -779,7 +780,6 @@ impl Api for Client where // Consumes form body let mut params = vec![]; - if let Some(param_required_array) = param_required_array { // style=form,explode=true for param_required_array in param_required_array { #[allow(clippy::uninlined_format_args)] @@ -787,7 +787,10 @@ impl Api for Client where format!("{:?}", param_required_array) )); } - } + #[allow(clippy::uninlined_format_args)] + params.push(("enum_field", + format!("{:?}", param_enum_field) + )); let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/lib.rs index 190fa5063566..72c7e7adc4b9 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/lib.rs @@ -310,7 +310,8 @@ pub trait Api { /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, context: &C) -> Result; async fn get_with_boolean_parameter( @@ -476,7 +477,8 @@ pub trait ApiNoContext { /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, ) -> Result; async fn get_with_boolean_parameter( @@ -672,11 +674,12 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, ) -> Result { let context = self.context().clone(); - self.api().form_test(required_array, &context).await + self.api().form_test(required_array, enum_field, &context).await } async fn get_with_boolean_parameter( diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/models.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/models.rs index e98c13654e73..f3008fdd34b2 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/models.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/models.rs @@ -2252,6 +2252,124 @@ impl Error { } } +/// Enumeration of values. +/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]` +/// which helps with FFI. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, Hash)] +#[cfg_attr(feature = "conversion", derive(frunk_enum_derive::LabelledGenericEnum))] +pub enum FormTestRequestEnumField { + #[serde(rename = "one_enum")] + OneEnum, +} + +impl std::fmt::Display for FormTestRequestEnumField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + FormTestRequestEnumField::OneEnum => write!(f, "one_enum"), + } + } +} + +impl std::str::FromStr for FormTestRequestEnumField { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match s { + "one_enum" => std::result::Result::Ok(FormTestRequestEnumField::OneEnum), + _ => std::result::Result::Err(format!("Value not valid: {s}")), + } + } +} + +// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { + let hdr_value = hdr_value.to_string(); + match hyper::header::HeaderValue::from_str(&hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(e) => std::result::Result::Err( + format!("Invalid header value for FormTestRequestEnumField - value: {hdr_value} is invalid {e}")) + } + } +} + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom for header::IntoHeaderValue { + type Error = String; + + fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result { + match hdr_value.to_str() { + std::result::Result::Ok(value) => { + match ::from_str(value) { + std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{value}' into FormTestRequestEnumField - {err}")) + } + }, + std::result::Result::Err(e) => std::result::Result::Err( + format!("Unable to convert header: {hdr_value:?} to string: {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom>> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { + let hdr_values : Vec = hdr_values.0.into_iter().map(|hdr_value| { + hdr_value.to_string() + }).collect(); + + match hyper::header::HeaderValue::from_str(&hdr_values.join(", ")) { + std::result::Result::Ok(hdr_value) => std::result::Result::Ok(hdr_value), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {hdr_values:?} into a header - {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom for header::IntoHeaderValue> { + type Error = String; + + fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result { + match hdr_values.to_str() { + std::result::Result::Ok(hdr_values) => { + let hdr_values : std::vec::Vec = hdr_values + .split(',') + .filter_map(|hdr_value| match hdr_value.trim() { + "" => std::option::Option::None, + hdr_value => std::option::Option::Some({ + match ::from_str(hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{hdr_value}' into FormTestRequestEnumField - {err}")) + } + }) + }).collect::, String>>()?; + + std::result::Result::Ok(header::IntoHeaderValue(hdr_values)) + }, + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to parse header: {hdr_values:?} as a string - {e}")), + } + } +} + +impl FormTestRequestEnumField { + /// Helper function to allow us to convert this model to an XML string. + /// Will panic if serialisation fails. + #[allow(dead_code)] + pub(crate) fn as_xml(&self) -> String { + serde_xml_rs::to_string(&self).expect("impossible to fail to serialize") + } +} + /// Test a model containing an anyOf that starts with a number #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] @@ -3002,6 +3120,146 @@ impl MyIdList { } } +/// An object with no type +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] +pub struct NoTypeObject(serde_json::Value); + +impl std::convert::From for NoTypeObject { + fn from(x: serde_json::Value) -> Self { + NoTypeObject(x) + } +} + +impl std::convert::From for serde_json::Value { + fn from(x: NoTypeObject) -> Self { + x.0 + } +} + +impl std::ops::Deref for NoTypeObject { + type Target = serde_json::Value; + fn deref(&self) -> &serde_json::Value { + &self.0 + } +} + +impl std::ops::DerefMut for NoTypeObject { + fn deref_mut(&mut self) -> &mut serde_json::Value { + &mut self.0 + } +} + +/// Converts the NoTypeObject value to the Query Parameters representation (style=form, explode=false) +/// specified in https://swagger.io/docs/specification/serialization/ +/// Should be implemented in a serde serializer +impl ::std::string::ToString for NoTypeObject { + fn to_string(&self) -> String { + self.0.to_string() + } +} + +/// Converts Query Parameters representation (style=form, explode=false) to a NoTypeObject value +/// as specified in https://swagger.io/docs/specification/serialization/ +/// Should be implemented in a serde deserializer +impl ::std::str::FromStr for NoTypeObject { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match std::str::FromStr::from_str(s) { + std::result::Result::Ok(r) => std::result::Result::Ok(NoTypeObject(r)), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {s} to NoTypeObject: {e:?}")), + } + } +} + +// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { + let hdr_value = hdr_value.to_string(); + match hyper::header::HeaderValue::from_str(&hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(e) => std::result::Result::Err( + format!("Invalid header value for NoTypeObject - value: {hdr_value} is invalid {e}")) + } + } +} + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom for header::IntoHeaderValue { + type Error = String; + + fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result { + match hdr_value.to_str() { + std::result::Result::Ok(value) => { + match ::from_str(value) { + std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{value}' into NoTypeObject - {err}")) + } + }, + std::result::Result::Err(e) => std::result::Result::Err( + format!("Unable to convert header: {hdr_value:?} to string: {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom>> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { + let hdr_values : Vec = hdr_values.0.into_iter().map(|hdr_value| { + hdr_value.to_string() + }).collect(); + + match hyper::header::HeaderValue::from_str(&hdr_values.join(", ")) { + std::result::Result::Ok(hdr_value) => std::result::Result::Ok(hdr_value), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {hdr_values:?} into a header - {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom for header::IntoHeaderValue> { + type Error = String; + + fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result { + match hdr_values.to_str() { + std::result::Result::Ok(hdr_values) => { + let hdr_values : std::vec::Vec = hdr_values + .split(',') + .filter_map(|hdr_value| match hdr_value.trim() { + "" => std::option::Option::None, + hdr_value => std::option::Option::Some({ + match ::from_str(hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{hdr_value}' into NoTypeObject - {err}")) + } + }) + }).collect::, String>>()?; + + std::result::Result::Ok(header::IntoHeaderValue(hdr_values)) + }, + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to parse header: {hdr_values:?} as a string - {e}")), + } + } +} + +impl NoTypeObject { + /// Helper function to allow us to convert this model to an XML string. + /// Will panic if serialisation fails. + #[allow(dead_code)] + pub(crate) fn as_xml(&self) -> String { + serde_xml_rs::to_string(&self).expect("impossible to fail to serialize") + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] pub struct NullableObject(String); diff --git a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/server/mod.rs b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/server/mod.rs index 720cb975d171..a485bf0ab239 100644 --- a/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server-deprecated/output/openapi-v3/src/server/mod.rs @@ -473,9 +473,12 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(body) => { // Form parameters let param_required_array = - None; + Vec::new(); + let param_enum_field = + models::FormTestRequestEnumField::OneEnum; let result = api_impl.form_test( param_required_array.as_ref(), + param_enum_field, &context ).await; let mut response = Response::new(Body::empty()); diff --git a/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs b/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs index 62b1a8c1389b..e9c468b84b7b 100644 --- a/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs +++ b/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs @@ -245,12 +245,12 @@ fn main() { Some("TestEnumParameters") => { let result = rt.block_on(client.test_enum_parameters( Some(&Vec::new()), - None, + Some(models::TestEnumParametersEnumHeaderStringParameter::Abc), Some(&Vec::new()), - None, - None, - None, - None + Some(models::TestEnumParametersEnumHeaderStringParameter::Abc), + Some(models::TestEnumParametersEnumQueryIntegerParameter::Variant1), + Some(models::TestEnumParametersEnumQueryDoubleParameter::Variant11), + Some(models::TestEnumParametersRequestEnumFormString::Abc) )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, diff --git a/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs b/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs index c3adc82cb031..53ab4b0613c2 100644 --- a/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs +++ b/samples/server/petstore/rust-server-deprecated/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs @@ -1073,7 +1073,7 @@ impl hyper::service::Service<(Request, C)> for Service where Ok(body) => { // Form parameters let param_enum_form_string = - None; + Some(models::TestEnumParametersRequestEnumFormString::Abc); let result = api_impl.test_enum_parameters( param_enum_header_string_array.as_ref(), param_enum_header_string, diff --git a/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator-ignore b/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator-ignore index 82e4e79984b4..7484ee590a38 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator-ignore +++ b/samples/server/petstore/rust-server/output/multipart-v3/.openapi-generator-ignore @@ -21,5 +21,3 @@ #docs/*.md # Then explicitly reverse the ignore rule for a single file: #!docs/README.md -# -# diff --git a/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES index 7025e5bf9838..bbae578c96d2 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/openapi-v3/.openapi-generator/FILES @@ -19,11 +19,13 @@ docs/DuplicateXmlObject.md docs/EnumWithStarObject.md docs/Err.md docs/Error.md +docs/FormTestRequestEnumField.md docs/Model12345AnyOfObject.md docs/Model12345AnyOfObjectAnyOf.md docs/MultigetGet201Response.md docs/MyId.md docs/MyIdList.md +docs/NoTypeObject.md docs/NullableObject.md docs/NullableTest.md docs/ObjectHeader.md 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 df104ccd672a..df142a3069cc 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/README.md +++ b/samples/server/petstore/rust-server/output/openapi-v3/README.md @@ -113,6 +113,7 @@ cargo run --example client XmlOtherPost cargo run --example client XmlOtherPut cargo run --example client XmlPost cargo run --example client XmlPut +cargo run --example client EnumInPathPathParamGet cargo run --example client MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet cargo run --example client CreateRepo cargo run --example client GetRepoInfo @@ -201,11 +202,13 @@ Method | HTTP request | Description - [EnumWithStarObject](docs/EnumWithStarObject.md) - [Err](docs/Err.md) - [Error](docs/Error.md) + - [FormTestRequestEnumField](docs/FormTestRequestEnumField.md) - [Model12345AnyOfObject](docs/Model12345AnyOfObject.md) - [Model12345AnyOfObjectAnyOf](docs/Model12345AnyOfObjectAnyOf.md) - [MultigetGet201Response](docs/MultigetGet201Response.md) - [MyId](docs/MyId.md) - [MyIdList](docs/MyIdList.md) + - [NoTypeObject](docs/NoTypeObject.md) - [NullableObject](docs/NullableObject.md) - [NullableTest](docs/NullableTest.md) - [ObjectHeader](docs/ObjectHeader.md) diff --git a/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml b/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml index 3be49f8eb8d7..bca81ddc7ef0 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml +++ b/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml @@ -780,6 +780,9 @@ components: NullableObject: nullable: true type: string + NoTypeObject: + description: An object with no type + title: an object with no type NullableTest: properties: nullable: @@ -847,12 +850,21 @@ components: anyOf: - $ref: "#/components/schemas/StringObject" - $ref: "#/components/schemas/UuidObject" + FormTest_request_enum_field: + enum: + - one_enum + type: string FormTest_request: properties: requiredArray: items: type: string type: array + enum_field: + $ref: "#/components/schemas/FormTest_request_enum_field" + required: + - enum_field + - requiredArray type: object AnyOfObject_anyOf: enum: diff --git a/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs b/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs index 1df4255024eb..30e4193c0756 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/bin/cli.rs @@ -112,7 +112,9 @@ enum Operation { /// Test a Form Post FormTest { #[clap(value_parser = parse_json::>, long)] - required_array: Option>, + required_array: Vec, + #[clap(value_parser = parse_json::)] + enum_field: models::FormTestRequestEnumField, }, GetWithBooleanParameter { /// Let's check apostrophes get encoded properly! @@ -352,11 +354,13 @@ async fn main() -> Result<()> { } Operation::FormTest { required_array, + enum_field, } => { info!("Performing a FormTest request"); let result = client.form_test( required_array.as_ref(), + enum_field, ).await?; debug!("Result: {:?}", result); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/docs/FormTestRequestEnumField.md b/samples/server/petstore/rust-server/output/openapi-v3/docs/FormTestRequestEnumField.md new file mode 100644 index 000000000000..858a6dbf787d --- /dev/null +++ b/samples/server/petstore/rust-server/output/openapi-v3/docs/FormTestRequestEnumField.md @@ -0,0 +1,9 @@ +# FormTestRequestEnumField + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server/output/openapi-v3/docs/NoTypeObject.md b/samples/server/petstore/rust-server/output/openapi-v3/docs/NoTypeObject.md new file mode 100644 index 000000000000..599c4b919753 --- /dev/null +++ b/samples/server/petstore/rust-server/output/openapi-v3/docs/NoTypeObject.md @@ -0,0 +1,9 @@ +# NoTypeObject + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md b/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md index 9ec0b3c33516..621325c0ea84 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md +++ b/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md @@ -159,21 +159,15 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) # **FormTest** -> FormTest(optional) +> FormTest(required_array, enum_field) Test a Form Post ### Required Parameters Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **optional** | **map[string]interface{}** | optional parameters | nil if no parameters - -### Optional Parameters -Optional parameters are passed through a map[string]interface{}. - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **required_array** | [**String**](String.md)| | + **required_array** | [**String**](String.md)| | + **enum_field** | [**FormTest_request_enum_field**](FormTest_request_enum_field.md)| | ### Return type diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs index c0140794489b..1a59fa58bf15 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs @@ -196,7 +196,8 @@ fn main() { }, Some("FormTest") => { let result = rt.block_on(client.form_test( - Some(&Vec::new()) + &Vec::new(), + models::FormTestRequestEnumField::OneEnum )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, @@ -326,14 +327,12 @@ fn main() { )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, - /* Disabled because there's no example. Some("EnumInPathPathParamGet") => { let result = rt.block_on(client.enum_in_path_path_param_get( - ??? + models::StringEnum::Foo )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, - */ Some("MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGet") => { let result = rt.block_on(client.multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get( "path_param_a_example".to_string(), 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 d69f9bf2bc83..2215f8da79a2 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 @@ -216,10 +216,11 @@ impl Api for Server where C: Has + Send + Sync /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, context: &C) -> Result { - info!("form_test({:?}) - X-Span-ID: {:?}", required_array, context.get().0.clone()); + info!("form_test({:?}, {:?}) - X-Span-ID: {:?}", required_array, enum_field, context.get().0.clone()); Err(ApiError("Api-Error: Operation is NOT implemented".into())) } 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 05d38a1b1a6d..c02e279f086c 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 @@ -789,7 +789,8 @@ impl Api for Client where #[allow(clippy::vec_init_then_push)] async fn form_test( &self, - param_required_array: Option<&Vec>, + param_required_array: &Vec, + param_enum_field: models::FormTestRequestEnumField, context: &C) -> Result { let mut client_service = self.client_service.clone(); @@ -824,7 +825,6 @@ impl Api for Client where // Consumes form body let mut params = vec![]; - if let Some(param_required_array) = param_required_array { // style=form,explode=true for param_required_array in param_required_array { #[allow(clippy::uninlined_format_args)] @@ -832,7 +832,10 @@ impl Api for Client where format!("{:?}", param_required_array) )); } - } + #[allow(clippy::uninlined_format_args)] + params.push(("enum_field", + format!("{:?}", param_enum_field) + )); let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); 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 07dbe1f5bdd2..16e1a16f00d2 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 @@ -337,7 +337,8 @@ pub trait Api { /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, context: &C) -> Result; async fn get_with_boolean_parameter( @@ -501,7 +502,8 @@ pub trait ApiNoContext { /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, ) -> Result; async fn get_with_boolean_parameter( @@ -693,11 +695,12 @@ impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for Contex /// Test a Form Post async fn form_test( &self, - required_array: Option<&Vec>, + required_array: &Vec, + enum_field: models::FormTestRequestEnumField, ) -> Result { let context = self.context().clone(); - self.api().form_test(required_array, &context).await + self.api().form_test(required_array, enum_field, &context).await } async fn get_with_boolean_parameter( 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 7c9622b88606..4e7481c8633d 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 @@ -2252,6 +2252,124 @@ impl Error { } } +/// Enumeration of values. +/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]` +/// which helps with FFI. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, Hash)] +#[cfg_attr(feature = "conversion", derive(frunk_enum_derive::LabelledGenericEnum))] +pub enum FormTestRequestEnumField { + #[serde(rename = "one_enum")] + OneEnum, +} + +impl std::fmt::Display for FormTestRequestEnumField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + FormTestRequestEnumField::OneEnum => write!(f, "one_enum"), + } + } +} + +impl std::str::FromStr for FormTestRequestEnumField { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match s { + "one_enum" => std::result::Result::Ok(FormTestRequestEnumField::OneEnum), + _ => std::result::Result::Err(format!("Value not valid: {s}")), + } + } +} + +// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { + let hdr_value = hdr_value.to_string(); + match hyper::header::HeaderValue::from_str(&hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(e) => std::result::Result::Err( + format!("Invalid header value for FormTestRequestEnumField - value: {hdr_value} is invalid {e}")) + } + } +} + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom for header::IntoHeaderValue { + type Error = String; + + fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result { + match hdr_value.to_str() { + std::result::Result::Ok(value) => { + match ::from_str(value) { + std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{value}' into FormTestRequestEnumField - {err}")) + } + }, + std::result::Result::Err(e) => std::result::Result::Err( + format!("Unable to convert header: {hdr_value:?} to string: {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom>> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { + let hdr_values : Vec = hdr_values.0.into_iter().map(|hdr_value| { + hdr_value.to_string() + }).collect(); + + match hyper::header::HeaderValue::from_str(&hdr_values.join(", ")) { + std::result::Result::Ok(hdr_value) => std::result::Result::Ok(hdr_value), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {hdr_values:?} into a header - {e}",)) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom for header::IntoHeaderValue> { + type Error = String; + + fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result { + match hdr_values.to_str() { + std::result::Result::Ok(hdr_values) => { + let hdr_values : std::vec::Vec = hdr_values + .split(',') + .filter_map(|hdr_value| match hdr_value.trim() { + "" => std::option::Option::None, + hdr_value => std::option::Option::Some({ + match ::from_str(hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{hdr_value}' into FormTestRequestEnumField - {err}")) + } + }) + }).collect::, String>>()?; + + std::result::Result::Ok(header::IntoHeaderValue(hdr_values)) + }, + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to parse header: {hdr_values:?} as a string - {e}")), + } + } +} + +impl FormTestRequestEnumField { + /// Helper function to allow us to convert this model to an XML string. + /// Will panic if serialisation fails. + #[allow(dead_code)] + pub(crate) fn as_xml(&self) -> String { + serde_xml_rs::to_string(&self).expect("impossible to fail to serialize") + } +} + /// Test a model containing an anyOf that starts with a number #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] @@ -3002,6 +3120,146 @@ impl MyIdList { } } +/// An object with no type +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] +pub struct NoTypeObject(serde_json::Value); + +impl std::convert::From for NoTypeObject { + fn from(x: serde_json::Value) -> Self { + NoTypeObject(x) + } +} + +impl std::convert::From for serde_json::Value { + fn from(x: NoTypeObject) -> Self { + x.0 + } +} + +impl std::ops::Deref for NoTypeObject { + type Target = serde_json::Value; + fn deref(&self) -> &serde_json::Value { + &self.0 + } +} + +impl std::ops::DerefMut for NoTypeObject { + fn deref_mut(&mut self) -> &mut serde_json::Value { + &mut self.0 + } +} + +/// Converts the NoTypeObject value to the Query Parameters representation (style=form, explode=false) +/// specified in +/// Should be implemented in a serde serializer +impl std::fmt::Display for NoTypeObject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Converts Query Parameters representation (style=form, explode=false) to a NoTypeObject value +/// as specified in +/// Should be implemented in a serde deserializer +impl ::std::str::FromStr for NoTypeObject { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match std::str::FromStr::from_str(s) { + std::result::Result::Ok(r) => std::result::Result::Ok(NoTypeObject(r)), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {s} to NoTypeObject: {e:?}")), + } + } +} + +// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { + let hdr_value = hdr_value.to_string(); + match hyper::header::HeaderValue::from_str(&hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(e) => std::result::Result::Err( + format!("Invalid header value for NoTypeObject - value: {hdr_value} is invalid {e}")) + } + } +} + +#[cfg(any(feature = "client", feature = "server"))] +impl std::convert::TryFrom for header::IntoHeaderValue { + type Error = String; + + fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result { + match hdr_value.to_str() { + std::result::Result::Ok(value) => { + match ::from_str(value) { + std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{value}' into NoTypeObject - {err}")) + } + }, + std::result::Result::Err(e) => std::result::Result::Err( + format!("Unable to convert header: {hdr_value:?} to string: {e}")) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom>> for hyper::header::HeaderValue { + type Error = String; + + fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { + let hdr_values : Vec = hdr_values.0.into_iter().map(|hdr_value| { + hdr_value.to_string() + }).collect(); + + match hyper::header::HeaderValue::from_str(&hdr_values.join(", ")) { + std::result::Result::Ok(hdr_value) => std::result::Result::Ok(hdr_value), + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to convert {hdr_values:?} into a header - {e}",)) + } + } +} + +#[cfg(feature = "server")] +impl std::convert::TryFrom for header::IntoHeaderValue> { + type Error = String; + + fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result { + match hdr_values.to_str() { + std::result::Result::Ok(hdr_values) => { + let hdr_values : std::vec::Vec = hdr_values + .split(',') + .filter_map(|hdr_value| match hdr_value.trim() { + "" => std::option::Option::None, + hdr_value => std::option::Option::Some({ + match ::from_str(hdr_value) { + std::result::Result::Ok(value) => std::result::Result::Ok(value), + std::result::Result::Err(err) => std::result::Result::Err( + format!("Unable to convert header value '{hdr_value}' into NoTypeObject - {err}")) + } + }) + }).collect::, String>>()?; + + std::result::Result::Ok(header::IntoHeaderValue(hdr_values)) + }, + std::result::Result::Err(e) => std::result::Result::Err(format!("Unable to parse header: {hdr_values:?} as a string - {e}")), + } + } +} + +impl NoTypeObject { + /// Helper function to allow us to convert this model to an XML string. + /// Will panic if serialisation fails. + #[allow(dead_code)] + pub(crate) fn as_xml(&self) -> String { + serde_xml_rs::to_string(&self).expect("impossible to fail to serialize") + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] pub struct NullableObject(String); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs index 5e0dfbd722c4..eb2394e91f18 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs @@ -509,11 +509,14 @@ impl hyper::service::Service<(Request, C)> for Service { // Form parameters let param_required_array = - None; + Vec::new(); + let param_enum_field = + models::FormTestRequestEnumField::OneEnum; let result = api_impl.form_test( param_required_array.as_ref(), + param_enum_field, &context ).await; let mut response = Response::new(BoxBody::new(http_body_util::Empty::new())); diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs index b635a60f7498..8e8aa8e817cf 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs @@ -253,12 +253,12 @@ fn main() { Some("TestEnumParameters") => { let result = rt.block_on(client.test_enum_parameters( Some(&Vec::new()), - None, + Some(models::TestEnumParametersEnumHeaderStringParameter::Abc), Some(&Vec::new()), - None, - None, - None, - None + Some(models::TestEnumParametersEnumHeaderStringParameter::Abc), + Some(models::TestEnumParametersEnumQueryIntegerParameter::Variant1), + Some(models::TestEnumParametersEnumQueryDoubleParameter::Variant11), + Some(models::TestEnumParametersRequestEnumFormString::Abc) )); info!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has).get().clone()); }, diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs index d80bcfda95ef..8a2cfd51efbd 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs @@ -1132,7 +1132,7 @@ impl hyper::service::Service<(Request, C)> for Service { // Form parameters let param_enum_form_string = - None; + Some(models::TestEnumParametersRequestEnumFormString::Abc); let result = api_impl.test_enum_parameters(