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
2 changes: 2 additions & 0 deletions docs/generators/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ These options may be applied as additional-properties (cli) or configOptions (pl

| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|bestFitInt|Use best fitting integer type where minimum or maximum is set| |false|
|enumNameSuffix|Suffix that will be appended to all enum names.| ||
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
|library|library template (sub-template) to use.|<dl><dt>**hyper**</dt><dd>HTTP client: Hyper.</dd><dt>**reqwest**</dt><dd>HTTP client: Reqwest.</dd></dl>|reqwest|
|packageName|Rust package name (convention: lowercase).| |openapi|
|packageVersion|Rust package version.| |1.0.0|
|preferUnsignedInt|Prefer unsigned integers where minimum value is &gt;= 0| |false|
|supportAsync|If set, generate async function call instead. This option is for 'reqwest' library only| |true|
|supportMultipleResponses|If set, return type wraps an enum of all possible 2xx schemas. This option is for 'reqwest' library only| |false|
|useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.*;

import static org.openapitools.codegen.utils.StringUtils.camelize;
Expand All @@ -50,13 +51,17 @@ public class RustClientCodegen extends DefaultCodegen implements CodegenConfig {
private boolean supportAsync = true;
private boolean supportMultipleResponses = false;
private boolean withAWSV4Signature = false;
private boolean preferUnsignedInt = false;
private boolean bestFitInt = false;

public static final String PACKAGE_NAME = "packageName";
public static final String PACKAGE_VERSION = "packageVersion";
public static final String HYPER_LIBRARY = "hyper";
public static final String REQWEST_LIBRARY = "reqwest";
public static final String SUPPORT_ASYNC = "supportAsync";
public static final String SUPPORT_MULTIPLE_RESPONSES = "supportMultipleResponses";
public static final String PREFER_UNSIGNED_INT = "preferUnsignedInt";
public static final String BEST_FIT_INT = "bestFitInt";

protected String packageName = "openapi";
protected String packageVersion = "1.0.0";
Expand All @@ -65,6 +70,7 @@ public class RustClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiFolder = "src/apis";
protected String modelFolder = "src/models";
protected String enumSuffix = ""; // default to empty string for backward compatibility
protected Map<String, String> unsignedMapping;

public CodegenType getTag() {
return CodegenType.CLIENT;
Expand Down Expand Up @@ -174,6 +180,12 @@ public RustClientCodegen() {
typeMapping.put("object", "serde_json::Value");
typeMapping.put("AnyType", "serde_json::Value");

unsignedMapping = new HashMap<>();
unsignedMapping.put("i8", "u8");
unsignedMapping.put("i16", "u16");
unsignedMapping.put("i32", "u32");
unsignedMapping.put("i64", "u64");

// no need for rust
//importMapping = new HashMap<String, String>();

Expand All @@ -193,6 +205,10 @@ public RustClientCodegen() {
cliOptions.add(new CliOption(CodegenConstants.ENUM_NAME_SUFFIX, CodegenConstants.ENUM_NAME_SUFFIX_DESC).defaultValue(this.enumSuffix));
cliOptions.add(new CliOption(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT_DESC, SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(PREFER_UNSIGNED_INT, "Prefer unsigned integers where minimum value is >= 0", SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(BEST_FIT_INT, "Use best fitting integer type where minimum or maximum is set", SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.FALSE.toString()));

supportedLibraries.put(HYPER_LIBRARY, "HTTP client: Hyper.");
supportedLibraries.put(REQWEST_LIBRARY, "HTTP client: Reqwest.");
Expand Down Expand Up @@ -296,6 +312,16 @@ public void processOpts() {
}
writePropertyBack(SUPPORT_MULTIPLE_RESPONSES, getSupportMultipleReturns());

if (additionalProperties.containsKey(PREFER_UNSIGNED_INT)) {
this.setPreferUnsignedInt(convertPropertyToBoolean(PREFER_UNSIGNED_INT));
}
writePropertyBack(PREFER_UNSIGNED_INT, getPreferUnsignedInt());

if (additionalProperties.containsKey(BEST_FIT_INT)) {
this.setBestFitInt(convertPropertyToBoolean(BEST_FIT_INT));
}
writePropertyBack(BEST_FIT_INT, getBestFitInt());

additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);

Expand Down Expand Up @@ -360,6 +386,22 @@ public void setSupportMultipleReturns(boolean supportMultipleResponses) {
this.supportMultipleResponses = supportMultipleResponses;
}

public boolean getPreferUnsignedInt() {
return preferUnsignedInt;
}

public void setPreferUnsignedInt(boolean preferUnsignedInt) {
this.preferUnsignedInt = preferUnsignedInt;
}

public boolean getBestFitInt() {
return bestFitInt;
}

public void setBestFitInt(boolean bestFitInt) {
this.bestFitInt = bestFitInt;
}

private boolean getUseSingleRequestParameter() {
return useSingleRequestParameter;
}
Expand Down Expand Up @@ -414,7 +456,8 @@ public String toVarName(String name) {

@Override
public String toParamName(String name) {
return toVarName(name);
// $ref appears to be all uppercase which is contrary to rustfmt practice so lowercase parameters
return toVarName(name.toLowerCase(Locale.ROOT));
Copy link
Member

@wing328 wing328 Jul 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #12820

}

@Override
Expand Down Expand Up @@ -525,10 +568,44 @@ public String getTypeDeclaration(Schema p) {
@Override
public String getSchemaType(Schema p) {
String schemaType = super.getSchemaType(p);
if (typeMapping.containsKey(schemaType)) {
return typeMapping.get(schemaType);
String type = typeMapping.getOrDefault(schemaType, schemaType);

boolean bestFit = convertPropertyToBoolean(BEST_FIT_INT);
boolean unsigned = convertPropertyToBoolean(PREFER_UNSIGNED_INT);

if (bestFit || unsigned) {
BigDecimal maximum = p.getMaximum();
BigDecimal minimum = p.getMinimum();

try {
if (maximum != null && minimum != null) {
long max = maximum.longValueExact();
long min = minimum.longValueExact();

if (unsigned && bestFit && max <= (Byte.MAX_VALUE * 2) + 1 && min >= 0) {
type = "u8";
} else if (bestFit && max <= Byte.MAX_VALUE && min >= Byte.MIN_VALUE) {
type = "i8";
} else if (unsigned && bestFit && max <= (Short.MAX_VALUE * 2) + 1 && min >= 0) {
type = "u16";
} else if (bestFit && max <= Short.MAX_VALUE && min >= Short.MIN_VALUE) {
type = "i16";
} else if (unsigned && bestFit && max <= (Integer.MAX_VALUE * 2L) + 1 && min >= 0) {
type = "u32";
} else if (bestFit && max <= Integer.MAX_VALUE && min >= Integer.MIN_VALUE) {
type = "i32";
}
}
} catch (ArithmeticException a) {
// no-op; case will be handled in the next if block
}

if (unsigned && minimum != null && minimum.compareTo(BigDecimal.ZERO) >= 0 && unsignedMapping.containsKey(type)) {
type = unsignedMapping.get(type);
}
}
return schemaType;

return type;
}

@Override
Expand Down Expand Up @@ -640,7 +717,6 @@ public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}


@Override
public String toEnumValue(String value, String datatype) {
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
Expand Down
3 changes: 3 additions & 0 deletions modules/openapi-generator/src/main/resources/rust/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,19 @@ impl Request {
self
}

#[allow(unused)]
pub fn with_query_param(mut self, basename: String, param: String) -> Self {
self.query_params.insert(basename, param);
self
}

#[allow(unused)]
pub fn with_path_param(mut self, basename: String, param: String) -> Self {
self.path_params.insert(basename, param);
self
}

#[allow(unused)]
pub fn with_form_param(mut self, basename: String, param: String) -> Self {
self.form_params.insert(basename, param);
self
Expand Down
Loading