[Rust-Axum] Support AnyOf, AllOf (#21948)

* Support AnyOf, AllOf

* Update

* Fix

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update
This commit is contained in:
Linh Tran Tuan 2025-09-27 17:01:37 +09:00 committed by GitHub
parent 2afac1aa28
commit e38f6c0580
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 443 additions and 263 deletions

View File

@ -61,4 +61,4 @@
- filename: "samples/server/petstore/rust-axum/output/rust-axum-oneof/tests/oneof_with_discriminator.rs"
sha256: 2d4f5a069fdcb3057bb078d5e75b3de63cd477b97725e457079df24bd2c30600
- filename: "samples/server/petstore/rust-axum/output/openapi-v3/tests/oneof_untagged.rs"
sha256: e72fbf81a9849dc7abb7e2169f2fc355c8b1cf991c0e2ffc083126abd9e966e7
sha256: 1d3fb01f65e98290b1d3eece28014c7d3e3f2fdf18e7110249d3c591cc4642ab

View File

@ -77,6 +77,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
<li>dyn</li>
<li>else</li>
<li>enum</li>
<li>errors</li>
<li>extern</li>
<li>false</li>
<li>final</li>
@ -207,8 +208,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|Composite|✓|OAS2,OAS3
|Polymorphism|✗|OAS2,OAS3
|Union|✗|OAS3
|allOf||OAS2,OAS3
|anyOf||OAS3
|allOf||OAS2,OAS3
|anyOf||OAS3
|oneOf|✓|OAS3
|not|✗|OAS3

View File

@ -99,6 +99,18 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
public RustAxumServerCodegen() {
super();
// The `#[validate(nested)]` macro relies on an internal field named `errors` to accumulate validation results. Therefore, defining a struct like this will fail:
//
// ```rust
// struct A {
// #[validate(nested)]
// errors: B,
// }
// ```
//
// To avoid this, either rename the field to something other than "errors", or reserve it.
this.reservedWords.add("errors");
modifyFeatureSet(features -> features
.wireFormatFeatures(EnumSet.of(
WireFormatFeature.JSON,
@ -112,7 +124,9 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
.schemaSupportFeatures(EnumSet.of(
SchemaSupportFeature.Simple,
SchemaSupportFeature.Composite,
SchemaSupportFeature.oneOf
SchemaSupportFeature.oneOf,
SchemaSupportFeature.anyOf,
SchemaSupportFeature.allOf
))
.excludeGlobalFeatures(
GlobalFeature.Info,
@ -633,105 +647,163 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
return op;
}
private void postProcessOneOfModels(List<ModelMap> allModels) {
final HashMap<String, List<String>> oneOfMapDiscriminator = new HashMap<>();
private void postProcessPolymorphism(final List<ModelMap> allModels) {
final HashMap<String, List<String>> discriminatorsForModel = new HashMap<>();
for (ModelMap mo : allModels) {
for (final ModelMap mo : allModels) {
final CodegenModel cm = mo.getModel();
final CodegenComposedSchemas cs = cm.getComposedSchemas();
if (cs != null) {
final List<CodegenProperty> csOneOf = cs.getOneOf();
if (csOneOf != null) {
for (CodegenProperty model : csOneOf) {
// Generate a valid name for the enum variant.
// Mainly needed for primitive types.
model.datatypeWithEnum = camelize(model.dataType.replaceAll("(?:\\w+::)+(\\w+)", "$1")
.replace("<", "Of").replace(">", ""));
// Primitive type is not properly set, this overrides it to guarantee adequate model generation.
if (!model.getDataType().matches(String.format(Locale.ROOT, ".*::%s", model.getDatatypeWithEnum()))) {
model.isPrimitiveType = true;
}
}
processPolymorphismDataType(csOneOf);
cs.setOneOf(csOneOf);
cm.setComposedSchemas(cs);
}
final List<CodegenProperty> csAnyOf = cs.getAnyOf();
if (csAnyOf != null) {
processPolymorphismDataType(csAnyOf);
cs.setAnyOf(csAnyOf);
cm.setComposedSchemas(cs);
}
}
if (cm.discriminator != null) {
for (String model : cm.oneOf) {
List<String> discriminators = oneOfMapDiscriminator.getOrDefault(model, new ArrayList<>());
for (final String model : cm.oneOf) {
final List<String> discriminators = discriminatorsForModel.getOrDefault(model, new ArrayList<>());
discriminators.add(cm.discriminator.getPropertyName());
oneOfMapDiscriminator.put(model, discriminators);
discriminatorsForModel.put(model, discriminators);
}
for (final String model : cm.anyOf) {
final List<String> discriminators = discriminatorsForModel.getOrDefault(model, new ArrayList<>());
discriminators.add(cm.discriminator.getPropertyName());
discriminatorsForModel.put(model, discriminators);
}
}
}
final var blocking = new HashSet<String>();
for (ModelMap mo : allModels) {
final CodegenModel cm = mo.getModel();
for (CodegenProperty var : cm.vars) {
var.isDiscriminator = false;
final List<String> discriminators = discriminatorsForModel.get(cm.getSchemaName());
if (discriminators != null) {
// If the discriminator field is not a defined attribute in the variant structure, create it.
if (!discriminating(discriminators, cm)) {
final String discriminator = discriminators.get(0);
CodegenProperty property = new CodegenProperty();
// Static attributes
// Only strings are supported by serde for tag field types, so it's the only one we'll deal with
property.openApiType = "string";
property.complexType = "string";
property.dataType = "String";
property.datatypeWithEnum = "String";
property.baseType = "string";
property.required = true;
property.isPrimitiveType = true;
property.isString = true;
property.isDiscriminator = true;
// Attributes based on the discriminator value
property.baseName = discriminator;
property.name = discriminator;
property.nameInCamelCase = camelize(discriminator);
property.nameInPascalCase = property.nameInCamelCase.substring(0, 1).toUpperCase(Locale.ROOT) + property.nameInCamelCase.substring(1);
property.nameInSnakeCase = underscore(discriminator).toUpperCase(Locale.ROOT);
property.getter = String.format(Locale.ROOT, "get%s", property.nameInPascalCase);
property.setter = String.format(Locale.ROOT, "set%s", property.nameInPascalCase);
property.defaultValueWithParam = String.format(Locale.ROOT, " = data.%s;", property.name);
// Attributes based on the model name
property.defaultValue = String.format(Locale.ROOT, "r#\"%s\"#.to_string()", cm.getSchemaName());
property.jsonSchema = String.format(Locale.ROOT, "{ \"default\":\"%s\"; \"type\":\"string\" }", cm.getSchemaName());
cm.vars.add(property);
}
}
final List<String> discriminatorsForModel = oneOfMapDiscriminator.get(cm.getSchemaName());
if (cm.vars.stream().noneMatch(v -> v.isDiscriminator)) {
blocking.add(cm.getSchemaName());
}
}
if (discriminatorsForModel != null) {
for (String discriminator : discriminatorsForModel) {
boolean hasDiscriminatorDefined = false;
for (CodegenProperty var : cm.vars) {
if (var.baseName.equals(discriminator)) {
var.isDiscriminator = true;
hasDiscriminatorDefined = true;
break;
}
}
// If the discriminator field is not a defined attribute in the variant structure, create it.
if (!hasDiscriminatorDefined) {
CodegenProperty property = new CodegenProperty();
// Static attributes
// Only strings are supported by serde for tag field types, so it's the only one we'll deal with
property.openApiType = "string";
property.complexType = "string";
property.dataType = "String";
property.datatypeWithEnum = "String";
property.baseType = "string";
property.required = true;
property.isPrimitiveType = true;
property.isString = true;
property.isDiscriminator = true;
// Attributes based on the discriminator value
property.baseName = discriminator;
property.name = discriminator;
property.nameInCamelCase = camelize(discriminator);
property.nameInPascalCase = property.nameInCamelCase.substring(0, 1).toUpperCase(Locale.ROOT) + property.nameInCamelCase.substring(1);
property.nameInSnakeCase = underscore(discriminator).toUpperCase(Locale.ROOT);
property.getter = String.format(Locale.ROOT, "get%s", property.nameInPascalCase);
property.setter = String.format(Locale.ROOT, "set%s", property.nameInPascalCase);
property.defaultValueWithParam = String.format(Locale.ROOT, " = data.%s;", property.name);
// Attributes based on the model name
property.defaultValue = String.format(Locale.ROOT, "r#\"%s\"#.to_string()", cm.getSchemaName());
property.jsonSchema = String.format(Locale.ROOT, "{ \"default\":\"%s\"; \"type\":\"string\" }", cm.getSchemaName());
cm.vars.add(property);
}
for (final ModelMap mo : allModels) {
final CodegenModel cm = mo.getModel();
if (cm.discriminator != null) {
// if no discriminator in any of variant -> disable discriminator
if (cm.oneOf.stream().anyMatch(blocking::contains) || cm.anyOf.stream().anyMatch(blocking::contains)) {
cm.discriminator = null;
}
}
}
}
private static boolean discriminating(final List<String> discriminatorsForModel, final CodegenModel cm) {
resetDiscriminatorProperty(cm);
// Discriminator will be presented as enum tag -> One and only one tag is allowed
int countString = 0;
int countNonString = 0;
for (final CodegenProperty var : cm.vars) {
if (discriminatorsForModel.stream().anyMatch(discriminator -> var.baseName.equals(discriminator) || var.name.equals(discriminator))) {
if (var.isString) {
var.isDiscriminator = true;
++countString;
} else
++countNonString;
}
}
if (countString > 0 && (countNonString > 0 || countString > 1)) {
// at least two discriminator, one of them is string -> should not render serde tag
resetDiscriminatorProperty(cm);
}
return countNonString > 0 || countString > 0;
}
private static void resetDiscriminatorProperty(final CodegenModel cm) {
for (final CodegenProperty var : cm.vars) {
var.isDiscriminator = false;
}
}
private static void processPolymorphismDataType(final List<CodegenProperty> cp) {
final HashSet<String> dedupDataTypeWithEnum = new HashSet<>();
final HashMap<String, Integer> dedupDataType = new HashMap<>();
int idx = 0;
for (CodegenProperty model : cp) {
// Generate a valid name for the enum variant.
// Mainly needed for primitive types.
model.datatypeWithEnum = camelize(model.dataType.replaceAll("(?:\\w+::)+(\\w+)", "$1")
.replace("<", "Of").replace(">", "")).replace(" ", "").replace(",", "");
if (!dedupDataTypeWithEnum.add(model.datatypeWithEnum)) {
model.datatypeWithEnum += ++idx;
}
dedupDataType.put(model.getDataType(), dedupDataType.getOrDefault(model.getDataType(), 0) + 1);
if (!model.getDataType().matches(String.format(Locale.ROOT, ".*::%s", model.getDatatypeWithEnum()))) {
model.isPrimitiveType = true;
}
}
for (CodegenProperty model : cp) {
if (dedupDataType.get(model.getDataType()) == 1) {
model.vendorExtensions.put("x-from-trait", true);
}
}
}
@Override
public OperationsMap postProcessOperationsWithModels(final OperationsMap operationsMap, List<ModelMap> allModels) {
postProcessOneOfModels(allModels);
postProcessPolymorphism(allModels);
final OperationMap operations = operationsMap.getOperations();
operations.put("classnamePascalCase", camelize(operations.getClassname()));
@ -901,7 +973,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
// restore things to sensible values.
@Override
public CodegenParameter fromRequestBody(RequestBody body, Set<String> imports, String bodyParameterName) {
final Schema original_schema = ModelUtils.getSchemaFromRequestBody(body);
final var original_schema = ModelUtils.getSchemaFromRequestBody(body);
CodegenParameter codegenParameter = super.fromRequestBody(body, imports, bodyParameterName);
if (StringUtils.isNotBlank(original_schema.get$ref())) {
@ -920,10 +992,10 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
@Override
public String toInstantiationType(final Schema p) {
if (ModelUtils.isArraySchema(p)) {
final Schema inner = ModelUtils.getSchemaItems(p);
final var inner = ModelUtils.getSchemaItems(p);
return instantiationTypes.get("array") + "<" + getSchemaType(inner) + ">";
} else if (ModelUtils.isMapSchema(p)) {
final Schema inner = ModelUtils.getAdditionalProperties(p);
final var inner = ModelUtils.getAdditionalProperties(p);
return instantiationTypes.get("map") + "<" + typeMapping.get("string") + ", " + getSchemaType(inner) + ">";
} else {
return null;
@ -952,6 +1024,10 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
@Override
public String toDefaultValue(final Schema p) {
String defaultValue = null;
if (ModelUtils.isEnumSchema(p))
return null;
if ((ModelUtils.isNullable(p)) && (p.getDefault() != null) && ("null".equalsIgnoreCase(p.getDefault().toString())))
return "Nullable::Null";
@ -965,6 +1041,9 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
} else if (ModelUtils.isNumberSchema(p)) {
if (p.getDefault() != null) {
defaultValue = p.getDefault().toString();
if (!defaultValue.contains(".")) {
defaultValue += ".0";
}
}
} else if (ModelUtils.isIntegerSchema(p)) {
if (p.getDefault() != null) {
@ -1081,7 +1160,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
String cmd = System.getenv("RUST_POST_PROCESS_FILE");
if (StringUtils.isEmpty(cmd)) {
cmd = "rustfmt";
command = new String[]{cmd, "--edition", "2021", fileName};
command = new String[]{cmd, "--edition", "2024", fileName};
} else {
command = new String[]{cmd, fileName};
}
@ -1093,7 +1172,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
}
@Override
protected void updateParameterForString(CodegenParameter codegenParameter, Schema parameterSchema) {
protected void updateParameterForString(CodegenParameter codegenParameter, final Schema parameterSchema) {
if (ModelUtils.isEmailSchema(parameterSchema)) {
codegenParameter.isEmail = true;
} else if (ModelUtils.isUUIDSchema(parameterSchema)) {
@ -1120,7 +1199,7 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
codegenParameter.isDecimal = true;
codegenParameter.isPrimitiveType = true;
}
if (Boolean.TRUE.equals(codegenParameter.isString)) {
if (codegenParameter.isString) {
codegenParameter.isPrimitiveType = true;
}
}
@ -1152,6 +1231,16 @@ public class RustAxumServerCodegen extends AbstractRustCodegen implements Codege
return null;
}
@Override
public String toVarName(String name) {
final var varName = super.toVarName(name);
if (varName.startsWith("r#"))
return "r_" + varName.substring(2);
return varName;
}
static class PathMethodOperations {
public String path;
public ArrayList<MethodOperation> methodOperations;

View File

@ -524,7 +524,7 @@ pub fn check_xss_map<T>(v: &std::collections::HashMap<String, T>) -> std::result
/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "conversion", derive(frunk_enum_derive::LabelledGenericEnum))]
@ -751,17 +751,38 @@ impl std::str::FromStr for {{{classname}}} {
{{^arrayModelType}}
{{! general struct}}
{{#anyOf.size}}
/// Any of:
{{#anyOf}}
/// - {{{.}}}
{{/anyOf}}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct {{{classname}}}(Box<serde_json::value::RawValue>);
{{#discriminator}}
#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
#[serde(tag = "{{{propertyBaseName}}}")]
{{/discriminator}}
{{^discriminator}}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
{{/discriminator}}
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum {{{classname}}} {
{{#composedSchemas}}
{{#anyOf}}
{{{datatypeWithEnum}}}({{{dataType}}}),
{{/anyOf}}
{{/composedSchemas}}
}
impl validator::Validate for {{{classname}}}
{
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
std::result::Result::Ok(())
match self {
{{#composedSchemas}}
{{#anyOf}}
{{^isModel}}
Self::{{{datatypeWithEnum}}}(_) => std::result::Result::Ok(()),
{{/isModel}}
{{#isModel}}
Self::{{{datatypeWithEnum}}}(v) => v.validate(),
{{/isModel}}
{{/anyOf}}
{{/composedSchemas}}
}
}
}
@ -776,11 +797,32 @@ impl std::str::FromStr for {{{classname}}} {
}
}
impl PartialEq for {{{classname}}} {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
{{#discriminator}}
impl serde::Serialize for {{{classname}}} {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer {
match self {
{{#composedSchemas}}
{{#anyOf}}
Self::{{{datatypeWithEnum}}}(x) => x.serialize(serializer),
{{/anyOf}}
{{/composedSchemas}}
}
}
}
{{/discriminator}}
{{#composedSchemas}}
{{#anyOf}}
{{#vendorExtensions.x-from-trait}}
impl From<{{{dataType}}}> for {{{classname}}} {
fn from(value: {{{dataType}}}) -> Self {
Self::{{{datatypeWithEnum}}}(value)
}
}
{{/vendorExtensions.x-from-trait}}
{{/anyOf}}
{{/composedSchemas}}
{{/anyOf.size}}
{{#oneOf.size}}
@ -792,11 +834,11 @@ impl PartialEq for {{{classname}}} {
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
{{/discriminator}}
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum {{{classname}}} {
{{#composedSchemas}}
{{#oneOf}}
{{{datatypeWithEnum}}}(Box<{{{dataType}}}>),
{{{datatypeWithEnum}}}({{{dataType}}}),
{{/oneOf}}
{{/composedSchemas}}
}
@ -807,18 +849,29 @@ impl validator::Validate for {{{classname}}}
match self {
{{#composedSchemas}}
{{#oneOf}}
{{#isPrimitiveType}}
{{^isModel}}
Self::{{{datatypeWithEnum}}}(_) => std::result::Result::Ok(()),
{{/isPrimitiveType}}
{{^isPrimitiveType}}
Self::{{{datatypeWithEnum}}}(x) => x.validate(),
{{/isPrimitiveType}}
{{/isModel}}
{{#isModel}}
Self::{{{datatypeWithEnum}}}(v) => v.validate(),
{{/isModel}}
{{/oneOf}}
{{/composedSchemas}}
}
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a {{{classname}}} value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
impl std::str::FromStr for {{{classname}}} {
type Err = serde_json::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
{{#discriminator}}
impl serde::Serialize for {{{classname}}} {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@ -834,29 +887,18 @@ impl serde::Serialize for {{{classname}}} {
}
{{/discriminator}}
{{#composedSchemas}}
{{#oneOf}}
{{#vendorExtensions.x-from-trait}}
impl From<{{{dataType}}}> for {{{classname}}} {
fn from(value: {{{dataType}}}) -> Self {
Self::{{{datatypeWithEnum}}}(Box::new(value))
Self::{{{datatypeWithEnum}}}(value)
}
}
{{/vendorExtensions.x-from-trait}}
{{/oneOf}}
{{/composedSchemas}}
/// Converts Query Parameters representation (style=form, explode=false) to a {{{classname}}} value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
impl std::str::FromStr for {{{classname}}} {
type Err = serde_json::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
{{/oneOf.size}}
{{^anyOf.size}}
{{^oneOf.size}}
@ -871,8 +913,10 @@ pub struct {{{classname}}} {
/// Note: inline enums are not fully supported by openapi-generator
{{/isEnum}}
{{#isDiscriminator}}
{{#isString}}
#[serde(default = "{{{classname}}}::_name_for_{{{name}}}")]
#[serde(serialize_with = "{{{classname}}}::_serialize_{{{name}}}")]
{{/isString}}
{{/isDiscriminator}}
#[serde(rename = "{{{baseName}}}")]
{{#hasValidation}}
@ -989,9 +1033,9 @@ pub struct {{{classname}}} {
{{/vars}}
}
{{#vars}}
{{#isDiscriminator}}
{{#isString}}
impl {{{classname}}} {
fn _name_for_{{{name}}}() -> String {
String::from("{{{classname}}}")
@ -1004,10 +1048,10 @@ impl {{{classname}}} {
s.serialize_str(&Self::_name_for_{{{name}}}())
}
}
{{/isString}}
{{/isDiscriminator}}
{{/vars}}
{{#vars}}
{{#hasValidation}}
{{#pattern}}
@ -1035,9 +1079,9 @@ fn validate_byte_{{#lambda.lowercase}}{{{classname}}}_{{{name}}}{{/lambda.lowerc
impl {{{classname}}} {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new({{#vars}}{{^defaultValue}}{{{name}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}, {{/defaultValue}}{{/vars}}) -> {{{classname}}} {
pub fn new({{#vars}}{{^isDiscriminator}}{{^defaultValue}}{{{name}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}, {{/defaultValue}}{{/isDiscriminator}}{{#isDiscriminator}}{{^isString}}{{^defaultValue}}{{{name}}}: {{#isNullable}}Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}, {{/defaultValue}}{{/isString}}{{/isDiscriminator}}{{/vars}}) -> {{{classname}}} {
{{{classname}}} {
{{#vars}} {{#defaultValue}}{{{name}}}: {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{{name}}}{{/defaultValue}},
{{#vars}} {{^isDiscriminator}}{{#defaultValue}}{{{name}}}: {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{{name}}}{{/defaultValue}}{{/isDiscriminator}}{{#isDiscriminator}}{{#isString}}{{{name}}}: Self::_name_for_{{{name}}}(){{/isString}}{{^isString}}{{#defaultValue}}{{{name}}}: {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{{name}}}{{/defaultValue}}{{/isString}}{{/isDiscriminator}},
{{/vars}}
}
}
@ -1075,7 +1119,7 @@ impl std::fmt::Display for {{{classname}}} {
{{/isArray}}
{{#isArray}}
{{#isNullable}}
Some(self.{{{name}}}.as_ref().map_or(vec!["null".to_string()], |x| x.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(","))),
Some(self.{{{name}}}.as_ref().map_or("null".to_string(), |x| x.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(","))),
{{/isNullable}}
{{^isNullable}}
Some(self.{{{name}}}.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")),
@ -1226,7 +1270,6 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<{{{classname
}
}
}
{{/oneOf.size}}
{{/anyOf.size}}

View File

@ -594,7 +594,7 @@ pub struct PaymentMethod {
#[serde(rename = "type")]
#[validate(custom(function = "check_xss_string"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
pub r_type: Option<String>,
}
impl PaymentMethod {
@ -602,7 +602,7 @@ impl PaymentMethod {
pub fn new() -> PaymentMethod {
PaymentMethod {
name: None,
r#type: None,
r_type: None,
}
}
}
@ -616,9 +616,9 @@ impl std::fmt::Display for PaymentMethod {
self.name
.as_ref()
.map(|name| ["name".to_string(), name.to_string()].join(",")),
self.r#type
self.r_type
.as_ref()
.map(|r#type| ["type".to_string(), r#type.to_string()].join(",")),
.map(|r_type| ["type".to_string(), r_type.to_string()].join(",")),
];
write!(
@ -641,7 +641,7 @@ impl std::str::FromStr for PaymentMethod {
#[allow(dead_code)]
struct IntermediateRep {
pub name: Vec<String>,
pub r#type: Vec<String>,
pub r_type: Vec<String>,
}
let mut intermediate_rep = IntermediateRep::default();
@ -668,7 +668,7 @@ impl std::str::FromStr for PaymentMethod {
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
"type" => intermediate_rep.r#type.push(
"type" => intermediate_rep.r_type.push(
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
_ => {
@ -686,7 +686,7 @@ impl std::str::FromStr for PaymentMethod {
// Use the intermediate representation to return the struct
std::result::Result::Ok(PaymentMethod {
name: intermediate_rep.name.into_iter().next(),
r#type: intermediate_rep.r#type.into_iter().next(),
r_type: intermediate_rep.r_type.into_iter().next(),
})
}
}

View File

@ -594,7 +594,7 @@ pub struct PaymentMethod {
#[serde(rename = "type")]
#[validate(custom(function = "check_xss_string"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
pub r_type: Option<String>,
}
impl PaymentMethod {
@ -602,7 +602,7 @@ impl PaymentMethod {
pub fn new() -> PaymentMethod {
PaymentMethod {
name: None,
r#type: None,
r_type: None,
}
}
}
@ -616,9 +616,9 @@ impl std::fmt::Display for PaymentMethod {
self.name
.as_ref()
.map(|name| ["name".to_string(), name.to_string()].join(",")),
self.r#type
self.r_type
.as_ref()
.map(|r#type| ["type".to_string(), r#type.to_string()].join(",")),
.map(|r_type| ["type".to_string(), r_type.to_string()].join(",")),
];
write!(
@ -641,7 +641,7 @@ impl std::str::FromStr for PaymentMethod {
#[allow(dead_code)]
struct IntermediateRep {
pub name: Vec<String>,
pub r#type: Vec<String>,
pub r_type: Vec<String>,
}
let mut intermediate_rep = IntermediateRep::default();
@ -668,7 +668,7 @@ impl std::str::FromStr for PaymentMethod {
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
"type" => intermediate_rep.r#type.push(
"type" => intermediate_rep.r_type.push(
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
_ => {
@ -686,7 +686,7 @@ impl std::str::FromStr for PaymentMethod {
// Use the intermediate representation to return the struct
std::result::Result::Ok(PaymentMethod {
name: intermediate_rep.name.into_iter().next(),
r#type: intermediate_rep.r#type.into_iter().next(),
r_type: intermediate_rep.r_type.into_iter().next(),
})
}
}

View File

@ -767,15 +767,20 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AnotherXmlOb
}
}
/// Any of:
/// - String
/// - uuid::Uuid
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AnyOfGet202Response(Box<serde_json::value::RawValue>);
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum AnyOfGet202Response {
String(String),
Uuid(uuid::Uuid),
}
impl validator::Validate for AnyOfGet202Response {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
std::result::Result::Ok(())
match self {
Self::String(_) => std::result::Result::Ok(()),
Self::Uuid(_) => std::result::Result::Ok(()),
}
}
}
@ -790,22 +795,32 @@ impl std::str::FromStr for AnyOfGet202Response {
}
}
impl PartialEq for AnyOfGet202Response {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
impl From<String> for AnyOfGet202Response {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<uuid::Uuid> for AnyOfGet202Response {
fn from(value: uuid::Uuid) -> Self {
Self::Uuid(value)
}
}
/// Test a model containing an anyOf of a hash map
/// Any of:
/// - String
/// - std::collections::HashMap<String, String>
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AnyOfHashMapObject(Box<serde_json::value::RawValue>);
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum AnyOfHashMapObject {
String(String),
HashMapOfStringString(std::collections::HashMap<String, String>),
}
impl validator::Validate for AnyOfHashMapObject {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
std::result::Result::Ok(())
match self {
Self::String(_) => std::result::Result::Ok(()),
Self::HashMapOfStringString(_) => std::result::Result::Ok(()),
}
}
}
@ -820,21 +835,32 @@ impl std::str::FromStr for AnyOfHashMapObject {
}
}
impl PartialEq for AnyOfHashMapObject {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
impl From<String> for AnyOfHashMapObject {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<std::collections::HashMap<String, String>> for AnyOfHashMapObject {
fn from(value: std::collections::HashMap<String, String>) -> Self {
Self::HashMapOfStringString(value)
}
}
/// Test a model containing an anyOf
/// Any of:
/// - String
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AnyOfObject(Box<serde_json::value::RawValue>);
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum AnyOfObject {
String(String),
String1(String),
}
impl validator::Validate for AnyOfObject {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
std::result::Result::Ok(())
match self {
Self::String(_) => std::result::Result::Ok(()),
Self::String1(_) => std::result::Result::Ok(()),
}
}
}
@ -849,12 +875,6 @@ impl std::str::FromStr for AnyOfObject {
}
}
impl PartialEq for AnyOfObject {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
}
}
/// Test containing an anyOf object
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
@ -1166,7 +1186,7 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<DuplicateXml
/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
#[repr(C)]
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
@ -1451,14 +1471,20 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<FormTestRequ
}
/// Test a model containing an anyOf that starts with a number
/// Any of:
/// - String
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Model12345AnyOfObject(Box<serde_json::value::RawValue>);
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum Model12345AnyOfObject {
String(String),
String1(String),
}
impl validator::Validate for Model12345AnyOfObject {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
std::result::Result::Ok(())
match self {
Self::String(_) => std::result::Result::Ok(()),
Self::String1(_) => std::result::Result::Ok(()),
}
}
}
@ -1473,12 +1499,6 @@ impl std::str::FromStr for Model12345AnyOfObject {
}
}
impl PartialEq for Model12345AnyOfObject {
fn eq(&self, other: &Self) -> bool {
self.0.get() == other.0.get()
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
pub struct MultigetGet201Response {
@ -2319,8 +2339,9 @@ pub struct ObjectParam {
pub required_param: bool,
#[serde(rename = "optionalParam")]
#[validate(range(min = 1u64, max = 10000000000000000000u64))]
#[serde(skip_serializing_if = "Option::is_none")]
pub optional_param: Option<i32>,
pub optional_param: Option<u64>,
}
impl ObjectParam {
@ -2366,7 +2387,7 @@ impl std::str::FromStr for ObjectParam {
#[allow(dead_code)]
struct IntermediateRep {
pub required_param: Vec<bool>,
pub optional_param: Vec<i32>,
pub optional_param: Vec<u64>,
}
let mut intermediate_rep = IntermediateRep::default();
@ -2394,7 +2415,7 @@ impl std::str::FromStr for ObjectParam {
),
#[allow(clippy::redundant_clone)]
"optionalParam" => intermediate_rep.optional_param.push(
<i32 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
<u64 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
_ => {
return std::result::Result::Err(
@ -2813,10 +2834,10 @@ impl std::ops::DerefMut for Ok {
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum OneOfGet200Response {
I32(Box<i32>),
VecOfString(Box<Vec<String>>),
I32(i32),
VecOfString(Vec<String>),
}
impl validator::Validate for OneOfGet200Response {
@ -2828,17 +2849,6 @@ impl validator::Validate for OneOfGet200Response {
}
}
impl From<i32> for OneOfGet200Response {
fn from(value: i32) -> Self {
Self::I32(Box::new(value))
}
}
impl From<Vec<String>> for OneOfGet200Response {
fn from(value: Vec<String>) -> Self {
Self::VecOfString(Box::new(value))
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a OneOfGet200Response value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
@ -2850,6 +2860,17 @@ impl std::str::FromStr for OneOfGet200Response {
}
}
impl From<i32> for OneOfGet200Response {
fn from(value: i32) -> Self {
Self::I32(value)
}
}
impl From<Vec<String>> for OneOfGet200Response {
fn from(value: Vec<String>) -> Self {
Self::VecOfString(value)
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
pub struct OptionalObjectHeader(i32);
@ -2971,7 +2992,7 @@ impl std::ops::DerefMut for Result {
/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
#[repr(C)]
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,

View File

@ -12,7 +12,7 @@ fn test_oneof_schema_untagged() {
let test2 = r#"{"value": ["foo", "bar"]}"#;
let test3 = Test {
value: OneOfGet200Response::I32(123.into()),
value: OneOfGet200Response::I32(123),
};
let test4 = Test {
value: OneOfGet200Response::VecOfString(vec!["foo".to_string(), "bar".to_string()].into()),

View File

@ -349,6 +349,8 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<AdditionalPr
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)]
#[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))]
pub struct Animal {
#[serde(default = "Animal::_name_for_class_name")]
#[serde(serialize_with = "Animal::_serialize_class_name")]
#[serde(rename = "className")]
#[validate(custom(function = "check_xss_string"))]
pub class_name: String,
@ -359,11 +361,24 @@ pub struct Animal {
pub color: Option<String>,
}
impl Animal {
fn _name_for_class_name() -> String {
String::from("Animal")
}
fn _serialize_class_name<S>(_: &String, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
s.serialize_str(&Self::_name_for_class_name())
}
}
impl Animal {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new(class_name: String) -> Animal {
pub fn new() -> Animal {
Animal {
class_name,
class_name: Self::_name_for_class_name(),
color: Some(r#"red"#.to_string()),
}
}
@ -649,7 +664,7 @@ pub struct ApiResponse {
#[serde(rename = "type")]
#[validate(custom(function = "check_xss_string"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
pub r_type: Option<String>,
#[serde(rename = "message")]
#[validate(custom(function = "check_xss_string"))]
@ -662,7 +677,7 @@ impl ApiResponse {
pub fn new() -> ApiResponse {
ApiResponse {
code: None,
r#type: None,
r_type: None,
message: None,
}
}
@ -677,9 +692,9 @@ impl std::fmt::Display for ApiResponse {
self.code
.as_ref()
.map(|code| ["code".to_string(), code.to_string()].join(",")),
self.r#type
self.r_type
.as_ref()
.map(|r#type| ["type".to_string(), r#type.to_string()].join(",")),
.map(|r_type| ["type".to_string(), r_type.to_string()].join(",")),
self.message
.as_ref()
.map(|message| ["message".to_string(), message.to_string()].join(",")),
@ -705,7 +720,7 @@ impl std::str::FromStr for ApiResponse {
#[allow(dead_code)]
struct IntermediateRep {
pub code: Vec<i32>,
pub r#type: Vec<String>,
pub r_type: Vec<String>,
pub message: Vec<String>,
}
@ -733,7 +748,7 @@ impl std::str::FromStr for ApiResponse {
<i32 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
"type" => intermediate_rep.r#type.push(
"type" => intermediate_rep.r_type.push(
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
@ -755,7 +770,7 @@ impl std::str::FromStr for ApiResponse {
// Use the intermediate representation to return the struct
std::result::Result::Ok(ApiResponse {
code: intermediate_rep.code.into_iter().next(),
r#type: intermediate_rep.r#type.into_iter().next(),
r_type: intermediate_rep.r_type.into_iter().next(),
message: intermediate_rep.message.into_iter().next(),
})
}
@ -2539,7 +2554,7 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<EnumArrays>
/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
#[repr(C)]
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
@ -3337,7 +3352,9 @@ impl std::str::FromStr for List {
let val = match string_iter.next() {
Some(x) => x,
None => {
return std::result::Result::Err("Missing value while parsing List".to_string());
return std::result::Result::Err(
"Missing value while parsing List".to_string(),
);
}
};
@ -3976,7 +3993,9 @@ impl std::str::FromStr for Name {
let val = match string_iter.next() {
Some(x) => x,
None => {
return std::result::Result::Err("Missing value while parsing Name".to_string());
return std::result::Result::Err(
"Missing value while parsing Name".to_string(),
);
}
};
@ -4786,7 +4805,7 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<OuterComposi
/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
#[repr(C)]
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
@ -5283,13 +5302,13 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<ReadOnlyFirs
pub struct Return {
#[serde(rename = "return")]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#return: Option<i32>,
pub r_return: Option<i32>,
}
impl Return {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new() -> Return {
Return { r#return: None }
Return { r_return: None }
}
}
@ -5299,9 +5318,9 @@ impl Return {
impl std::fmt::Display for Return {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let params: Vec<Option<String>> = vec![
self.r#return
self.r_return
.as_ref()
.map(|r#return| ["return".to_string(), r#return.to_string()].join(",")),
.map(|r_return| ["return".to_string(), r_return.to_string()].join(",")),
];
write!(
@ -5323,7 +5342,7 @@ impl std::str::FromStr for Return {
#[derive(Default)]
#[allow(dead_code)]
struct IntermediateRep {
pub r#return: Vec<i32>,
pub r_return: Vec<i32>,
}
let mut intermediate_rep = IntermediateRep::default();
@ -5346,7 +5365,7 @@ impl std::str::FromStr for Return {
#[allow(clippy::match_single_binding)]
match key {
#[allow(clippy::redundant_clone)]
"return" => intermediate_rep.r#return.push(
"return" => intermediate_rep.r_return.push(
<i32 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
_ => {
@ -5363,7 +5382,7 @@ impl std::str::FromStr for Return {
// Use the intermediate representation to return the struct
std::result::Result::Ok(Return {
r#return: intermediate_rep.r#return.into_iter().next(),
r_return: intermediate_rep.r_return.into_iter().next(),
})
}
}
@ -5899,7 +5918,7 @@ impl TestEnumParametersRequest {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new() -> TestEnumParametersRequest {
TestEnumParametersRequest {
enum_form_string: Some(r#"-efg"#.to_string()),
enum_form_string: None,
}
}
}
@ -6611,7 +6630,9 @@ impl std::str::FromStr for User {
let val = match string_iter.next() {
Some(x) => x,
None => {
return std::result::Result::Err("Missing value while parsing User".to_string());
return std::result::Result::Err(
"Missing value while parsing User".to_string(),
);
}
};

View File

@ -177,7 +177,7 @@ pub struct ApiResponse {
#[serde(rename = "type")]
#[validate(custom(function = "check_xss_string"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
pub r_type: Option<String>,
#[serde(rename = "message")]
#[validate(custom(function = "check_xss_string"))]
@ -190,7 +190,7 @@ impl ApiResponse {
pub fn new() -> ApiResponse {
ApiResponse {
code: None,
r#type: None,
r_type: None,
message: None,
}
}
@ -205,9 +205,9 @@ impl std::fmt::Display for ApiResponse {
self.code
.as_ref()
.map(|code| ["code".to_string(), code.to_string()].join(",")),
self.r#type
self.r_type
.as_ref()
.map(|r#type| ["type".to_string(), r#type.to_string()].join(",")),
.map(|r_type| ["type".to_string(), r_type.to_string()].join(",")),
self.message
.as_ref()
.map(|message| ["message".to_string(), message.to_string()].join(",")),
@ -233,7 +233,7 @@ impl std::str::FromStr for ApiResponse {
#[allow(dead_code)]
struct IntermediateRep {
pub code: Vec<i32>,
pub r#type: Vec<String>,
pub r_type: Vec<String>,
pub message: Vec<String>,
}
@ -261,7 +261,7 @@ impl std::str::FromStr for ApiResponse {
<i32 as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
"type" => intermediate_rep.r#type.push(
"type" => intermediate_rep.r_type.push(
<String as std::str::FromStr>::from_str(val).map_err(|x| x.to_string())?,
),
#[allow(clippy::redundant_clone)]
@ -283,7 +283,7 @@ impl std::str::FromStr for ApiResponse {
// Use the intermediate representation to return the struct
std::result::Result::Ok(ApiResponse {
code: intermediate_rep.code.into_iter().next(),
r#type: intermediate_rep.r#type.into_iter().next(),
r_type: intermediate_rep.r_type.into_iter().next(),
message: intermediate_rep.message.into_iter().next(),
})
}
@ -1491,7 +1491,9 @@ impl std::str::FromStr for User {
let val = match string_iter.next() {
Some(x) => x,
None => {
return std::result::Result::Err("Missing value while parsing User".to_string());
return std::result::Result::Err(
"Missing value while parsing User".to_string(),
);
}
};

View File

@ -91,8 +91,11 @@ impl Goodbye {
impl Goodbye {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new(op: String, d: models::GoodbyeD) -> Goodbye {
Goodbye { op, d }
pub fn new(d: models::GoodbyeD) -> Goodbye {
Goodbye {
op: Self::_name_for_op(),
d,
}
}
}
@ -394,7 +397,7 @@ impl Greeting {
pub fn new(d: models::GreetingD) -> Greeting {
Greeting {
d,
op: r#"Greeting"#.to_string(),
op: Self::_name_for_op(),
}
}
}
@ -698,7 +701,7 @@ impl Hello {
#[allow(clippy::new_without_default, clippy::too_many_arguments)]
pub fn new(d: models::HelloD) -> Hello {
Hello {
op: r#"Hello"#.to_string(),
op: Self::_name_for_op(),
d,
}
}
@ -971,25 +974,36 @@ impl std::convert::TryFrom<HeaderValue> for header::IntoHeaderValue<HelloD> {
#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
#[serde(tag = "op")]
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum Message {
Hello(Box<models::Hello>),
Greeting(Box<models::Greeting>),
Goodbye(Box<models::Goodbye>),
SomethingCompletelyDifferent(Box<models::SomethingCompletelyDifferent>),
Hello(models::Hello),
Greeting(models::Greeting),
Goodbye(models::Goodbye),
SomethingCompletelyDifferent(models::SomethingCompletelyDifferent),
}
impl validator::Validate for Message {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
match self {
Self::Hello(x) => x.validate(),
Self::Greeting(x) => x.validate(),
Self::Goodbye(x) => x.validate(),
Self::SomethingCompletelyDifferent(x) => x.validate(),
Self::Hello(v) => v.validate(),
Self::Greeting(v) => v.validate(),
Self::Goodbye(v) => v.validate(),
Self::SomethingCompletelyDifferent(v) => v.validate(),
}
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a Message value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
impl std::str::FromStr for Message {
type Err = serde_json::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
impl serde::Serialize for Message {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -1006,64 +1020,42 @@ impl serde::Serialize for Message {
impl From<models::Hello> for Message {
fn from(value: models::Hello) -> Self {
Self::Hello(Box::new(value))
Self::Hello(value)
}
}
impl From<models::Greeting> for Message {
fn from(value: models::Greeting) -> Self {
Self::Greeting(Box::new(value))
Self::Greeting(value)
}
}
impl From<models::Goodbye> for Message {
fn from(value: models::Goodbye) -> Self {
Self::Goodbye(Box::new(value))
Self::Goodbye(value)
}
}
impl From<models::SomethingCompletelyDifferent> for Message {
fn from(value: models::SomethingCompletelyDifferent) -> Self {
Self::SomethingCompletelyDifferent(Box::new(value))
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a Message value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
impl std::str::FromStr for Message {
type Err = serde_json::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
serde_json::from_str(s)
Self::SomethingCompletelyDifferent(value)
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::large_enum_variant)]
pub enum SomethingCompletelyDifferent {
VecOfObject(Box<Vec<crate::types::Object>>),
Object(Box<crate::types::Object>),
VecOfObject(Vec<crate::types::Object>),
Object(crate::types::Object),
}
impl validator::Validate for SomethingCompletelyDifferent {
fn validate(&self) -> std::result::Result<(), validator::ValidationErrors> {
match self {
Self::VecOfObject(_) => std::result::Result::Ok(()),
Self::Object(x) => x.validate(),
Self::Object(_) => std::result::Result::Ok(()),
}
}
}
impl From<Vec<crate::types::Object>> for SomethingCompletelyDifferent {
fn from(value: Vec<crate::types::Object>) -> Self {
Self::VecOfObject(Box::new(value))
}
}
impl From<crate::types::Object> for SomethingCompletelyDifferent {
fn from(value: crate::types::Object) -> Self {
Self::Object(Box::new(value))
}
}
/// Converts Query Parameters representation (style=form, explode=false) to a SomethingCompletelyDifferent value
/// as specified in https://swagger.io/docs/specification/serialization/
/// Should be implemented in a serde deserializer
@ -1074,3 +1066,14 @@ impl std::str::FromStr for SomethingCompletelyDifferent {
serde_json::from_str(s)
}
}
impl From<Vec<crate::types::Object>> for SomethingCompletelyDifferent {
fn from(value: Vec<crate::types::Object>) -> Self {
Self::VecOfObject(value)
}
}
impl From<crate::types::Object> for SomethingCompletelyDifferent {
fn from(value: crate::types::Object) -> Self {
Self::Object(value)
}
}