From efe34d37b933b16c05a864a1a638ef1e79b55af3 Mon Sep 17 00:00:00 2001 From: polyprogrammist Date: Fri, 5 Dec 2025 01:05:19 +0800 Subject: [PATCH] fix allOf of oneOfs by introducing cartesian product --- typify-impl/src/merge.rs | 41 +- typify-impl/tests/github.out | 396 +---------- .../tests/schemas/allof_multiple_oneof.json | 75 ++ typify/tests/schemas/allof_multiple_oneof.rs | 661 ++++++++++++++++++ 4 files changed, 779 insertions(+), 394 deletions(-) create mode 100644 typify/tests/schemas/allof_multiple_oneof.json create mode 100644 typify/tests/schemas/allof_multiple_oneof.rs diff --git a/typify-impl/src/merge.rs b/typify-impl/src/merge.rs index 8e9104de..1720be92 100644 --- a/typify-impl/src/merge.rs +++ b/typify-impl/src/merge.rs @@ -332,7 +332,20 @@ pub(crate) fn try_merge_with_subschemas( } if let Some(one_of) = one_of { - let merged_subschemas = try_merge_with_each_subschema(&schema_object, one_of, defs); + // Check if the base schema already has a oneOf - if so, we need to + // compute the Cartesian product of the two oneOfs + let base_one_of = schema_object + .subschemas + .as_ref() + .and_then(|ss| ss.one_of.as_ref()); + + let merged_subschemas = if let Some(base_variants) = base_one_of { + // Cartesian product: for each base variant and each new variant, + // merge them together + try_merge_oneof_cartesian_product(base_variants, one_of, defs) + } else { + try_merge_with_each_subschema(&schema_object, one_of, defs) + }; match merged_subschemas.len() { 0 => return Err(()), @@ -413,6 +426,32 @@ fn try_merge_with_each_subschema( joined_schemas } +/// Compute the Cartesian product of two oneOf schemas. For each combination +/// of a variant from the first oneOf and a variant from the second oneOf, +/// merge them together. This is used when we have `allOf: [oneOf[A,B], oneOf[C,D]]` +/// which should produce `oneOf[A∩C, A∩D, B∩C, B∩D]`. +fn try_merge_oneof_cartesian_product( + base_variants: &[Schema], + new_variants: &[Schema], + defs: &BTreeMap, +) -> Vec { + let mut result = Vec::new(); + + for base_variant in base_variants { + for new_variant in new_variants { + // Try to merge each pair of variants + if let Ok(merged) = try_merge_schema(base_variant, new_variant, defs) { + // Only include if the merge produced a satisfiable schema + if merged != Schema::Bool(false) { + result.push(merged); + } + } + } + } + + result +} + fn merge_schema_not( schema: &Schema, not_schema: &Schema, diff --git a/typify-impl/tests/github.out b/typify-impl/tests/github.out index 3cede02a..55e9eebf 100644 --- a/typify-impl/tests/github.out +++ b/typify-impl/tests/github.out @@ -41187,7 +41187,7 @@ impl ::std::convert::TryFrom<::std::string::String> for IssueCommentCreatedActio #[serde(deny_unknown_fields)] pub struct IssueCommentCreatedIssue { pub active_lock_reason: ::std::option::Option, - pub assignee: ::std::option::Option, + pub assignee: ::std::option::Option, pub assignees: ::std::vec::Vec, pub author_association: AuthorAssociation, #[doc = "Contents of the issue"] @@ -41300,136 +41300,6 @@ impl ::std::convert::TryFrom<::std::string::String> for IssueCommentCreatedIssue value.parse() } } -#[doc = "`IssueCommentCreatedIssueAssignee`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"allOf\": ["] -#[doc = " {"] -#[doc = " \"oneOf\": ["] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " ]"] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"not\": {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " }"] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct IssueCommentCreatedIssueAssignee { - pub avatar_url: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub email: ::std::option::Option<::std::string::String>, - pub events_url: ::std::string::String, - pub followers_url: ::std::string::String, - pub following_url: ::std::string::String, - pub gists_url: ::std::string::String, - pub gravatar_id: ::std::string::String, - pub html_url: ::std::string::String, - pub id: i64, - pub login: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub name: ::std::option::Option<::std::string::String>, - pub node_id: ::std::string::String, - pub organizations_url: ::std::string::String, - pub received_events_url: ::std::string::String, - pub repos_url: ::std::string::String, - pub site_admin: bool, - pub starred_url: ::std::string::String, - pub subscriptions_url: ::std::string::String, - #[serde(rename = "type")] - pub type_: IssueCommentCreatedIssueAssigneeType, - pub url: ::std::string::String, -} -#[doc = "`IssueCommentCreatedIssueAssigneeType`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"type\": \"string\","] -#[doc = " \"enum\": ["] -#[doc = " \"Bot\","] -#[doc = " \"User\","] -#[doc = " \"Organization\""] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive( - :: serde :: Deserialize, - :: serde :: Serialize, - Clone, - Copy, - Debug, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, -)] -pub enum IssueCommentCreatedIssueAssigneeType { - Bot, - User, - Organization, -} -impl ::std::fmt::Display for IssueCommentCreatedIssueAssigneeType { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - match *self { - Self::Bot => f.write_str("Bot"), - Self::User => f.write_str("User"), - Self::Organization => f.write_str("Organization"), - } - } -} -impl ::std::str::FromStr for IssueCommentCreatedIssueAssigneeType { - type Err = self::error::ConversionError; - fn from_str(value: &str) -> ::std::result::Result { - match value { - "Bot" => Ok(Self::Bot), - "User" => Ok(Self::User), - "Organization" => Ok(Self::Organization), - _ => Err("invalid value".into()), - } - } -} -impl ::std::convert::TryFrom<&str> for IssueCommentCreatedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from(value: &str) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<&::std::string::String> for IssueCommentCreatedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: &::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<::std::string::String> for IssueCommentCreatedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: ::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} #[doc = "`IssueCommentCreatedIssuePullRequest`"] #[doc = r""] #[doc = r"
JSON schema"] @@ -41829,7 +41699,7 @@ impl ::std::convert::TryFrom<::std::string::String> for IssueCommentDeletedActio #[serde(deny_unknown_fields)] pub struct IssueCommentDeletedIssue { pub active_lock_reason: ::std::option::Option, - pub assignee: ::std::option::Option, + pub assignee: ::std::option::Option, pub assignees: ::std::vec::Vec, pub author_association: AuthorAssociation, #[doc = "Contents of the issue"] @@ -41942,136 +41812,6 @@ impl ::std::convert::TryFrom<::std::string::String> for IssueCommentDeletedIssue value.parse() } } -#[doc = "`IssueCommentDeletedIssueAssignee`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"allOf\": ["] -#[doc = " {"] -#[doc = " \"oneOf\": ["] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " ]"] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"not\": {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " }"] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct IssueCommentDeletedIssueAssignee { - pub avatar_url: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub email: ::std::option::Option<::std::string::String>, - pub events_url: ::std::string::String, - pub followers_url: ::std::string::String, - pub following_url: ::std::string::String, - pub gists_url: ::std::string::String, - pub gravatar_id: ::std::string::String, - pub html_url: ::std::string::String, - pub id: i64, - pub login: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub name: ::std::option::Option<::std::string::String>, - pub node_id: ::std::string::String, - pub organizations_url: ::std::string::String, - pub received_events_url: ::std::string::String, - pub repos_url: ::std::string::String, - pub site_admin: bool, - pub starred_url: ::std::string::String, - pub subscriptions_url: ::std::string::String, - #[serde(rename = "type")] - pub type_: IssueCommentDeletedIssueAssigneeType, - pub url: ::std::string::String, -} -#[doc = "`IssueCommentDeletedIssueAssigneeType`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"type\": \"string\","] -#[doc = " \"enum\": ["] -#[doc = " \"Bot\","] -#[doc = " \"User\","] -#[doc = " \"Organization\""] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive( - :: serde :: Deserialize, - :: serde :: Serialize, - Clone, - Copy, - Debug, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, -)] -pub enum IssueCommentDeletedIssueAssigneeType { - Bot, - User, - Organization, -} -impl ::std::fmt::Display for IssueCommentDeletedIssueAssigneeType { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - match *self { - Self::Bot => f.write_str("Bot"), - Self::User => f.write_str("User"), - Self::Organization => f.write_str("Organization"), - } - } -} -impl ::std::str::FromStr for IssueCommentDeletedIssueAssigneeType { - type Err = self::error::ConversionError; - fn from_str(value: &str) -> ::std::result::Result { - match value { - "Bot" => Ok(Self::Bot), - "User" => Ok(Self::User), - "Organization" => Ok(Self::Organization), - _ => Err("invalid value".into()), - } - } -} -impl ::std::convert::TryFrom<&str> for IssueCommentDeletedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from(value: &str) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<&::std::string::String> for IssueCommentDeletedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: &::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<::std::string::String> for IssueCommentDeletedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: ::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} #[doc = "`IssueCommentDeletedIssuePullRequest`"] #[doc = r""] #[doc = r"
JSON schema"] @@ -42559,7 +42299,7 @@ pub struct IssueCommentEditedChangesBody { #[serde(deny_unknown_fields)] pub struct IssueCommentEditedIssue { pub active_lock_reason: ::std::option::Option, - pub assignee: ::std::option::Option, + pub assignee: ::std::option::Option, pub assignees: ::std::vec::Vec, pub author_association: AuthorAssociation, #[doc = "Contents of the issue"] @@ -42672,136 +42412,6 @@ impl ::std::convert::TryFrom<::std::string::String> for IssueCommentEditedIssueA value.parse() } } -#[doc = "`IssueCommentEditedIssueAssignee`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"allOf\": ["] -#[doc = " {"] -#[doc = " \"oneOf\": ["] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " ]"] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"$ref\": \"#/definitions/user\""] -#[doc = " },"] -#[doc = " {"] -#[doc = " \"not\": {"] -#[doc = " \"type\": \"null\""] -#[doc = " }"] -#[doc = " }"] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)] -#[serde(deny_unknown_fields)] -pub struct IssueCommentEditedIssueAssignee { - pub avatar_url: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub email: ::std::option::Option<::std::string::String>, - pub events_url: ::std::string::String, - pub followers_url: ::std::string::String, - pub following_url: ::std::string::String, - pub gists_url: ::std::string::String, - pub gravatar_id: ::std::string::String, - pub html_url: ::std::string::String, - pub id: i64, - pub login: ::std::string::String, - #[serde(default, skip_serializing_if = "::std::option::Option::is_none")] - pub name: ::std::option::Option<::std::string::String>, - pub node_id: ::std::string::String, - pub organizations_url: ::std::string::String, - pub received_events_url: ::std::string::String, - pub repos_url: ::std::string::String, - pub site_admin: bool, - pub starred_url: ::std::string::String, - pub subscriptions_url: ::std::string::String, - #[serde(rename = "type")] - pub type_: IssueCommentEditedIssueAssigneeType, - pub url: ::std::string::String, -} -#[doc = "`IssueCommentEditedIssueAssigneeType`"] -#[doc = r""] -#[doc = r"
JSON schema"] -#[doc = r""] -#[doc = r" ```json"] -#[doc = "{"] -#[doc = " \"type\": \"string\","] -#[doc = " \"enum\": ["] -#[doc = " \"Bot\","] -#[doc = " \"User\","] -#[doc = " \"Organization\""] -#[doc = " ]"] -#[doc = "}"] -#[doc = r" ```"] -#[doc = r"
"] -#[derive( - :: serde :: Deserialize, - :: serde :: Serialize, - Clone, - Copy, - Debug, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, -)] -pub enum IssueCommentEditedIssueAssigneeType { - Bot, - User, - Organization, -} -impl ::std::fmt::Display for IssueCommentEditedIssueAssigneeType { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - match *self { - Self::Bot => f.write_str("Bot"), - Self::User => f.write_str("User"), - Self::Organization => f.write_str("Organization"), - } - } -} -impl ::std::str::FromStr for IssueCommentEditedIssueAssigneeType { - type Err = self::error::ConversionError; - fn from_str(value: &str) -> ::std::result::Result { - match value { - "Bot" => Ok(Self::Bot), - "User" => Ok(Self::User), - "Organization" => Ok(Self::Organization), - _ => Err("invalid value".into()), - } - } -} -impl ::std::convert::TryFrom<&str> for IssueCommentEditedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from(value: &str) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<&::std::string::String> for IssueCommentEditedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: &::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} -impl ::std::convert::TryFrom<::std::string::String> for IssueCommentEditedIssueAssigneeType { - type Error = self::error::ConversionError; - fn try_from( - value: ::std::string::String, - ) -> ::std::result::Result { - value.parse() - } -} #[doc = "`IssueCommentEditedIssuePullRequest`"] #[doc = r""] #[doc = r"
JSON schema"] diff --git a/typify/tests/schemas/allof_multiple_oneof.json b/typify/tests/schemas/allof_multiple_oneof.json new file mode 100644 index 00000000..cec8c80e --- /dev/null +++ b/typify/tests/schemas/allof_multiple_oneof.json @@ -0,0 +1,75 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "definitions": { + "MyStruct": { + "allOf": [ + { + "oneOf": [ + { + "properties": { + "myfirsttag": { + "enum": [ + "a" + ], + "type": "string" + } + }, + "required": [ + "myfirsttag" + ], + "type": "object" + }, + { + "properties": { + "myfirsttag": { + "enum": [ + "b" + ], + "type": "string" + } + }, + "required": [ + "myfirsttag" + ], + "type": "object" + } + ] + }, + { + "oneOf": [ + { + "properties": { + "mysecondtag": { + "enum": [ + "c" + ], + "type": "string" + } + }, + "required": [ + "mysecondtag" + ], + "type": "object" + }, + { + "properties": { + "mysecondtag": { + "enum": [ + "d" + ], + "type": "string" + } + }, + "required": [ + "mysecondtag" + ], + "type": "object" + } + ] + } + ], + "title": "MyStruct", + "type": "object" + } + } +} diff --git a/typify/tests/schemas/allof_multiple_oneof.rs b/typify/tests/schemas/allof_multiple_oneof.rs new file mode 100644 index 00000000..5ad5c7c9 --- /dev/null +++ b/typify/tests/schemas/allof_multiple_oneof.rs @@ -0,0 +1,661 @@ +#![deny(warnings)] +#[doc = r" Error types."] +pub mod error { + #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] + pub struct ConversionError(::std::borrow::Cow<'static, str>); + impl ::std::error::Error for ConversionError {} + impl ::std::fmt::Display for ConversionError { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Display::fmt(&self.0, f) + } + } + impl ::std::fmt::Debug for ConversionError { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { + ::std::fmt::Debug::fmt(&self.0, f) + } + } + impl From<&'static str> for ConversionError { + fn from(value: &'static str) -> Self { + Self(value.into()) + } + } + impl From for ConversionError { + fn from(value: String) -> Self { + Self(value.into()) + } + } +} +#[doc = "`MyStruct`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"title\": \"MyStruct\","] +#[doc = " \"type\": \"object\","] +#[doc = " \"allOf\": ["] +#[doc = " {"] +#[doc = " \"oneOf\": ["] +#[doc = " {"] +#[doc = " \"type\": \"object\","] +#[doc = " \"required\": ["] +#[doc = " \"myfirsttag\""] +#[doc = " ],"] +#[doc = " \"properties\": {"] +#[doc = " \"myfirsttag\": {"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"a\""] +#[doc = " ]"] +#[doc = " }"] +#[doc = " }"] +#[doc = " },"] +#[doc = " {"] +#[doc = " \"type\": \"object\","] +#[doc = " \"required\": ["] +#[doc = " \"myfirsttag\""] +#[doc = " ],"] +#[doc = " \"properties\": {"] +#[doc = " \"myfirsttag\": {"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"b\""] +#[doc = " ]"] +#[doc = " }"] +#[doc = " }"] +#[doc = " }"] +#[doc = " ]"] +#[doc = " },"] +#[doc = " {"] +#[doc = " \"oneOf\": ["] +#[doc = " {"] +#[doc = " \"type\": \"object\","] +#[doc = " \"required\": ["] +#[doc = " \"mysecondtag\""] +#[doc = " ],"] +#[doc = " \"properties\": {"] +#[doc = " \"mysecondtag\": {"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"c\""] +#[doc = " ]"] +#[doc = " }"] +#[doc = " }"] +#[doc = " },"] +#[doc = " {"] +#[doc = " \"type\": \"object\","] +#[doc = " \"required\": ["] +#[doc = " \"mysecondtag\""] +#[doc = " ],"] +#[doc = " \"properties\": {"] +#[doc = " \"mysecondtag\": {"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"d\""] +#[doc = " ]"] +#[doc = " }"] +#[doc = " }"] +#[doc = " }"] +#[doc = " ]"] +#[doc = " }"] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)] +#[serde(untagged)] +pub enum MyStruct { + Variant0 { + myfirsttag: MyStructVariant0Myfirsttag, + mysecondtag: MyStructVariant0Mysecondtag, + }, + Variant1 { + myfirsttag: MyStructVariant1Myfirsttag, + mysecondtag: MyStructVariant1Mysecondtag, + }, + Variant2 { + myfirsttag: MyStructVariant2Myfirsttag, + mysecondtag: MyStructVariant2Mysecondtag, + }, + Variant3 { + myfirsttag: MyStructVariant3Myfirsttag, + mysecondtag: MyStructVariant3Mysecondtag, + }, +} +#[doc = "`MyStructVariant0Myfirsttag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"a\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant0Myfirsttag { + #[serde(rename = "a")] + A, +} +impl ::std::fmt::Display for MyStructVariant0Myfirsttag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::A => f.write_str("a"), + } + } +} +impl ::std::str::FromStr for MyStructVariant0Myfirsttag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "a" => Ok(Self::A), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant0Myfirsttag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant0Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant0Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant0Mysecondtag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"c\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant0Mysecondtag { + #[serde(rename = "c")] + C, +} +impl ::std::fmt::Display for MyStructVariant0Mysecondtag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::C => f.write_str("c"), + } + } +} +impl ::std::str::FromStr for MyStructVariant0Mysecondtag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "c" => Ok(Self::C), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant0Mysecondtag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant0Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant0Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant1Myfirsttag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"a\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant1Myfirsttag { + #[serde(rename = "a")] + A, +} +impl ::std::fmt::Display for MyStructVariant1Myfirsttag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::A => f.write_str("a"), + } + } +} +impl ::std::str::FromStr for MyStructVariant1Myfirsttag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "a" => Ok(Self::A), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant1Myfirsttag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant1Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant1Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant1Mysecondtag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"d\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant1Mysecondtag { + #[serde(rename = "d")] + D, +} +impl ::std::fmt::Display for MyStructVariant1Mysecondtag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::D => f.write_str("d"), + } + } +} +impl ::std::str::FromStr for MyStructVariant1Mysecondtag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "d" => Ok(Self::D), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant1Mysecondtag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant1Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant1Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant2Myfirsttag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"b\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant2Myfirsttag { + #[serde(rename = "b")] + B, +} +impl ::std::fmt::Display for MyStructVariant2Myfirsttag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::B => f.write_str("b"), + } + } +} +impl ::std::str::FromStr for MyStructVariant2Myfirsttag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "b" => Ok(Self::B), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant2Myfirsttag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant2Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant2Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant2Mysecondtag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"c\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant2Mysecondtag { + #[serde(rename = "c")] + C, +} +impl ::std::fmt::Display for MyStructVariant2Mysecondtag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::C => f.write_str("c"), + } + } +} +impl ::std::str::FromStr for MyStructVariant2Mysecondtag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "c" => Ok(Self::C), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant2Mysecondtag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant2Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant2Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant3Myfirsttag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"b\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant3Myfirsttag { + #[serde(rename = "b")] + B, +} +impl ::std::fmt::Display for MyStructVariant3Myfirsttag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::B => f.write_str("b"), + } + } +} +impl ::std::str::FromStr for MyStructVariant3Myfirsttag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "b" => Ok(Self::B), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant3Myfirsttag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant3Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant3Myfirsttag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +#[doc = "`MyStructVariant3Mysecondtag`"] +#[doc = r""] +#[doc = r"
JSON schema"] +#[doc = r""] +#[doc = r" ```json"] +#[doc = "{"] +#[doc = " \"type\": \"string\","] +#[doc = " \"enum\": ["] +#[doc = " \"d\""] +#[doc = " ]"] +#[doc = "}"] +#[doc = r" ```"] +#[doc = r"
"] +#[derive( + :: serde :: Deserialize, + :: serde :: Serialize, + Clone, + Copy, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, +)] +pub enum MyStructVariant3Mysecondtag { + #[serde(rename = "d")] + D, +} +impl ::std::fmt::Display for MyStructVariant3Mysecondtag { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match *self { + Self::D => f.write_str("d"), + } + } +} +impl ::std::str::FromStr for MyStructVariant3Mysecondtag { + type Err = self::error::ConversionError; + fn from_str(value: &str) -> ::std::result::Result { + match value { + "d" => Ok(Self::D), + _ => Err("invalid value".into()), + } + } +} +impl ::std::convert::TryFrom<&str> for MyStructVariant3Mysecondtag { + type Error = self::error::ConversionError; + fn try_from(value: &str) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<&::std::string::String> for MyStructVariant3Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: &::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +impl ::std::convert::TryFrom<::std::string::String> for MyStructVariant3Mysecondtag { + type Error = self::error::ConversionError; + fn try_from( + value: ::std::string::String, + ) -> ::std::result::Result { + value.parse() + } +} +fn main() {}