Skip to content
Closed
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: 1 addition & 1 deletion bin/rust-petstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ for spec_path in \
; do
spec=$(basename "$spec_path" | sed 's/.yaml//' | sed 's/.json//' )

for library in hyper reqwest; do
for library in hyper reqwest reqwestFutures; do
args="generate --template-dir modules/openapi-generator/src/main/resources/rust
--input-spec $spec_path
--generator-name rust
Expand Down
10 changes: 10 additions & 0 deletions bin/windows/rust-futures-petstore.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar

If Not Exist %executable% (
mvn clean package
)

REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g rust --library reqwestFutures -o samples\client\petstore\rust

java %JAVA_OPTS% -jar %executable% %ags%
3 changes: 2 additions & 1 deletion docs/generators/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ sidebar_label: rust
| ------ | ----------- | ------ | ------- |
|packageName|Rust package name (convention: lowercase).| |openapi|
|packageVersion|Rust package version.| |1.0.0|
|interfacePrefix|Method prefix.| ||
|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>|hyper|
|library|library template (sub-template) to use.|<dl><dt>**hyper**</dt><dd>HTTP client: Hyper.</dd><dt>**reqwest**</dt><dd>HTTP client: Reqwest.</dd><dt>**reqwestFutures**</dt><dd>HTTP client: Reqwest (futures).</dd><dl>|hyper|
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class RustClientCodegen extends DefaultCodegen implements CodegenConfig {

public static final String HYPER_LIBRARY = "hyper";
public static final String REQWEST_LIBRARY = "reqwest";
public static final String REQWEST_FUTURES_LIBRARY = "reqwestFutures";

protected String packageName = "openapi";
protected String packageVersion = "1.0.0";
Expand Down Expand Up @@ -136,11 +137,14 @@ public RustClientCodegen() {
.defaultValue("openapi"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Rust package version.")
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.INTERFACE_PREFIX, "Method prefix.")
.defaultValue(""));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
.defaultValue(Boolean.TRUE.toString()));

supportedLibraries.put(HYPER_LIBRARY, "HTTP client: Hyper.");
supportedLibraries.put(REQWEST_LIBRARY, "HTTP client: Reqwest.");
supportedLibraries.put(REQWEST_FUTURES_LIBRARY, "HTTP client: Reqwest (futures).");

CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use.");
libraryOption.setEnum(supportedLibraries);
Expand Down Expand Up @@ -221,6 +225,8 @@ public void processOpts() {
additionalProperties.put(HYPER_LIBRARY, "true");
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
additionalProperties.put(REQWEST_LIBRARY, "true");
} else if (REQWEST_FUTURES_LIBRARY.equals(getLibrary())) {
additionalProperties.put("reqwestFutures", "true");
} else {
LOGGER.error("Unknown library option (-l/--library): {}", getLibrary());
}
Expand Down Expand Up @@ -431,7 +437,7 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
// http method verb conversion, depending on client library (e.g. Hyper: PUT => Put, Reqwest: PUT => put)
if (HYPER_LIBRARY.equals(getLibrary())) {
operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
} else if (REQWEST_LIBRARY.equals(getLibrary()) || REQWEST_FUTURES_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ futures = "0.1.23"
{{#reqwest}}
reqwest = "~0.9"
{{/reqwest}}
{{#reqwestFutures}}
reqwest = "~0.9"
futures = "0.1.23"
mime_guess = "2.0.1"
{{/reqwestFutures}}

[dev-dependencies]
{{#hyper}}
Expand Down
231 changes: 231 additions & 0 deletions modules/openapi-generator/src/main/resources/rust/api.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{{>partial_header}}
use std::rc::Rc;
use std::borrow::Borrow;
#[allow(unused_imports)]
use std::option::Option;

use reqwest;

use super::{Error, configuration};

pub struct {{{classname}}}Client {
configuration: Rc<configuration::Configuration>,
}

impl {{{classname}}}Client {
pub fn new(configuration: Rc<configuration::Configuration>) -> {{{classname}}}Client {
{{{classname}}}Client {
configuration,
}
}
}

pub trait {{{classname}}} {
{{#operations}}
{{#operation}}
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{returnType}}}{{/returnType}}, Error>;
{{/operation}}
{{/operations}}
}

impl {{{classname}}} for {{{classname}}}Client {
{{#operations}}
{{#operation}}
fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Result<{{^returnType}}(){{/returnType}}{{#returnType}}{{{returnType}}}{{/returnType}}, Error> {
let configuration: &configuration::Configuration = self.configuration.borrow();
let client = &configuration.client;

let uri_str = format!("{}{{{path}}}", configuration.base_path{{#pathParams}}, {{{baseName}}}={{#isString}}crate::apis::urlencode({{/isString}}{{{paramName}}}{{^required}}.unwrap(){{/required}}{{#required}}{{#isNullable}}.unwrap(){{/isNullable}}{{/required}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}{{#isString}}){{/isString}}{{/pathParams}});
let mut req_builder = client.{{{httpMethod}}}(uri_str.as_str());

{{#queryParams}}
{{#required}}
req_builder = req_builder.query(&[("{{{baseName}}}", &{{{paramName}}}{{#isListContainer}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isListContainer}}.to_string())]);
{{/required}}
{{^required}}
if let Some(ref s) = {{{paramName}}} {
req_builder = req_builder.query(&[("{{{baseName}}}", &s{{#isListContainer}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isListContainer}}.to_string())]);
}
{{/required}}
{{/queryParams}}
{{#hasAuthMethods}}
{{#authMethods}}
{{#isApiKey}}
{{#isKeyInQuery}}
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
req_builder = req_builder.query(&[("{{{keyParamName}}}", val)]);
}
{{/isKeyInQuery}}
{{/isApiKey}}
{{/authMethods}}
{{/hasAuthMethods}}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
{{#hasHeaderParams}}
{{#headerParams}}
{{#required}}
{{^isNullable}}
req_builder = req_builder.header("{{{baseName}}}", {{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
{{/isNullable}}
{{#isNullable}}
match {{{paramName}}} {
Some(param_value) => { req_builder = req_builder.header("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string()); },
None => { req_builder = req_builder.header("{{{baseName}}}", ""); },
}
{{/isNullable}}
{{/required}}
{{^required}}
if let Some(param_value) = {{{paramName}}} {
req_builder = req_builder.header("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
}
{{/required}}
{{/headerParams}}
{{/hasHeaderParams}}
{{#hasAuthMethods}}
{{#authMethods}}
{{#isApiKey}}
{{#isKeyInHeader}}
if let Some(ref apikey) = configuration.api_key {
let key = apikey.key.clone();
let val = match apikey.prefix {
Some(ref prefix) => format!("{} {}", prefix, key),
None => key,
};
req_builder = req_builder.header("{{{keyParamName}}}", val);
};
{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasic}}
{{^isBasicBearer}}
if let Some(ref auth_conf) = configuration.basic_auth {
req_builder = req_builder.basic_auth(auth_conf.0.to_owned(), auth_conf.1.to_owned());
};
{{/isBasicBearer}}
{{#isBasicBearer}}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
{{/isBasicBearer}}
{{/isBasic}}
{{#isOAuth}}
if let Some(ref token) = configuration.oauth_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}
{{#isMultipart}}
{{#hasFormParams}}
let mut form = reqwest::multipart::Form::new();
{{#formParams}}
{{#isFile}}
{{#required}}
{{^isNullable}}
form = form.file("{{{baseName}}}", {{{paramName}}})?;
{{/isNullable}}
{{#isNullable}}
match {{{paramName}}} {
Some(param_value) => { form = form.file("{{{baseName}}}", param_value)?; },
None => { unimplemented!("Required nullable form file param not supported"); },
}
{{/isNullable}}
{{/required}}
{{^required}}
if let Some(param_value) = {{{paramName}}} {
form = form.file("{{{baseName}}}", param_value)?;
}
{{/required}}
{{/isFile}}
{{^isFile}}
{{#required}}
{{^isNullable}}
form = form.text("{{{baseName}}}", {{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
{{/isNullable}}
{{#isNullable}}
match {{{paramName}}} {
Some(param_value) => { form = form.text("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string()); },
None => { form = form.text("{{{baseName}}}", ""); },
}
{{/isNullable}}
{{/required}}
{{^required}}
if let Some(param_value) = {{{paramName}}} {
form = form.text("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
}
{{/required}}
{{/isFile}}
{{/formParams}}
req_builder = req_builder.multipart(form);
{{/hasFormParams}}
{{/isMultipart}}
{{^isMultipart}}
{{#hasFormParams}}
let mut form_params = std::collections::HashMap::new();
{{#formParams}}
{{#isFile}}
{{#required}}
{{^isNullable}}
form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content"));
{{/isNullable}}
{{#isNullable}}
match {{{paramName}}} {
Some(param_value) => { form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content")); },
None => { unimplemented!("Required nullable file form param not supported with x-www-form-urlencoded content"); },
}
{{/isNullable}}
{{/required}}
{{^required}}
if let Some(param_value) = {{{paramName}}} {
form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content"));
}
{{/required}}
{{/isFile}}
{{^isFile}}
{{#required}}
{{^isNullable}}
form_params.insert("{{{baseName}}}", {{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
{{/isNullable}}
{{#isNullable}}
match {{{paramName}}} {
Some(param_value) => { form_params.insert("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string()); },
None => { form_params.insert("{{{baseName}}}", ""); },
}
{{/isNullable}}
{{/required}}
{{^required}}
if let Some(param_value) = {{{paramName}}} {
form_params.insert("{{{baseName}}}", param_value{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
}
{{/required}}
{{/isFile}}
{{/formParams}}
req_builder = req_builder.form(&form_params);
{{/hasFormParams}}
{{/isMultipart}}
{{#hasBodyParam}}
{{#bodyParams}}
req_builder = req_builder.json(&{{{paramName}}});
{{/bodyParams}}
{{/hasBodyParam}}

// send request
let req = req_builder.build()?;

{{^returnType}}
client.execute(req)?.error_for_status()?;
Ok(())
{{/returnType}}
{{#returnType}}
Ok(client.execute(req)?.error_for_status()?.json()?)
{{/returnType}}
}

{{/operation}}
{{/operations}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ extern crate futures;
{{#reqwest}}
extern crate reqwest;
{{/reqwest}}
{{#reqwestFutures}}
extern crate reqwest;
extern crate futures;
extern crate mime_guess;
{{/reqwestFutures}}

pub mod apis;
pub mod models;
Loading