Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust/flatbuffers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ rust-version = "1.51"
[features]
default = ["std"]
std = []
serialize = ["serde"]
serialize = ["serde", "serde/derive"]

[dependencies]
bitflags = "2.8.0"
Expand Down
47 changes: 35 additions & 12 deletions src/idl_gen_rust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,13 +854,18 @@ class RustGenerator : public BaseGenerator {
code_ += "}";
code_ += "";

if (!IsBitFlagsEnum(enum_def)) {
code_ += "impl<'de> serde::Deserialize<'de> for {{ENUM_TY}} {";
code_ += "impl<'de> serde::Deserialize<'de> for {{ENUM_TY}} {";
code_ +=
" fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>";
code_ += " where";
code_ += " D: serde::Deserializer<'de>,";
code_ += " {";
if (IsBitFlagsEnum(enum_def)) {
code_ +=
" fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>";
code_ += " where";
code_ += " D: serde::Deserializer<'de>,";
code_ += " {";
" let bits = <{{BASE_TYPE}} as "
"serde::Deserialize>::deserialize(deserializer)?;";
code_ += " Ok(Self::from_bits_retain(bits as {{BASE_TYPE}}))";
} else {
code_ += " let s = String::deserialize(deserializer)?;";
code_ += " for item in {{ENUM_TY}}::ENUM_VALUES {";
code_ +=
Expand All @@ -874,10 +879,10 @@ class RustGenerator : public BaseGenerator {
code_ += " Err(serde::de::Error::custom(format!(";
code_ += " \"Unknown {{ENUM_TY}} variant: {s}\"";
code_ += " )))";
code_ += " }";
code_ += "}";
code_ += "";
}
code_ += " }";
code_ += "}";
code_ += "";
}

// Generate Follow and Push so we can serialize and stuff.
Expand Down Expand Up @@ -982,7 +987,13 @@ class RustGenerator : public BaseGenerator {
code_ += "#[allow(clippy::upper_case_acronyms)]"; // NONE's spelling is
// intended.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
if (parser_.opts.rust_serialize) {
code_ +=
"#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]";
code_ += "#[serde(tag = \"type\", content = \"value\")]";
} else {
code_ += "#[derive(Debug, Clone, PartialEq)]";
}
code_ += "{{ACCESS_TYPE}} enum {{ENUM_OTY}} {";
code_ += " NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
Expand Down Expand Up @@ -2322,12 +2333,20 @@ class RustGenerator : public BaseGenerator {

// Generate the native object.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
if (parser_.opts.rust_serialize) {
code_ += "#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]";
} else {
code_ += "#[derive(Debug, Clone, PartialEq)]";
}
code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
ForAllObjectTableFields(table, [&](const FieldDef& field) {
// Union objects combine both the union discriminant and value, so we
// skip making a field for the discriminant.
if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
if (parser_.opts.rust_serialize && field.IsOptional() &&
!IsUnion(field.value.type)) {
code_ += "#[serde(default, skip_serializing_if = \"Option::is_none\")]";
}
code_ += "pub {{FIELD}}: {{FIELD_OTY}},";
});
code_ += "}";
Expand Down Expand Up @@ -3037,7 +3056,11 @@ class RustGenerator : public BaseGenerator {
if (parser_.opts.generate_object_based_api) {
// Struct declaration
code_ += "";
code_ += "#[derive(Debug, Clone, PartialEq)]";
if (parser_.opts.rust_serialize) {
code_ += "#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]";
} else {
code_ += "#[derive(Debug, Clone, PartialEq)]";
}
code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
ForAllStructFields(struct_def, [&](const FieldDef& field) {
(void)field; // unused.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl<'a> Ability {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct AbilityT {
pub id: u32,
pub distance: u32,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ pub struct AnyAmbiguousAliasesUnionTableOffset {}

#[allow(clippy::upper_case_acronyms)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum AnyAmbiguousAliasesT {
NONE,
M1(alloc::boxed::Box<MonsterT>),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ pub struct AnyUnionTableOffset {}

#[allow(clippy::upper_case_acronyms)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum AnyT {
NONE,
Monster(alloc::boxed::Box<MonsterT>),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ pub struct AnyUniqueAliasesUnionTableOffset {}

#[allow(clippy::upper_case_acronyms)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum AnyUniqueAliasesT {
NONE,
M(alloc::boxed::Box<MonsterT>),
Expand Down
10 changes: 10 additions & 0 deletions tests/monster_test_serialize/my_game/example/color_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ impl Serialize for Color {
}
}

impl<'de> serde::Deserialize<'de> for Color {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bits = <u8 as serde::Deserialize>::deserialize(deserializer)?;
Ok(Self::from_bits_retain(bits as u8))
}
}

impl<'a> ::flatbuffers::Follow<'a> for Color {
type Inner = Self;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ impl Serialize for LongEnum {
}
}

impl<'de> serde::Deserialize<'de> for LongEnum {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bits = <u64 as serde::Deserialize>::deserialize(deserializer)?;
Ok(Self::from_bits_retain(bits as u64))
}
}

impl<'a> ::flatbuffers::Follow<'a> for LongEnum {
type Inner = Self;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1972,20 +1972,28 @@ impl ::core::fmt::Debug for Monster<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct MonsterT {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pos: Option<Vec3T>,
pub mana: i16,
pub hp: i16,
pub name: alloc::string::String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub inventory: Option<alloc::vec::Vec<u8>>,
pub color: Color,
pub test: AnyT,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub test4: Option<alloc::vec::Vec<TestT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testarrayofstring: Option<alloc::vec::Vec<alloc::string::String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testarrayoftables: Option<alloc::vec::Vec<MonsterT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enemy: Option<alloc::boxed::Box<MonsterT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testnestedflatbuffer: Option<alloc::vec::Vec<u8>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testempty: Option<alloc::boxed::Box<StatT>>,
pub testbool: bool,
pub testhashs32_fnv1: i32,
Expand All @@ -1996,31 +2004,48 @@ pub struct MonsterT {
pub testhashu32_fnv1a: u32,
pub testhashs64_fnv1a: i64,
pub testhashu64_fnv1a: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testarrayofbools: Option<alloc::vec::Vec<bool>>,
pub testf: f32,
pub testf2: f32,
pub testf3: f32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testarrayofstring2: Option<alloc::vec::Vec<alloc::string::String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testarrayofsortedstruct: Option<alloc::vec::Vec<AbilityT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub flex: Option<alloc::vec::Vec<u8>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub test5: Option<alloc::vec::Vec<TestT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_longs: Option<alloc::vec::Vec<i64>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_doubles: Option<alloc::vec::Vec<f64>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_namespace_test: Option<alloc::boxed::Box<super::InParentNamespaceT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_referrables: Option<alloc::vec::Vec<ReferrableT>>,
pub single_weak_reference: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_weak_references: Option<alloc::vec::Vec<u64>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_strong_referrables: Option<alloc::vec::Vec<ReferrableT>>,
pub co_owning_reference: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_co_owning_references: Option<alloc::vec::Vec<u64>>,
pub non_owning_reference: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_non_owning_references: Option<alloc::vec::Vec<u64>>,
pub any_unique: AnyUniqueAliasesT,
pub any_ambiguous: AnyAmbiguousAliasesT,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vector_of_enums: Option<alloc::vec::Vec<Color>>,
pub signed_enum: Race,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub testrequirednestedflatbuffer: Option<alloc::vec::Vec<u8>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scalar_key_sorted_tables: Option<alloc::vec::Vec<StatT>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub native_inline: Option<TestT>,
pub long_enum_non_enum_default: LongEnum,
pub long_enum_normal_default: LongEnum,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl ::core::fmt::Debug for Referrable<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ReferrableT {
pub id: u64,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ impl ::core::fmt::Debug for Stat<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct StatT {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub id: Option<alloc::string::String>,
pub val: i64,
pub count: u16,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl<'a> StructOfStructs {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct StructOfStructsT {
pub a: AbilityT,
pub b: TestT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl<'a> StructOfStructsOfStructs {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct StructOfStructsOfStructsT {
pub a: StructOfStructsT,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl<'a> Test {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct TestT {
pub a: i16,
pub b: i8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl ::core::fmt::Debug for TestSimpleTableWithEnum<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct TestSimpleTableWithEnumT {
pub color: Color,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl ::core::fmt::Debug for TypeAliases<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct TypeAliasesT {
pub i8_: i8,
pub u8_: u8,
Expand All @@ -397,7 +397,9 @@ pub struct TypeAliasesT {
pub u64_: u64,
pub f32_: f32,
pub f64_: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub v8: Option<alloc::vec::Vec<i8>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vf64: Option<alloc::vec::Vec<f64>>,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl<'a> Vec3 {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Vec3T {
pub x: f32,
pub y: f32,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl ::core::fmt::Debug for Monster<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct MonsterT {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl ::core::fmt::Debug for InParentNamespace<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct InParentNamespaceT {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,9 @@ impl ::core::fmt::Debug for TableB<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct TableBT {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub a: Option<alloc::boxed::Box<super::super::TableAT>>,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<'a> Unused {
}
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct UnusedT {
pub a: i32,
}
Expand Down
3 changes: 2 additions & 1 deletion tests/monster_test_serialize/table_a_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,9 @@ impl ::core::fmt::Debug for TableA<'_> {
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct TableAT {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub b: Option<alloc::boxed::Box<my_game::other_name_space::TableBT>>,
}

Expand Down
Loading
Loading