Skip to content
Open
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
11 changes: 11 additions & 0 deletions bin/configs/rust-reqwest-petstore-no-chrono.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
generatorName: rust
outputDir: samples/client/petstore/rust/reqwest/petstore-no-chrono
library: reqwest
inputSpec: modules/openapi-generator/src/test/resources/3_0/rust/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/rust
additionalProperties:
supportAsync: false
useChrono: false
packageName: petstore-reqwest-no-chrono
enumNameMappings:
delivered: shipped
1 change: 1 addition & 0 deletions docs/generators/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|supportTokenSource|If set, add support for google-cloud-token. This option is for 'reqwest' and 'reqwest-trait' library only and requires the 'supportAsync' option| |false|
|topLevelApiClient|Creates a top level `Api` trait and `ApiClient` struct that contain all Apis. This option is for 'reqwest-trait' library only| |false|
|useBonBuilder|Use the bon crate for building parameter types. This option is for the 'reqwest-trait' library only| |false|
|useChrono|If set, use chrono to represent date time objects (`chrono::NaiveDate` for `date` and `chrono::DateTime<chrono::FixedOffset>>` for `date-time`)| |true|
|useSerdePathToError|If set, use the serde_path_to_error library to enhance serde error messages. This option is for 'reqwest' and 'reqwest-trait' 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|
|withAWSV4Signature|whether to include AWS v4 signature support| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class RustClientCodegen extends AbstractRustCodegen implements CodegenConfig {
Expand All @@ -54,6 +55,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
@Setter(AccessLevel.PRIVATE) private boolean supportMiddleware = false;
@Setter(AccessLevel.PRIVATE) private boolean useSerdePathToError = false;
@Setter(AccessLevel.PRIVATE) private boolean supportTokenSource = false;
private boolean useChrono = true;
private boolean supportMultipleResponses = false;
private boolean withAWSV4Signature = false;
@Setter private boolean preferUnsignedInt = false;
Expand All @@ -73,6 +75,7 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
public static final String SUPPORT_MIDDLEWARE = "supportMiddleware";
public static final String USE_SERDE_PATH_TO_ERROR = "useSerdePathToError";
public static final String SUPPORT_TOKEN_SOURCE = "supportTokenSource";
public static final String USE_CHRONO = "useChrono";
public static final String SUPPORT_MULTIPLE_RESPONSES = "supportMultipleResponses";
public static final String PREFER_UNSIGNED_INT = "preferUnsignedInt";
public static final String BEST_FIT_INT = "bestFitInt";
Expand All @@ -91,6 +94,9 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
// The API has at least one UUID type.
// If the API does not contain any UUIDs we do not need depend on the `uuid` crate
private boolean hasUUIDs = false;
// The API has at least one Chrono type.
// If the API does not contain any Dates or DateTimes we do not need to depend on the `chrono` crate
private boolean usesChronoTypes = false;

@Override
public CodegenType getTag() {
Expand Down Expand Up @@ -182,8 +188,10 @@ public RustClientCodegen() {
typeMapping.put("map", "std::collections::HashMap");
typeMapping.put("UUID", "uuid::Uuid");
typeMapping.put("URI", "String");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "String");
// Temporarily set the default to chrono. Then when `processOpts` is called it will update to not use chrono if specified
typeMapping.put("date", "chrono::NaiveDate");
typeMapping.put("DateTime", "chrono::DateTime<chrono::FixedOffset>");

typeMapping.put("password", "String");
typeMapping.put("decimal", "String");

Expand Down Expand Up @@ -216,6 +224,8 @@ public RustClientCodegen() {
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(SUPPORT_TOKEN_SOURCE, "If set, add support for google-cloud-token. This option is for 'reqwest' and 'reqwest-trait' library only and requires the 'supportAsync' option", SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(USE_CHRONO, "If set, use chrono to represent date time objects (`chrono::NaiveDate` for `date` and `chrono::DateTime<chrono::FixedOffset>>` for `date-time`)", SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(SUPPORT_MULTIPLE_RESPONSES, "If set, return type wraps an enum of all possible 2xx schemas. This option is for 'reqwest' and 'reqwest-trait' library only", SchemaTypeUtil.BOOLEAN_TYPE)
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(CodegenConstants.ENUM_NAME_SUFFIX, CodegenConstants.ENUM_NAME_SUFFIX_DESC).defaultValue(this.enumSuffix));
Expand Down Expand Up @@ -463,6 +473,11 @@ public void processOpts() {
}
writePropertyBack(SUPPORT_TOKEN_SOURCE, getSupportTokenSource());

if (additionalProperties.containsKey(USE_CHRONO)) {
this.setUseChrono(convertPropertyToBoolean(USE_CHRONO));
}
writePropertyBack(USE_CHRONO, isUseChrono());

if (additionalProperties.containsKey(SUPPORT_MULTIPLE_RESPONSES)) {
this.setSupportMultipleReturns(convertPropertyToBoolean(SUPPORT_MULTIPLE_RESPONSES));
}
Expand Down Expand Up @@ -772,12 +787,23 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
}
}

// Check for UUIDs
for (var param : operation.allParams) {
if (!hasUUIDs && param.isUuid) {
hasUUIDs = true;
break;
}
}
// Check for Chrono Types
if(isUseChrono()){
for (CodegenParameter param : operation.allParams) {
if (!usesChronoTypes && (param.isDate || param.isDateTime)) {
LOGGER.debug("Found Chrono Type in operation Parameter: {}", param.paramName);
usesChronoTypes = true;
break;
}
}
}

// If we use a file body parameter, we need to include the imports and crates for it
// But they should be added only once per file
Expand Down Expand Up @@ -874,32 +900,61 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
CodegenModel m = map.getModel();
if (m.getIsUuid() || hasUuidInProperties(m.vars)) {
hasUUIDs = true;
LOGGER.debug("found UUID in model: " + m.name);
LOGGER.debug("Found UUID in model: {}", m.name);
break;
}
}
}

