Skip to content

Commit 670e9d7

Browse files
authored
[rust] Fixed discriminator causing duplicate enum variants (#20711)
* Fixed discriminator * Added testcase and updated samples
1 parent 79145dc commit 670e9d7

File tree

112 files changed

+2363
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+2363
-0
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@
2222
import java.io.Writer;
2323
import java.math.BigDecimal;
2424
import java.math.BigInteger;
25+
import java.util.ArrayList;
2526
import java.util.Arrays;
2627
import java.util.Collections;
2728
import java.util.EnumSet;
29+
import java.util.HashMap;
2830
import java.util.HashSet;
2931
import java.util.List;
3032
import java.util.Locale;
3133
import java.util.Map;
3234
import java.util.Objects;
3335
import java.util.Optional;
36+
import java.util.Set;
3437
import java.util.stream.Collectors;
3538

3639
import org.openapitools.codegen.CliOption;
@@ -342,6 +345,32 @@ public ModelsMap postProcessModels(ModelsMap objs) {
342345
break;
343346
}
344347
}
348+
349+
// Check if there are duplicate mappings in the discriminator
350+
// ie.
351+
// ```
352+
// mappings:
353+
// student: '#/components/schemas/Person'
354+
// teacher: '#/components/schemas/Person'
355+
// car: '#/components/schemas/Vehicle'
356+
// ```
357+
//
358+
// Should be mapped to an enum with `PersonStudent`, `PersonTeacher`, `Vehicle` to 2 `Person` enum variants. (a compiler error)
359+
if (cm.discriminator.getMapping() != null) {
360+
if (hasDuplicateValues(cm.discriminator.getMapping())) {
361+
var inverted = invertMap(cm.discriminator.getMapping());
362+
for (var s : inverted.entrySet()) {
363+
if (s.getValue().size() > 1) {
364+
LOGGER.debug("Found duplicated enum model (" + s.getKey() + ") in model " + cm.name + ". Adding suffix to model names.");
365+
for (var m : cm.discriminator.getMappedModels()) {
366+
if (s.getValue().contains(m.getMappingName())) {
367+
m.setModelName(m.getModelName() + StringUtils.camelize(m.getMappingName()));
368+
}
369+
}
370+
}
371+
}
372+
}
373+
}
345374
}
346375

347376
// Flag structs with byteArrays in them so that we can annotate them with the serde_as macro
@@ -789,4 +818,18 @@ protected ImmutableMap.Builder<String, Lambda> addMustacheLambdas() {
789818
.put("lifetimeName", new ReplaceAllLambda("^r#", "r_"));
790819
}
791820

821+
public static <K, V> Map<V, List<K>> invertMap(Map<K, V> map) {
822+
Map<V, List<K>> invertedMap = new HashMap<>();
823+
824+
for (Map.Entry<K, V> entry : map.entrySet()) {
825+
invertedMap.computeIfAbsent(entry.getValue(), k -> new ArrayList<>()).add(entry.getKey());
826+
}
827+
828+
return invertedMap;
829+
}
830+
831+
public static <K, V> boolean hasDuplicateValues(Map<K, V> map) {
832+
Set<V> uniqueValues = new HashSet<>(map.values());
833+
return uniqueValues.size() < map.size();
834+
}
792835
}

modules/openapi-generator/src/test/resources/3_0/rust/petstore.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,26 @@ paths:
656656
application/json:
657657
schema:
658658
$ref: '#/components/schemas/TypeTesting'
659+
'/tests/discriminatorDuplicateEnums':
660+
get:
661+
tags:
662+
- testing
663+
summary: 'Test for duplicate enums when using discriminator. (One of the issues in #20500)'
664+
responses:
665+
'200':
666+
description: test
667+
content:
668+
application/json:
669+
schema:
670+
anyOf:
671+
- $ref: '#/components/schemas/Person'
672+
- $ref: '#/components/schemas/Vehicle'
673+
discriminator:
674+
propertyName: objectType
675+
mapping:
676+
student: '#/components/schemas/Person'
677+
teacher: '#/components/schemas/Person'
678+
car: '#/components/schemas/Vehicle'
659679
externalDocs:
660680
description: Find out more about Swagger
661681
url: 'http://swagger.io'
@@ -1014,4 +1034,24 @@ components:
10141034
properties:
10151035
foo: {}
10161036
required: ["foo"]
1037+
Person:
1038+
type: object
1039+
properties:
1040+
type:
1041+
type: string
1042+
name:
1043+
type: string
1044+
required:
1045+
- type
1046+
- name
1047+
Vehicle:
1048+
type: object
1049+
properties:
1050+
type:
1051+
type: string
1052+
speed:
1053+
type: number
1054+
required:
1055+
- type
1056+
- speed
10171057

