[Rust] Add support for base64-encoded byte arrays (#18469)

Co-authored-by: Elric Milon <whirm@gmx.com>
This commit is contained in:
Elric Milon
2024-04-25 04:26:34 +02:00
committed by GitHub
parent efb7e5624d
commit d7b808e2e9
22 changed files with 89 additions and 19 deletions

View File

@@ -270,10 +270,10 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
// Remove the discriminator field from the model, serde will take care of this
for (ModelMap model : objs.getModels()) {
CodegenModel cm = model.getModel();
// Remove the discriminator field from the model, serde will take care of this
if (cm.discriminator != null) {
String reserved_var_name = cm.discriminator.getPropertyBaseName();
@@ -284,6 +284,14 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
}
}
}
// Flag structs with byteArrays in them so that we can annotate them with the serde_as macro
for (CodegenProperty cp : cm.vars) {
if (cp.isByteArray) {
cm.vendorExtensions.put("x-rust-has-byte-array", true);
break;
}
}
}
// process enum in models
return postProcessModelsEnum(objs);
@@ -537,6 +545,11 @@ public class RustClientCodegen extends AbstractRustCodegen implements CodegenCon
if (property.isNullable && !property.required) {
additionalProperties.put("serdeWith", true);
}
// If a property is a base64-encoded byte array, use `serde_with` for deserialization.
if (property.isByteArray) {
additionalProperties.put("serdeWith", true);
}
}
@Override

View File

@@ -35,7 +35,7 @@ homepage = "{{.}}
serde = "^1.0"
serde_derive = "^1.0"
{{#serdeWith}}
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
{{/serdeWith}}
serde_json = "^1.0"
url = "^2.2"

View File

@@ -2,7 +2,9 @@
use crate::models;
{{#models}}
{{#model}}
{{^isEnum}}{{#vendorExtensions.x-rust-has-byte-array}}
use serde_with::serde_as;
{{/vendorExtensions.x-rust-has-byte-array}}{{/isEnum}}
{{#description}}
/// {{{classname}}} : {{{description}}}
{{/description}}
@@ -85,15 +87,18 @@ impl Default for {{classname}} {
{{!-- for non-enum schemas --}}
{{^isEnum}}
{{^discriminator}}
{{#oneOf.isEmpty}}
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
{{#vendorExtensions.x-rust-has-byte-array}}#[serde_as]
{{/vendorExtensions.x-rust-has-byte-array}}{{#oneOf.isEmpty}}#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct {{{classname}}} {
{{#vars}}
{{#description}}
/// {{{.}}}
{{/description}}
{{#isByteArray}}
{{#required}}#[serde_as(as = "serde_with::base64::Base64")]{{/required}}{{^required}}#[serde_as(as = "Option<serde_with::base64::Base64>")]{{/required}}
{{/isByteArray}}
#[serde(rename = "{{{baseName}}}"{{^required}}{{#isNullable}}, default, with = "::serde_with::rust::double_option"{{/isNullable}}{{/required}}{{^required}}, skip_serializing_if = "Option::is_none"{{/required}}{{#required}}{{#isNullable}}, deserialize_with = "Option::deserialize"{{/isNullable}}{{/required}})]
pub {{{name}}}: {{#isNullable}}Option<{{/isNullable}}{{^required}}Option<{{/required}}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{^isModel}}{{{dataType}}}{{/isModel}}{{/isEnum}}{{#isNullable}}>{{/isNullable}}{{^required}}>{{/required}},
pub {{{name}}}: {{#isNullable}}Option<{{/isNullable}}{{^required}}Option<{{/required}}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{#isModel}}{{^avoidBoxedModels}}Box<{{/avoidBoxedModels}}{{{dataType}}}{{^avoidBoxedModels}}>{{/avoidBoxedModels}}{{/isModel}}{{^isModel}}{{#isByteArray}}Vec<u8>{{/isByteArray}}{{^isByteArray}}{{{dataType}}}{{/isByteArray}}{{/isModel}}{{/isEnum}}{{#isNullable}}>{{/isNullable}}{{^required}}>{{/required}},
{{/vars}}
}
@@ -101,7 +106,7 @@ impl {{{classname}}} {
{{#description}}
/// {{{.}}}
{{/description}}
pub fn new({{#requiredVars}}{{{name}}}: {{#isNullable}}Option<{{/isNullable}}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}>{{/isNullable}}{{^-last}}, {{/-last}}{{/requiredVars}}) -> {{{classname}}} {
pub fn new({{#requiredVars}}{{{name}}}: {{#isNullable}}Option<{{/isNullable}}{{#isEnum}}{{#isArray}}{{#uniqueItems}}std::collections::HashSet<{{/uniqueItems}}{{^uniqueItems}}Vec<{{/uniqueItems}}{{/isArray}}{{{enumName}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{#isByteArray}}Vec<u8>{{/isByteArray}}{{^isByteArray}}{{{dataType}}}{{/isByteArray}}{{/isEnum}}{{#isNullable}}>{{/isNullable}}{{^-last}}, {{/-last}}{{/requiredVars}}) -> {{{classname}}} {
{{{classname}}} {
{{#vars}}
{{{name}}}{{^required}}: None{{/required}}{{#required}}{{#isModel}}{{^avoidBoxedModels}}: {{^isNullable}}Box::new({{{name}}}){{/isNullable}}{{#isNullable}}if let Some(x) = {{{name}}} {Some(Box::new(x))} else {None}{{/isNullable}}{{/avoidBoxedModels}}{{/isModel}}{{/required}},

View File

@@ -838,6 +838,7 @@ components:
- string
- boolean
- uuid
- bytes
properties:
int32:
type: integer
@@ -858,6 +859,9 @@ components:
uuid:
type: string
format: uuid
bytes:
type: string
format: byte
Return:
description: Test using keywords
type: object

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}

View File

@@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
serde = "^1.0"
serde_derive = "^1.0"
serde_with = "^2.0"
serde_with = { version = "^3", default-features = false, features = ["base64", "std", "macros"] }
serde_json = "^1.0"
url = "^2.2"
uuid = { version = "^1.0", features = ["serde", "v4"] }

View File

@@ -11,6 +11,7 @@ Name | Type | Description | Notes
**string** | **String** | |
**boolean** | **bool** | |
**uuid** | [**uuid::Uuid**](uuid::Uuid.md) | |
**bytes** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,7 +10,10 @@
use crate::models;
use serde_with::serde_as;
/// TypeTesting : Test handling of different field data types
#[serde_as]
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TypeTesting {
#[serde(rename = "int32")]
@@ -27,11 +30,14 @@ pub struct TypeTesting {
pub boolean: bool,
#[serde(rename = "uuid")]
pub uuid: uuid::Uuid,
#[serde_as(as = "serde_with::base64::Base64")]
#[serde(rename = "bytes")]
pub bytes: Vec<u8>,
}
impl TypeTesting {
/// Test handling of different field data types
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid) -> TypeTesting {
pub fn new(int32: i32, int64: i64, float: f32, double: f64, string: String, boolean: bool, uuid: uuid::Uuid, bytes: Vec<u8>) -> TypeTesting {
TypeTesting {
int32,
int64,
@@ -40,6 +46,7 @@ impl TypeTesting {
string,
boolean,
uuid,
bytes,
}
}
}