From 1e1ac08cd8730c135ad352088e15aa4ca3fc536c Mon Sep 17 00:00:00 2001 From: Artem Medvedev Date: Tue, 20 Feb 2024 03:36:42 +0100 Subject: [PATCH] fix(rust): untagged enum of type-aliases without discriminator Partially solves #17869 There is a downside - variants names doesn't reflect model name of reference It also doesn't solve issue of import, will be solved separately --- .../rust-reqwest-oneOf-alias-type.yaml | 8 ++ .../src/main/resources/rust/model.mustache | 9 +- .../3_0/rust/issue_17869_oneOf_aliases.yaml | 42 +++++++++ .../oneOf/src/models/bar_ref_or_value.rs | 4 +- .../rust/reqwest/oneOf-aliases/.gitignore | 3 + .../oneOf-aliases/.openapi-generator-ignore | 23 +++++ .../oneOf-aliases/.openapi-generator/FILES | 11 +++ .../oneOf-aliases/.openapi-generator/VERSION | 1 + .../rust/reqwest/oneOf-aliases/.travis.yml | 1 + .../rust/reqwest/oneOf-aliases/Cargo.toml | 17 ++++ .../rust/reqwest/oneOf-aliases/README.md | 43 +++++++++ .../oneOf-aliases/docs/AccountOrEmail.md | 11 +++ .../rust/reqwest/oneOf-aliases/git_push.sh | 57 +++++++++++ .../oneOf-aliases/src/apis/configuration.rs | 53 +++++++++++ .../reqwest/oneOf-aliases/src/apis/mod.rs | 94 +++++++++++++++++++ .../rust/reqwest/oneOf-aliases/src/lib.rs | 10 ++ .../src/models/account_or_email.rs | 32 +++++++ .../reqwest/oneOf-aliases/src/models/mod.rs | 2 + .../oneOf/src/models/bar_ref_or_value.rs | 4 +- 19 files changed, 418 insertions(+), 7 deletions(-) create mode 100644 bin/configs/rust-reqwest-oneOf-alias-type.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/rust/issue_17869_oneOf_aliases.yaml create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/.gitignore create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator-ignore create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/FILES create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/VERSION create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/.travis.yml create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/Cargo.toml create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/README.md create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/docs/AccountOrEmail.md create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/git_push.sh create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/src/apis/configuration.rs create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/src/apis/mod.rs create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/src/lib.rs create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/src/models/account_or_email.rs create mode 100644 samples/client/others/rust/reqwest/oneOf-aliases/src/models/mod.rs diff --git a/bin/configs/rust-reqwest-oneOf-alias-type.yaml b/bin/configs/rust-reqwest-oneOf-alias-type.yaml new file mode 100644 index 0000000000000..17ac307d5bd3c --- /dev/null +++ b/bin/configs/rust-reqwest-oneOf-alias-type.yaml @@ -0,0 +1,8 @@ +generatorName: rust +outputDir: samples/client/others/rust/reqwest/oneOf-aliases +library: reqwest +inputSpec: modules/openapi-generator/src/test/resources/3_0/rust/issue_17869_oneOf_aliases.yaml +templateDir: modules/openapi-generator/src/main/resources/rust +additionalProperties: + supportAsync: false + packageName: oneof-reqwest-oneOf-aliases diff --git a/modules/openapi-generator/src/main/resources/rust/model.mustache b/modules/openapi-generator/src/main/resources/rust/model.mustache index a3eccd350131a..397a81bfbd694 100644 --- a/modules/openapi-generator/src/main/resources/rust/model.mustache +++ b/modules/openapi-generator/src/main/resources/rust/model.mustache @@ -112,13 +112,16 @@ impl {{{classname}}} { {{! TODO: add other vars that are not part of the oneOf}} #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] +{{#description}} +/// {{{.}}} +{{/description}} pub enum {{classname}} { - {{#oneOf}} + {{#composedSchemas.oneOf}} {{#description}} /// {{{.}}} {{/description}} - {{{.}}}(Box<{{{.}}}>), - {{/oneOf}} + {{{dataType}}}_{{-index}}(Box<{{{dataType}}}>), + {{/composedSchemas.oneOf}} } impl Default for {{classname}} { diff --git a/modules/openapi-generator/src/test/resources/3_0/rust/issue_17869_oneOf_aliases.yaml b/modules/openapi-generator/src/test/resources/3_0/rust/issue_17869_oneOf_aliases.yaml new file mode 100644 index 0000000000000..4a8388044faa4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/rust/issue_17869_oneOf_aliases.yaml @@ -0,0 +1,42 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Omitted", + "description": "Omitted", + "license": { + "name": "" + }, + "version": "0.1.0" + }, + "servers": [ + { + "url": "http://localhost:8080", + "description": "Omitted" + } + ], + "paths": {}, + "components": { + "schemas": { + "AccountName": { + "type": "string", + "description": "An account name." + }, + "AccountOrEmail": { + "oneOf": [ + { + "$ref": "#/components/schemas/Email" + }, + { + "$ref": "#/components/schemas/AccountName" + } + ], + "description": "Either an account name or an email." + }, + "Email": { + "type": "string", + "description": "An email address." + } + }, + "responses": {} + } +} \ No newline at end of file diff --git a/samples/client/others/rust/hyper/oneOf/src/models/bar_ref_or_value.rs b/samples/client/others/rust/hyper/oneOf/src/models/bar_ref_or_value.rs index f7a595f0cd36a..7cba46033a385 100644 --- a/samples/client/others/rust/hyper/oneOf/src/models/bar_ref_or_value.rs +++ b/samples/client/others/rust/hyper/oneOf/src/models/bar_ref_or_value.rs @@ -16,8 +16,8 @@ use super::BarRef; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum BarRefOrValue { - Bar(Box), - BarRef(Box), + crate::models::Bar_1(Box), + crate::models::BarRef_2(Box), } impl Default for BarRefOrValue { diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/.gitignore b/samples/client/others/rust/reqwest/oneOf-aliases/.gitignore new file mode 100644 index 0000000000000..6aa106405a4b4 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/.gitignore @@ -0,0 +1,3 @@ +/target/ +**/*.rs.bk +Cargo.lock diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator-ignore b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator-ignore new file mode 100644 index 0000000000000..7484ee590a389 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/FILES b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/FILES new file mode 100644 index 0000000000000..e80abc0d5d5ae --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/FILES @@ -0,0 +1,11 @@ +.gitignore +.travis.yml +Cargo.toml +README.md +docs/AccountOrEmail.md +git_push.sh +src/apis/configuration.rs +src/apis/mod.rs +src/lib.rs +src/models/account_or_email.rs +src/models/mod.rs diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/VERSION b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/VERSION new file mode 100644 index 0000000000000..c9e125ba18809 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.4.0-SNAPSHOT diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/.travis.yml b/samples/client/others/rust/reqwest/oneOf-aliases/.travis.yml new file mode 100644 index 0000000000000..22761ba7ee19a --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/.travis.yml @@ -0,0 +1 @@ +language: rust diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/Cargo.toml b/samples/client/others/rust/reqwest/oneOf-aliases/Cargo.toml new file mode 100644 index 0000000000000..9783926129840 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "oneof-reqwest-oneOf-aliases" +version = "0.1.0" +authors = ["OpenAPI Generator team and contributors"] +description = "Omitted" +license = "" +edition = "2018" + +[dependencies] +serde = "^1.0" +serde_derive = "^1.0" +serde_json = "^1.0" +url = "^2.2" +uuid = { version = "^1.0", features = ["serde", "v4"] } +[dependencies.reqwest] +version = "^0.11" +features = ["json", "blocking", "multipart"] diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/README.md b/samples/client/others/rust/reqwest/oneOf-aliases/README.md new file mode 100644 index 0000000000000..7dcfd7bd04330 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/README.md @@ -0,0 +1,43 @@ +# Rust API client for oneof-reqwest-oneOf-aliases + +Omitted + + +## Overview + +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://openapis.org) from a remote server, you can easily generate an API client. + +- API version: 0.1.0 +- Package version: 0.1.0 +- Build package: `org.openapitools.codegen.languages.RustClientCodegen` + +## Installation + +Put the package under your project folder in a directory named `oneof-reqwest-oneOf-aliases` and add the following to `Cargo.toml` under `[dependencies]`: + +``` +oneof-reqwest-oneOf-aliases = { path = "./oneof-reqwest-oneOf-aliases" } +``` + +## Documentation for API Endpoints + +All URIs are relative to *http://localhost:8080* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- + + +## Documentation For Models + + - [AccountOrEmail](docs/AccountOrEmail.md) + + +To get access to the crate's generated documentation, use: + +``` +cargo doc --open +``` + +## Author + + diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/docs/AccountOrEmail.md b/samples/client/others/rust/reqwest/oneOf-aliases/docs/AccountOrEmail.md new file mode 100644 index 0000000000000..bde793a580bf6 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/docs/AccountOrEmail.md @@ -0,0 +1,11 @@ +# AccountOrEmail + +## Enum Variants + +| Name | Description | +|---- | -----| +| String | Either an account name or an email. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/git_push.sh b/samples/client/others/rust/reqwest/oneOf-aliases/git_push.sh new file mode 100644 index 0000000000000..f53a75d4fabe7 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/configuration.rs b/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/configuration.rs new file mode 100644 index 0000000000000..f510921d27d05 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/configuration.rs @@ -0,0 +1,53 @@ +/* + * Omitted + * + * Omitted + * + * The version of the OpenAPI document: 0.1.0 + * + * Generated by: https://openapi-generator.tech + */ + + + +#[derive(Debug, Clone)] +pub struct Configuration { + pub base_path: String, + pub user_agent: Option, + pub client: reqwest::blocking::Client, + pub basic_auth: Option, + pub oauth_access_token: Option, + pub bearer_access_token: Option, + pub api_key: Option, + // TODO: take an oauth2 token source, similar to the go one +} + +pub type BasicAuth = (String, Option); + +#[derive(Debug, Clone)] +pub struct ApiKey { + pub prefix: Option, + pub key: String, +} + + +impl Configuration { + pub fn new() -> Configuration { + Configuration::default() + } +} + +impl Default for Configuration { + fn default() -> Self { + Configuration { + base_path: "http://localhost:8080".to_owned(), + user_agent: Some("OpenAPI-Generator/0.1.0/rust".to_owned()), + client: reqwest::blocking::Client::new(), + basic_auth: None, + oauth_access_token: None, + bearer_access_token: None, + api_key: None, + + } + } +} diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/mod.rs b/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/mod.rs new file mode 100644 index 0000000000000..dccbc940fb49c --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/src/apis/mod.rs @@ -0,0 +1,94 @@ +use std::error; +use std::fmt; + +#[derive(Debug, Clone)] +pub struct ResponseContent { + pub status: reqwest::StatusCode, + pub content: String, + pub entity: Option, +} + +#[derive(Debug)] +pub enum Error { + Reqwest(reqwest::Error), + Serde(serde_json::Error), + Io(std::io::Error), + ResponseError(ResponseContent), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (module, e) = match self { + Error::Reqwest(e) => ("reqwest", e.to_string()), + Error::Serde(e) => ("serde", e.to_string()), + Error::Io(e) => ("IO", e.to_string()), + Error::ResponseError(e) => ("response", format!("status code {}", e.status)), + }; + write!(f, "error in {}: {}", module, e) + } +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(match self { + Error::Reqwest(e) => e, + Error::Serde(e) => e, + Error::Io(e) => e, + Error::ResponseError(_) => return None, + }) + } +} + +impl From for Error { + fn from(e: reqwest::Error) -> Self { + Error::Reqwest(e) + } +} + +impl From for Error { + fn from(e: serde_json::Error) -> Self { + Error::Serde(e) + } +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Error::Io(e) + } +} + +pub fn urlencode>(s: T) -> String { + ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect() +} + +pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> { + if let serde_json::Value::Object(object) = value { + let mut params = vec![]; + + for (key, value) in object { + match value { + serde_json::Value::Object(_) => params.append(&mut parse_deep_object( + &format!("{}[{}]", prefix, key), + value, + )), + serde_json::Value::Array(array) => { + for (i, value) in array.iter().enumerate() { + params.append(&mut parse_deep_object( + &format!("{}[{}][{}]", prefix, key, i), + value, + )); + } + }, + serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())), + _ => params.push((format!("{}[{}]", prefix, key), value.to_string())), + } + } + + return params; + } + + unimplemented!("Only objects are supported with style=deepObject") +} + + +pub mod configuration; diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/src/lib.rs b/samples/client/others/rust/reqwest/oneOf-aliases/src/lib.rs new file mode 100644 index 0000000000000..c1dd666f7957b --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/src/lib.rs @@ -0,0 +1,10 @@ +#[macro_use] +extern crate serde_derive; + +extern crate serde; +extern crate serde_json; +extern crate url; +extern crate reqwest; + +pub mod apis; +pub mod models; diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/src/models/account_or_email.rs b/samples/client/others/rust/reqwest/oneOf-aliases/src/models/account_or_email.rs new file mode 100644 index 0000000000000..4f38d1a017713 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/src/models/account_or_email.rs @@ -0,0 +1,32 @@ +/* + * Omitted + * + * Omitted + * + * The version of the OpenAPI document: 0.1.0 + * + * Generated by: https://openapi-generator.tech + */ + +/// AccountOrEmail : Either an account name or an email. +use super::String; + + + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +/// Either an account name or an email. +pub enum AccountOrEmail { + /// An email address. + String_1(Box), + /// An account name. + String_2(Box), +} + +impl Default for AccountOrEmail { + fn default() -> Self { + Self::String(Box::default()) + } +} + + diff --git a/samples/client/others/rust/reqwest/oneOf-aliases/src/models/mod.rs b/samples/client/others/rust/reqwest/oneOf-aliases/src/models/mod.rs new file mode 100644 index 0000000000000..f75f75e4638c0 --- /dev/null +++ b/samples/client/others/rust/reqwest/oneOf-aliases/src/models/mod.rs @@ -0,0 +1,2 @@ +pub mod account_or_email; +pub use self::account_or_email::AccountOrEmail; diff --git a/samples/client/others/rust/reqwest/oneOf/src/models/bar_ref_or_value.rs b/samples/client/others/rust/reqwest/oneOf/src/models/bar_ref_or_value.rs index f7a595f0cd36a..7cba46033a385 100644 --- a/samples/client/others/rust/reqwest/oneOf/src/models/bar_ref_or_value.rs +++ b/samples/client/others/rust/reqwest/oneOf/src/models/bar_ref_or_value.rs @@ -16,8 +16,8 @@ use super::BarRef; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum BarRefOrValue { - Bar(Box), - BarRef(Box), + crate::models::Bar_1(Box), + crate::models::BarRef_2(Box), } impl Default for BarRefOrValue {