samples/client/petstore/rust/hyper/petstore/.openapi-generator/FILES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ docs/NullableArray.md
1414
docs/NumericEnumTesting.md
1515
docs/OptionalTesting.md
1616
docs/Order.md
17+
docs/Person.md
1718
docs/Pet.md
1819
docs/PetApi.md
1920
docs/PropertyTest.md
@@ -22,10 +23,12 @@ docs/Return.md
2223
docs/StoreApi.md
2324
docs/Tag.md
2425
docs/TestingApi.md
26+
docs/TestsDiscriminatorDuplicateEnumsGet200Response.md
2527
docs/TypeTesting.md
2628
docs/UniqueItemArrayTesting.md
2729
docs/User.md
2830
docs/UserApi.md
31+
docs/Vehicle.md
2932
git_push.sh
3033
src/apis/client.rs
3134
src/apis/configuration.rs
@@ -37,6 +40,7 @@ src/apis/store_api.rs
3740
src/apis/testing_api.rs
3841
src/apis/user_api.rs
3942
src/lib.rs
43+
src/models/_tests_discriminator_duplicate_enums_get_200_response.rs
4044
src/models/action_container.rs
4145
src/models/any_type_test.rs
4246
src/models/api_response.rs
@@ -51,9 +55,11 @@ src/models/nullable_array.rs
5155
src/models/numeric_enum_testing.rs
5256
src/models/optional_testing.rs
5357
src/models/order.rs
58+
src/models/person.rs
5459
src/models/pet.rs
5560
src/models/property_test.rs
5661
src/models/tag.rs
5762
src/models/type_testing.rs
5863
src/models/unique_item_array_testing.rs
5964
src/models/user.rs
65+
src/models/vehicle.rs

