Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,8 @@ private void processParam(CodegenParameter param, CodegenOperation op) {
}
}
} else if (param.isArray) {
param.vendorExtensions.put("x-format-string", "{:?}");
boolean itemsAreEnum = param.items != null && param.items.getIsEnumOrRef();
param.vendorExtensions.put("x-format-string", itemsAreEnum ? "{}" : "{:?}");
if (param.items.isString) {
// We iterate through the list of string and ensure they end up in the format vec!["example".to_string()]
example = (param.example != null)
Expand All @@ -1765,7 +1766,7 @@ private void processParam(CodegenParameter param, CodegenOperation op) {
example = (param.example != null) ? param.example : "&Vec::new()";
}
} else {
param.vendorExtensions.put("x-format-string", "{:?}");
param.vendorExtensions.put("x-format-string", param.getIsEnumOrRef() ? "{}" : "{:?}");
// 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");
Expand Down Expand Up @@ -1798,7 +1799,8 @@ private void processParam(CodegenParameter param, CodegenOperation op) {
param.vendorExtensions.put("x-example", "None");
} else {
// Not required, so override the format string and example
param.vendorExtensions.put("x-format-string", "{:?}");
boolean itemsAreEnum = param.isArray && param.items != null && param.items.getIsEnumOrRef();
param.vendorExtensions.put("x-format-string", (param.getIsEnumOrRef() || itemsAreEnum) ? "{}" : "{:?}");
String exampleString = (example != null) ? "Some(" + example + ")" : "None";
param.vendorExtensions.put("x-example", exampleString);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
{{/allParams}}
context: &C) -> Result<{{{operationId}}}Response, ApiError>
{
info!("{{#exts}}{{{x-operation-id}}}{{/exts}}({{#allParams}}{{#exts}}{{{x-format-string}}}{{/exts}}{{^-last}}, {{/-last}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{{paramName}}}{{/allParams}}, context.get().0.clone());
info!("{{#exts}}{{{x-operation-id}}}{{/exts}}({{#allParams}}{:?}{{^-last}}, {{/-last}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{{paramName}}}{{/allParams}}, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,37 @@ public void testMultipleResponseContentTypes() throws IOException {
target.toFile().deleteOnExit();
}

/**
* Test that enum items inside an array-typed form parameter are serialized using their
* Display impl (i.e. "{}") rather than Debug (i.e. "{:?}"). Both required and optional
* array-of-enum form params must use Display so the wire value matches the OpenAPI enum
* string, not the Rust variant debug representation.
*/
@Test
public void testFormEnumArrayUsesDisplay() throws IOException {
Path target = Files.createTempDirectory("test");
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("rust-server")
.setInputSpec("src/test/resources/3_0/rust-server/form-enum-array.yaml")
.setSkipOverwrite(false)
.setOutputDir(target.toAbsolutePath().toString().replace("\\", "/"));
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
files.forEach(File::deleteOnExit);

Path clientModPath = Path.of(target.toString(), "/src/client/mod.rs");
TestUtils.assertFileExists(clientModPath);

// Both the required and optional array-of-enum params must use "{}" (Display),
// not "{:?}" (Debug), so the serialized string matches the OpenAPI enum value.
TestUtils.assertFileContains(clientModPath, "format!(\"{}\", param_required_enum_array)");
TestUtils.assertFileContains(clientModPath, "format!(\"{}\", param_optional_enum_array)");
TestUtils.assertFileNotContains(clientModPath, "format!(\"{:?}\", param_required_enum_array)");
TestUtils.assertFileNotContains(clientModPath, "format!(\"{:?}\", param_optional_enum_array)");

// Clean up
target.toFile().deleteOnExit();
}

/**
* Test that binary/byte request bodies are passed through as raw bytes rather than being
* coerced to UTF-8, which panics on any non-UTF-8 payload (see issue #24094).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
openapi: "3.0.3"
info:
title: Form Enum Array Test
version: "1.0.0"
paths:
/form-enum-array:
post:
operationId: FormEnumArray
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
required_enum_array:
type: array
items:
type: string
enum:
- value_one
- value_two
optional_enum_array:
type: array
items:
type: string
enum:
- value_one
- value_two
required:
- required_enum_array
responses:
'200':
description: OK
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
object_field: Option<models::MultipartRequestObjectField>,
context: &C) -> Result<MultipartRequestPostResponse, ApiError>
{
info!("multipart_request_post(\"{}\", {:?}, {:?}, {:?}) - X-Span-ID: {:?}", string_field, binary_field, optional_string_field, object_field, context.get().0.clone());
info!("multipart_request_post({:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", string_field, binary_field, optional_string_field, object_field, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
url: String,
context: &C) -> Result<CallbackWithHeaderPostResponse, ApiError>
{
info!("callback_with_header_post(\"{}\") - X-Span-ID: {:?}", url, context.get().0.clone());
info!("callback_with_header_post({:?}) - X-Span-ID: {:?}", url, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -232,7 +232,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
iambool: bool,
context: &C) -> Result<GetWithBooleanParameterResponse, ApiError>
{
info!("get_with_boolean_parameter({}) - X-Span-ID: {:?}", iambool, context.get().0.clone());
info!("get_with_boolean_parameter({:?}) - X-Span-ID: {:?}", iambool, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -250,7 +250,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
x_header: String,
context: &C) -> Result<MandatoryRequestHeaderGetResponse, ApiError>
{
info!("mandatory_request_header_get(\"{}\") - X-Span-ID: {:?}", x_header, context.get().0.clone());
info!("mandatory_request_header_get({:?}) - X-Span-ID: {:?}", x_header, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -324,7 +324,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
required_with_example: i32,
context: &C) -> Result<QueryExampleGetResponse, ApiError>
{
info!("query_example_get(\"{}\", {}) - X-Span-ID: {:?}", required_no_example, required_with_example, context.get().0.clone());
info!("query_example_get({:?}, {:?}) - X-Span-ID: {:?}", required_no_example, required_with_example, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -341,7 +341,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
url: String,
context: &C) -> Result<RegisterCallbackPostResponse, ApiError>
{
info!("register_callback_post(\"{}\") - X-Span-ID: {:?}", url, context.get().0.clone());
info!("register_callback_post({:?}) - X-Span-ID: {:?}", url, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -467,7 +467,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
path_param_b: String,
context: &C) -> Result<MultiplePathParamsWithVeryLongPathToTestFormattingPathParamAPathParamBGetResponse, ApiError>
{
info!("multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get(\"{}\", \"{}\") - X-Span-ID: {:?}", path_param_a, path_param_b, context.get().0.clone());
info!("multiple_path_params_with_very_long_path_to_test_formatting_path_param_a_path_param_b_get({:?}, {:?}) - X-Span-ID: {:?}", path_param_a, path_param_b, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -485,7 +485,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
repo_id: String,
context: &C) -> Result<GetRepoInfoResponse, ApiError>
{
info!("get_repo_info(\"{}\") - X-Span-ID: {:?}", repo_id, context.get().0.clone());
info!("get_repo_info({:?}) - X-Span-ID: {:?}", repo_id, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ impl<S, C, B> Api<C> for Client<S, C> where
}
#[allow(clippy::uninlined_format_args)]
params.push(("enum_field",
format!("{:?}", param_enum_field)
format!("{}", param_enum_field)
));

let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
body: models::User,
context: &C) -> Result<TestBodyWithQueryParamsResponse, ApiError>
{
info!("test_body_with_query_params(\"{}\", {:?}) - X-Span-ID: {:?}", query, body, context.get().0.clone());
info!("test_body_with_query_params({:?}, {:?}) - X-Span-ID: {:?}", query, body, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -281,7 +281,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
callback: Option<String>,
context: &C) -> Result<TestEndpointParametersResponse, ApiError>
{
info!("test_endpoint_parameters({}, {}, \"{}\", {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, context.get().0.clone());
info!("test_endpoint_parameters({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -318,7 +318,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
param2: String,
context: &C) -> Result<TestJsonFormDataResponse, ApiError>
{
info!("test_json_form_data(\"{}\", \"{}\") - X-Span-ID: {:?}", param, param2, context.get().0.clone());
info!("test_json_form_data({:?}, {:?}) - X-Span-ID: {:?}", param, param2, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -327,7 +327,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
hyphen_param: String,
context: &C) -> Result<HyphenParamResponse, ApiError>
{
info!("hyphen_param(\"{}\") - X-Span-ID: {:?}", hyphen_param, context.get().0.clone());
info!("hyphen_param({:?}) - X-Span-ID: {:?}", hyphen_param, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -388,7 +388,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
api_key: Option<String>,
context: &C) -> Result<DeletePetResponse, ApiError>
{
info!("delete_pet({}, {:?}) - X-Span-ID: {:?}", pet_id, api_key, context.get().0.clone());
info!("delete_pet({:?}, {:?}) - X-Span-ID: {:?}", pet_id, api_key, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -398,7 +398,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
pet_id: i64,
context: &C) -> Result<GetPetByIdResponse, ApiError>
{
info!("get_pet_by_id({}) - X-Span-ID: {:?}", pet_id, context.get().0.clone());
info!("get_pet_by_id({:?}) - X-Span-ID: {:?}", pet_id, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -410,7 +410,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
status: Option<String>,
context: &C) -> Result<UpdatePetWithFormResponse, ApiError>
{
info!("update_pet_with_form({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, name, status, context.get().0.clone());
info!("update_pet_with_form({:?}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, name, status, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -422,7 +422,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
file: Option<swagger::ByteArray>,
context: &C) -> Result<UploadFileResponse, ApiError>
{
info!("upload_file({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, additional_metadata, file, context.get().0.clone());
info!("upload_file({:?}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, additional_metadata, file, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -451,7 +451,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
order_id: String,
context: &C) -> Result<DeleteOrderResponse, ApiError>
{
info!("delete_order(\"{}\") - X-Span-ID: {:?}", order_id, context.get().0.clone());
info!("delete_order({:?}) - X-Span-ID: {:?}", order_id, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -461,7 +461,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
order_id: u64,
context: &C) -> Result<GetOrderByIdResponse, ApiError>
{
info!("get_order_by_id({}) - X-Span-ID: {:?}", order_id, context.get().0.clone());
info!("get_order_by_id({:?}) - X-Span-ID: {:?}", order_id, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down Expand Up @@ -502,7 +502,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
password: String,
context: &C) -> Result<LoginUserResponse, ApiError>
{
info!("login_user(\"{}\", \"{}\") - X-Span-ID: {:?}", username, password, context.get().0.clone());
info!("login_user({:?}, {:?}) - X-Span-ID: {:?}", username, password, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -521,7 +521,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
username: String,
context: &C) -> Result<DeleteUserResponse, ApiError>
{
info!("delete_user(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone());
info!("delete_user({:?}) - X-Span-ID: {:?}", username, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -531,7 +531,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
username: String,
context: &C) -> Result<GetUserByNameResponse, ApiError>
{
info!("get_user_by_name(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone());
info!("get_user_by_name({:?}) - X-Span-ID: {:?}", username, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -542,7 +542,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
body: models::User,
context: &C) -> Result<UpdateUserResponse, ApiError>
{
info!("update_user(\"{}\", {:?}) - X-Span-ID: {:?}", username, body, context.get().0.clone());
info!("update_user({:?}, {:?}) - X-Span-ID: {:?}", username, body, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,7 @@ impl<S, C, B> Api<C> for Client<S, C> where
if let Some(param_enum_form_string) = param_enum_form_string {
#[allow(clippy::uninlined_format_args)]
params.push(("enum_form_string",
format!("{:?}", param_enum_form_string)
format!("{}", param_enum_form_string)
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
body: String,
context: &C) -> Result<HtmlPostResponse, ApiError>
{
info!("html_post(\"{}\") - X-Span-ID: {:?}", body, context.get().0.clone());
info!("html_post({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand All @@ -212,7 +212,7 @@ impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
value: String,
context: &C) -> Result<PostYamlResponse, ApiError>
{
info!("post_yaml(\"{}\") - X-Span-ID: {:?}", value, context.get().0.clone());
info!("post_yaml({:?}) - X-Span-ID: {:?}", value, context.get().0.clone());
Err(ApiError("Api-Error: Operation is NOT implemented".into()))
}

Expand Down
Loading