Skip to content

Commit ec51326

Browse files
fix(rust-axum): fix uint32/uint64 type mapping
1 parent c07f3a0 commit ec51326

3 files changed

Lines changed: 200 additions & 6 deletions

File tree

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

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.slf4j.LoggerFactory;
4545

4646
import java.io.File;
47+
import java.math.BigDecimal;
4748
import java.math.BigInteger;
4849
import java.nio.file.Path;
4950
import java.util.*;
@@ -1024,6 +1025,63 @@ public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, S
10241025
return codegenParameter;
10251026
}
10261027

1028+
private String getIntegerDataType(String format,
1029+
BigInteger minimum,
1030+
boolean exclusiveMinimum,
1031+
BigInteger maximum,
1032+
boolean exclusiveMaximum,
1033+
boolean explicitUnsigned) {
1034+
boolean unsigned = explicitUnsigned || canFitIntoUnsigned(minimum, exclusiveMinimum);
1035+
1036+
if (StringUtils.isEmpty(format)) {
1037+
return bestFittingIntegerType(
1038+
minimum,
1039+
exclusiveMinimum,
1040+
maximum,
1041+
exclusiveMaximum,
1042+
true);
1043+
}
1044+
1045+
switch (format) {
1046+
// custom integer formats (legacy)
1047+
case "uint32":
1048+
return "u32";
1049+
case "uint64":
1050+
return "u64";
1051+
case "int32":
1052+
return unsigned ? "u32" : "i32";
1053+
case "int64":
1054+
return unsigned ? "u64" : "i64";
1055+
default:
1056+
LOGGER.warn("The integer format '{}' is not recognized and will be ignored.", format);
1057+
return bestFittingIntegerType(
1058+
minimum,
1059+
exclusiveMinimum,
1060+
maximum,
1061+
exclusiveMaximum,
1062+
true);
1063+
}
1064+
}
1065+
1066+
@Override
1067+
public String getSchemaType(Schema p) {
1068+
if (Objects.equals(p.getType(), "integer")) {
1069+
BigInteger minimum = Optional.ofNullable(p.getMinimum()).map(BigDecimal::toBigInteger).orElse(null);
1070+
BigInteger maximum = Optional.ofNullable(p.getMaximum()).map(BigDecimal::toBigInteger).orElse(null);
1071+
boolean explicitUnsigned = ModelUtils.isUnsignedIntegerSchema(p) || ModelUtils.isUnsignedLongSchema(p);
1072+
1073+
return getIntegerDataType(
1074+
p.getFormat(),
1075+
minimum,
1076+
Optional.ofNullable(p.getExclusiveMinimum()).orElse(false),
1077+
maximum,
1078+
Optional.ofNullable(p.getExclusiveMaximum()).orElse(false),
1079+
explicitUnsigned);
1080+
}
1081+
1082+
return super.getSchemaType(p);
1083+
}
1084+
10271085
@Override
10281086
public String toInstantiationType(final Schema p) {
10291087
if (ModelUtils.isArraySchema(p)) {
@@ -1113,13 +1171,17 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
11131171
}
11141172

11151173
// Integer type fitting
1116-
if (Objects.equals(property.baseType, "integer")) {
1174+
if (Boolean.TRUE.equals(property.isInteger) || Boolean.TRUE.equals(property.isLong) || Objects.equals(property.baseType, "UnsignedInteger") || Objects.equals(property.baseType, "UnsignedLong")) {
11171175
BigInteger minimum = Optional.ofNullable(property.getMinimum()).map(BigInteger::new).orElse(null);
11181176
BigInteger maximum = Optional.ofNullable(property.getMaximum()).map(BigInteger::new).orElse(null);
1119-
property.dataType = bestFittingIntegerType(
1120-
minimum, property.getExclusiveMinimum(),
1121-
maximum, property.getExclusiveMaximum(),
1122-
true);
1177+
boolean explicitUnsigned = Objects.equals(property.baseType, "UnsignedInteger") || Objects.equals(property.baseType, "UnsignedLong");
1178+
property.dataType = getIntegerDataType(
1179+
property.dataFormat,
1180+
minimum,
1181+
property.getExclusiveMinimum(),
1182+
maximum,
1183+
property.getExclusiveMaximum(),
1184+
explicitUnsigned);
11231185
}
11241186

11251187
property.name = underscore(property.name);

modules/openapi-generator/src/test/java/org/openapitools/codegen/rust/RustAxumServerCodegenTest.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package org.openapitools.codegen.rust;
22

3+
import io.swagger.v3.oas.models.media.IntegerSchema;
34
import org.openapitools.codegen.DefaultGenerator;
45
import org.openapitools.codegen.TestUtils;
56
import org.openapitools.codegen.config.CodegenConfigurator;
7+
import org.openapitools.codegen.languages.RustAxumServerCodegen;
8+
import org.testng.Assert;
69
import org.testng.annotations.Test;
710

811
import java.io.File;
912
import java.io.IOException;
13+
import java.math.BigDecimal;
1014
import java.nio.file.Files;
1115
import java.nio.file.Path;
16+
import java.util.HashMap;
1217
import java.util.List;
1318

1419
import static org.openapitools.codegen.TestUtils.linearize;
@@ -49,4 +54,53 @@ public void testPreventDuplicateOperationDeclaration() throws IOException {
4954
TestUtils.assertFileExists(outputPath);
5055
TestUtils.assertFileContains(outputPath, routerSpec);
5156
}
52-
}
57+
58+
@Test
59+
public void testIntegerSchemaTypeMapping() {
60+
RustAxumServerCodegen codegen = new RustAxumServerCodegen();
61+
IntegerSchema schema = new IntegerSchema();
62+
63+
schema.setFormat("uint32");
64+
Assert.assertEquals(codegen.getSchemaType(schema), "u32");
65+
66+
schema.setFormat("uint64");
67+
Assert.assertEquals(codegen.getSchemaType(schema), "u64");
68+
69+
schema.setFormat("int32");
70+
schema.setMinimum(BigDecimal.ZERO);
71+
Assert.assertEquals(codegen.getSchemaType(schema), "u32");
72+
73+
schema.setFormat("int64");
74+
Assert.assertEquals(codegen.getSchemaType(schema), "u64");
75+
76+
schema.setFormat(null);
77+
schema.setMaximum(BigDecimal.valueOf(255));
78+
Assert.assertEquals(codegen.getSchemaType(schema), "u8");
79+
80+
schema.setExtensions(new HashMap<>());
81+
schema.getExtensions().put("x-unsigned", true);
82+
schema.setMaximum(null);
83+
Assert.assertEquals(codegen.getSchemaType(schema), "u32");
84+
}
85+
86+
@Test
87+
public void testGeneratedIntegerTypes() throws IOException {
88+
Path target = Files.createTempDirectory("test");
89+
final CodegenConfigurator configurator = new CodegenConfigurator()
90+
.setGeneratorName("rust-axum")
91+
.setInputSpec("src/test/resources/3_0/rust-axum/integer-types.yaml")
92+
.setSkipOverwrite(false)
93+
.setOutputDir(target.toAbsolutePath().toString().replace("\\", "/"));
94+
List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
95+
files.forEach(File::deleteOnExit);
96+
97+
Path modelsPath = Path.of(target.toString(), "/src/models.rs");
98+
TestUtils.assertFileExists(modelsPath);
99+
TestUtils.assertFileContains(modelsPath, "pub legacy_uint32: u32");
100+
TestUtils.assertFileContains(modelsPath, "pub legacy_uint64: u64");
101+
TestUtils.assertFileContains(modelsPath, "pub positive_int32: u32");
102+
TestUtils.assertFileContains(modelsPath, "pub positive_int64: u64");
103+
TestUtils.assertFileContains(modelsPath, "pub small_positive: u8");
104+
TestUtils.assertFileContains(modelsPath, "pub struct GetIntegersQueryParams");
105+
}
106+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
openapi: 3.0.3
2+
info:
3+
title: Rust Axum Integer Type Mapping Test
4+
version: 1.0.0
5+
paths:
6+
/integers:
7+
get:
8+
operationId: getIntegers
9+
parameters:
10+
- name: legacy_uint32
11+
in: query
12+
required: true
13+
schema:
14+
type: integer
15+
format: uint32
16+
- name: legacy_uint64
17+
in: query
18+
required: true
19+
schema:
20+
type: integer
21+
format: uint64
22+
- name: positive_int32
23+
in: query
24+
required: true
25+
schema:
26+
type: integer
27+
format: int32
28+
minimum: 0
29+
- name: positive_int64
30+
in: query
31+
required: true
32+
schema:
33+
type: integer
34+
format: int64
35+
minimum: 0
36+
- name: small_positive
37+
in: query
38+
required: true
39+
schema:
40+
type: integer
41+
minimum: 0
42+
maximum: 255
43+
responses:
44+
'200':
45+
description: OK
46+
content:
47+
application/json:
48+
schema:
49+
$ref: '#/components/schemas/IntegerTypes'
50+
components:
51+
schemas:
52+
IntegerTypes:
53+
type: object
54+
required:
55+
- legacy_uint32
56+
- legacy_uint64
57+
- positive_int32
58+
- positive_int64
59+
- small_positive
60+
properties:
61+
legacy_uint32:
62+
type: integer
63+
format: uint32
64+
legacy_uint64:
65+
type: integer
66+
format: uint64
67+
positive_int32:
68+
type: integer
69+
format: int32
70+
minimum: 0
71+
positive_int64:
72+
type: integer
73+
format: int64
74+
minimum: 0
75+
small_positive:
76+
type: integer
77+
minimum: 0
78+
maximum: 255

0 commit comments

Comments
 (0)