samples/client/petstore/rust/hyper/petstore/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Class | Method | HTTP request | Description
3939
*StoreApi* | [**get_inventory**](docs/StoreApi.md#get_inventory) | **Get** /store/inventory | Returns pet inventories by status
4040
*StoreApi* | [**get_order_by_id**](docs/StoreApi.md#get_order_by_id) | **Get** /store/order/{orderId} | Find purchase order by ID
4141
*StoreApi* | [**place_order**](docs/StoreApi.md#place_order) | **Post** /store/order | Place an order for a pet
42+
*TestingApi* | [**tests_discriminator_duplicate_enums_get**](docs/TestingApi.md#tests_discriminator_duplicate_enums_get) | **Get** /tests/discriminatorDuplicateEnums | Test for duplicate enums when using discriminator. (One of the issues in #20500)
4243
*TestingApi* | [**tests_file_response_get**](docs/TestingApi.md#tests_file_response_get) | **Get** /tests/fileResponse | Returns an image file
4344
*TestingApi* | [**tests_type_testing_get**](docs/TestingApi.md#tests_type_testing_get) | **Get** /tests/typeTesting | Route to test the TypeTesting schema
4445
*UserApi* | [**create_user**](docs/UserApi.md#create_user) | **Post** /user | Create user
@@ -64,14 +65,17 @@ Class | Method | HTTP request | Description
6465
- [NumericEnumTesting](docs/NumericEnumTesting.md)
6566
- [OptionalTesting](docs/OptionalTesting.md)
6667
- [Order](docs/Order.md)
68+
- [Person](docs/Person.md)
6769
- [Pet](docs/Pet.md)
6870
- [PropertyTest](docs/PropertyTest.md)
6971
- [Ref](docs/Ref.md)
7072
- [Return](docs/Return.md)
7173
- [Tag](docs/Tag.md)
74+
- [TestsDiscriminatorDuplicateEnumsGet200Response](docs/TestsDiscriminatorDuplicateEnumsGet200Response.md)
7275
- [TypeTesting](docs/TypeTesting.md)
7376
- [UniqueItemArrayTesting](docs/UniqueItemArrayTesting.md)
7477
- [User](docs/User.md)
78+
- [Vehicle](docs/Vehicle.md)
7579

7680

7781
To get access to the crate's generated documentation, use:
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Person
2+
3+
## Properties
4+
5+
Name | Type | Description | Notes
6+
------------ | ------------- | ------------- | -------------
7+
**r#type** | **String** | |
8+
**name** | **String** | |
9+
10+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
11+
12+

samples/client/petstore/rust/hyper/petstore/docs/TestingApi.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,37 @@ All URIs are relative to *http://petstore.swagger.io/v2*
44

55
Method | HTTP request | Description
66
------------- | ------------- | -------------
7+
[**tests_discriminator_duplicate_enums_get**](TestingApi.md#tests_discriminator_duplicate_enums_get) | **Get** /tests/discriminatorDuplicateEnums | Test for duplicate enums when using discriminator. (One of the issues in #20500)
78
[**tests_file_response_get**](TestingApi.md#tests_file_response_get) | **Get** /tests/fileResponse | Returns an image file
89
[**tests_type_testing_get**](TestingApi.md#tests_type_testing_get) | **Get** /tests/typeTesting | Route to test the TypeTesting schema
910

1011

1112

13+
## tests_discriminator_duplicate_enums_get
14+
15+
> models::TestsDiscriminatorDuplicateEnumsGet200Response tests_discriminator_duplicate_enums_get()
16+
Test for duplicate enums when using discriminator. (One of the issues in #20500)
17+
18+
### Parameters
19+
20+
This endpoint does not need any parameter.
21+
22+
### Return type
23+
24+
[**models::TestsDiscriminatorDuplicateEnumsGet200Response**](_tests_discriminatorDuplicateEnums_get_200_response.md)
25+
26+
### Authorization
27+
28+
No authorization required
29+
30+
### HTTP request headers
31+
32+
- **Content-Type**: Not defined
33+
- **Accept**: application/json
34+
35+
[[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)
36+
37+
1238
## tests_file_response_get
1339

1440
> std::path::PathBuf tests_file_response_get()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# TestsDiscriminatorDuplicateEnumsGet200Response
2+
3+
## Enum Variants
4+
5+
| Name | Value |
6+
|---- | -----|
7+
8+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
9+
10+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Vehicle
2+
3+
## Properties
4+
5+
Name | Type | Description | Notes
6+
------------ | ------------- | ------------- | -------------
7+
**r#type** | **String** | |
8+
**speed** | **f64** | |
9+
10+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
11+
12+

samples/client/petstore/rust/hyper/petstore/src/apis/testing_api.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,21 @@ impl<C: Connect> TestingApiClient<C>
3737
}
3838

3939
pub trait TestingApi: Send + Sync {
40+
fn tests_discriminator_duplicate_enums_get(&self, ) -> Pin<Box<dyn Future<Output = Result<models::TestsDiscriminatorDuplicateEnumsGet200Response, Error>> + Send>>;
4041
fn tests_file_response_get(&self, ) -> Pin<Box<dyn Future<Output = Result<std::path::PathBuf, Error>> + Send>>;
4142
fn tests_type_testing_get(&self, ) -> Pin<Box<dyn Future<Output = Result<models::TypeTesting, Error>> + Send>>;
4243
}
4344

4445
impl<C: Connect>TestingApi for TestingApiClient<C>
4546
where C: Clone + std::marker::Send + Sync {
47+
#[allow(unused_mut)]
48+
fn tests_discriminator_duplicate_enums_get(&self, ) -> Pin<Box<dyn Future<Output = Result<models::TestsDiscriminatorDuplicateEnumsGet200Response, Error>> + Send>> {
49+
let mut req = __internal_request::Request::new(hyper::Method::GET, "/tests/discriminatorDuplicateEnums".to_string())
50+
;
51+
52+
req.execute(self.configuration.borrow())
53+
}
54+
4655
#[allow(unused_mut)]
4756
fn tests_file_response_get(&self, ) -> Pin<Box<dyn Future<Output = Result<std::path::PathBuf, Error>> + Send>> {
4857
let mut req = __internal_request::Request::new(hyper::Method::GET, "/tests/fileResponse".to_string())
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* OpenAPI Petstore
3+
*
4+
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
5+
*
6+
* The version of the OpenAPI document: 1.0.0
7+
*
8+
* Generated by: https://openapi-generator.tech
9+
*/
10+
11+
use crate::models;
12+
use serde::{Deserialize, Serialize};
13+
14+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15+
#[serde(tag = "objectType")]
16+
pub enum TestsDiscriminatorDuplicateEnumsGet200Response {
17+
#[serde(rename="car")]
18+
Vehicle {
19+
#[serde(rename = "type")]
20+
r#type: String,
21+
#[serde(rename = "name")]
22+
name: String,
23+
#[serde(rename = "speed")]
24+
speed: f64,
25+
},
26+
#[serde(rename="student")]
27+
PersonStudent {
28+
#[serde(rename = "type")]
29+
r#type: String,
30+
#[serde(rename = "name")]
31+
name: String,
32+
#[serde(rename = "speed")]
33+
speed: f64,
34+
},
35+
#[serde(rename="teacher")]
36+
PersonTeacher {
37+
#[serde(rename = "type")]
38+
r#type: String,
39+
#[serde(rename = "name")]
40+
name: String,
41+
#[serde(rename = "speed")]
42+
speed: f64,
43+
},
44+
}
45+
46+
impl Default for TestsDiscriminatorDuplicateEnumsGet200Response {
47+
fn default() -> Self {
48+
Self::Vehicle {
49+
r#type: Default::default(),
50+
name: Default::default(),
51+
speed: Default::default(),
52+
}
53+
54+
}
55+
}
56+
57+

0 commit comments

Comments
 (0)