From 17ceaae16ef73fdc7dd77dba7e6820ac09134595 Mon Sep 17 00:00:00 2001 From: Fawdlstty Date: Wed, 3 Dec 2025 11:48:45 +0800 Subject: [PATCH] [rust] add deser support for enum type (#8803) * add deser support for enum type * update generated files * remove deser generator when bitflag enable * add deser test * Restore the Rust editions version * Remove unnecessary modifications --- src/idl_gen_rust.cpp | 23 +++++++++++++++++++ .../any_ambiguous_aliases_generated.rs | 19 +++++++++++++++ .../my_game/example/any_generated.rs | 19 +++++++++++++++ .../example/any_unique_aliases_generated.rs | 19 +++++++++++++++ .../my_game/example/race_generated.rs | 19 +++++++++++++++ .../from_include_generated.rs | 19 +++++++++++++++ tests/rust_serialize_test/Cargo.toml | 1 - tests/rust_serialize_test/src/main.rs | 12 +++++++++- 8 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index be4091d5f..22df1dcf0 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -841,6 +841,29 @@ class RustGenerator : public BaseGenerator { code_ += " }"; code_ += "}"; code_ += ""; + + if (!IsBitFlagsEnum(enum_def)) { + code_ += "impl<'de> serde::Deserialize<'de> for {{ENUM_TY}} {"; + code_ += + " fn deserialize(deserializer: D) -> Result"; + code_ += " where"; + code_ += " D: serde::Deserializer<'de>,"; + code_ += " {"; + code_ += " let s = String::deserialize(deserializer)?;"; + code_ += " for item in {{ENUM_TY}}::ENUM_VALUES {"; + code_ += " if let Some(item_name) = item.variant_name() {"; + code_ += " if item_name == s {"; + code_ += " return Ok(item.clone());"; + code_ += " }"; + code_ += " }"; + code_ += " }"; + code_ += " Err(serde::de::Error::custom(format!("; + code_ += " \"Unknown {{ENUM_TY}} variant: {s}\""; + code_ += " )))"; + code_ += " }"; + code_ += "}"; + code_ += ""; + } } // Generate Follow and Push so we can serialize and stuff. diff --git a/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs b/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs index 25c2f9fe3..c3c54eece 100644 --- a/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs @@ -71,6 +71,25 @@ impl Serialize for AnyAmbiguousAliases { } } +impl<'de> serde::Deserialize<'de> for AnyAmbiguousAliases { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + for item in AnyAmbiguousAliases::ENUM_VALUES { + if let Some(item_name) = item.variant_name() { + if item_name == s { + return Ok(item.clone()); + } + } + } + Err(serde::de::Error::custom(format!( + "Unknown AnyAmbiguousAliases variant: {s}" + ))) + } +} + impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases { type Inner = Self; #[inline] diff --git a/tests/monster_test_serialize/my_game/example/any_generated.rs b/tests/monster_test_serialize/my_game/example/any_generated.rs index 2781a59e6..02880890c 100644 --- a/tests/monster_test_serialize/my_game/example/any_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_generated.rs @@ -71,6 +71,25 @@ impl Serialize for Any { } } +impl<'de> serde::Deserialize<'de> for Any { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + for item in Any::ENUM_VALUES { + if let Some(item_name) = item.variant_name() { + if item_name == s { + return Ok(item.clone()); + } + } + } + Err(serde::de::Error::custom(format!( + "Unknown Any variant: {s}" + ))) + } +} + impl<'a> flatbuffers::Follow<'a> for Any { type Inner = Self; #[inline] diff --git a/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs b/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs index 3ae88c3f2..89ae6d4b8 100644 --- a/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs @@ -71,6 +71,25 @@ impl Serialize for AnyUniqueAliases { } } +impl<'de> serde::Deserialize<'de> for AnyUniqueAliases { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + for item in AnyUniqueAliases::ENUM_VALUES { + if let Some(item_name) = item.variant_name() { + if item_name == s { + return Ok(item.clone()); + } + } + } + Err(serde::de::Error::custom(format!( + "Unknown AnyUniqueAliases variant: {s}" + ))) + } +} + impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases { type Inner = Self; #[inline] diff --git a/tests/monster_test_serialize/my_game/example/race_generated.rs b/tests/monster_test_serialize/my_game/example/race_generated.rs index 681b627b5..c1c061819 100644 --- a/tests/monster_test_serialize/my_game/example/race_generated.rs +++ b/tests/monster_test_serialize/my_game/example/race_generated.rs @@ -71,6 +71,25 @@ impl Serialize for Race { } } +impl<'de> serde::Deserialize<'de> for Race { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + for item in Race::ENUM_VALUES { + if let Some(item_name) = item.variant_name() { + if item_name == s { + return Ok(item.clone()); + } + } + } + Err(serde::de::Error::custom(format!( + "Unknown Race variant: {s}" + ))) + } +} + impl<'a> flatbuffers::Follow<'a> for Race { type Inner = Self; #[inline] diff --git a/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs b/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs index 17a951a65..647fd6aff 100644 --- a/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs +++ b/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs @@ -59,6 +59,25 @@ impl Serialize for FromInclude { } } +impl<'de> serde::Deserialize<'de> for FromInclude { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + for item in FromInclude::ENUM_VALUES { + if let Some(item_name) = item.variant_name() { + if item_name == s { + return Ok(item.clone()); + } + } + } + Err(serde::de::Error::custom(format!( + "Unknown FromInclude variant: {s}" + ))) + } +} + impl<'a> flatbuffers::Follow<'a> for FromInclude { type Inner = Self; #[inline] diff --git a/tests/rust_serialize_test/Cargo.toml b/tests/rust_serialize_test/Cargo.toml index ff47c123e..4a28955da 100644 --- a/tests/rust_serialize_test/Cargo.toml +++ b/tests/rust_serialize_test/Cargo.toml @@ -9,4 +9,3 @@ edition = "2021" flatbuffers = { path = "../../rust/flatbuffers", features=["serialize"] } serde = "1.0" serde_json = "1.0" - diff --git a/tests/rust_serialize_test/src/main.rs b/tests/rust_serialize_test/src/main.rs index 239e2a4e9..0978da049 100644 --- a/tests/rust_serialize_test/src/main.rs +++ b/tests/rust_serialize_test/src/main.rs @@ -3,6 +3,9 @@ mod monster_test_serialize_generated; pub use monster_test_serialize_generated::my_game; +use crate::my_game::example::AnyAmbiguousAliases; +use std::collections::HashMap; + fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) { let mon = { let s0 = builder.create_string("test1"); @@ -29,7 +32,10 @@ fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::Flat test: Some( my_game::example::Monster::create( builder, - &my_game::example::MonsterArgs { name: Some(fred_name), ..Default::default() }, + &my_game::example::MonsterArgs { + name: Some(fred_name), + ..Default::default() + }, ) .as_union_value(), ), @@ -83,4 +89,8 @@ fn main() { let t1 = testarrayofstring[1].as_str().unwrap(); assert_eq!(t1, "test2"); + + let s = r#"{"val":"M1"}"#; + let des = serde_json::from_str::>(s).unwrap(); + assert_eq!(*des.get("val").unwrap(), AnyAmbiguousAliases::M1); }