if (isUseChrono() && !usesChronoTypes) {
for (var map : allModels) {
CodegenModel m = map.getModel();
if (m.getIsDate() || hasChronoTypeInProperties(m.vars)) {
usesChronoTypes = true;
LOGGER.debug("Found Chrono Type in model: {}", m.name);
break;
}
}
}

this.additionalProperties.put("hasUUIDs", hasUUIDs);
this.additionalProperties.put("usesChronoTypes", isUseChrono() && usesChronoTypes);
return objs;
}

/**
* Recursively searches for a model's properties for a UUID type field.
*/
private boolean hasUuidInProperties(List<CodegenProperty> properties) {
return checkForPropertiesRecursively(properties, (property) -> property.isUuid);
}

/**
* Recursively searches for a model's properties for a Date or DateTime type field.
*/
private boolean hasChronoTypeInProperties(List<CodegenProperty> properties) {
return checkForPropertiesRecursively(properties, (property) -> property.isDate || property.isDateTime);
}

/**
* Recursively searches for a condition in a property
* @param properties the {@link CodegenProperty} to recursively search for
* @param propertyCheck the {@link Function} to be applied to check an individual {@link CodegenProperty} for a match
* @return true if there is at least one match, false if there is no match
*/
private boolean checkForPropertiesRecursively(List<CodegenProperty> properties, Function<CodegenProperty, Boolean> propertyCheck){
for (CodegenProperty property : properties) {
if (property.isUuid) {
if (propertyCheck.apply(property)) {
return true;
}
// Check nested properties
if (property.items != null && hasUuidInProperties(Collections.singletonList(property.items))) {
if (property.items != null && checkForPropertiesRecursively(Collections.singletonList(property.items), propertyCheck)) {
return true;
}
if (property.additionalProperties != null && hasUuidInProperties(Collections.singletonList(property.additionalProperties))) {
if (property.additionalProperties != null && checkForPropertiesRecursively(Collections.singletonList(property.additionalProperties), propertyCheck)) {
return true;
}
if (property.vars != null && hasUuidInProperties(property.vars)) {
if (property.vars != null && checkForPropertiesRecursively(property.vars, propertyCheck)) {
return true;
}
}
Expand Down Expand Up @@ -938,4 +993,20 @@ public static <K, V> boolean hasDuplicateValues(Map<K, V> map) {
Set<V> uniqueValues = new HashSet<>(map.values());
return uniqueValues.size() < map.size();
}


private boolean isUseChrono() {
return useChrono;
}

private void setUseChrono(boolean useChrono) {
this.useChrono = useChrono;
if(isUseChrono()){
typeMapping.put("date", "chrono::NaiveDate");
typeMapping.put("DateTime", "chrono::DateTime<chrono::FixedOffset>");
}else{
typeMapping.put("date", "String");
typeMapping.put("DateTime", "String");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ url = "^2.5"
{{#hasUUIDs}}
uuid = { version = "^1.8", features = ["serde", "v4"] }
{{/hasUUIDs}}
{{#usesChronoTypes}}
chrono = { version = "^0.4", features = ["serde"] }
{{/usesChronoTypes}}
{{#hyper}}
{{#hyper0x}}
hyper = { version = "~0.14", features = ["full"] }
Expand Down
1 change: 1 addition & 0 deletions samples/client/petstore/rust/hyper/petstore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
hyper = { version = "^1.3.1", features = ["full"] }
hyper-util = { version = "0.1.5", features = ["client", "client-legacy", "http1", "http2"] }
http-body-util = { version = "0.1.2" }
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/rust/hyper/petstore/docs/Order.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
1 change: 1 addition & 0 deletions samples/client/petstore/rust/hyper0x/petstore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
hyper = { version = "~0.14", features = ["full"] }
hyper-tls = "~0.5"
http = "~0.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
async-trait = "^0.1"
reqwest = { version = "^0.13", default-features = false, features = ["json", "multipart", "stream", "query", "form"] }
mockall = { version = "^0.13", optional = true}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
tokio = { version = "^1.46.0", features = ["fs"] }
tokio-util = { version = "^0.7", features = ["codec"] }
reqwest = { version = "^0.13", default-features = false, features = ["json", "multipart", "stream", "query", "form"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
tokio = { version = "^1.46.0", features = ["fs"] }
tokio-util = { version = "^0.7", features = ["codec"] }
reqwest = { version = "^0.13", default-features = false, features = ["json", "multipart", "stream", "query", "form"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
tokio = { version = "^1.46.0", features = ["fs"] }
tokio-util = { version = "^0.7", features = ["codec"] }
reqwest = { version = "^0.13", default-features = false, features = ["json", "multipart", "stream", "query", "form"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "^1.0"
serde_repr = "^0.1"
url = "^2.5"
uuid = { version = "^1.8", features = ["serde", "v4"] }
chrono = { version = "^0.4", features = ["serde"] }
tokio = { version = "^1.46.0", features = ["fs"] }
tokio-util = { version = "^0.7", features = ["codec"] }
reqwest = { version = "^0.13", default-features = false, features = ["json", "multipart", "stream", "query", "form"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Name | Type | Description | Notes
**id** | Option<**i64**> | | [optional]
**pet_id** | Option<**i64**> | | [optional]
**quantity** | Option<**i32**> | | [optional]
**ship_date** | Option<**String**> | | [optional]
**ship_date** | Option<**chrono::DateTime<chrono::FixedOffset>**> | | [optional]
**status** | Option<**Status**> | Order Status (enum: placed, approved, delivered) | [optional]
**complete** | Option<**bool**> | | [optional][default to false]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Order {
#[serde(rename = "quantity", skip_serializing_if = "Option::is_none")]
pub quantity: Option<i32>,
#[serde(rename = "shipDate", skip_serializing_if = "Option::is_none")]
pub ship_date: Option<String>,
pub ship_date: Option<chrono::DateTime<chrono::FixedOffset>>,
/// Order Status
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<Status>,
Expand Down
Loading
Loading