Skip to content

[Rust] Support struct type field with key attribute #8604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
14 changes: 13 additions & 1 deletion samples/rust_generated/my_game/sample/vec_3_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Vec3, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Vec3(pub [u8; 12]);
impl Default for Vec3 {
fn default() -> Self {
Expand All @@ -27,6 +27,18 @@ impl core::fmt::Debug for Vec3 {
.finish()
}
}
impl core::cmp::Ord for Vec3 {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.x().total_cmp(&other.x())
.then(self.y().total_cmp(&other.y()))
.then(self.z().total_cmp(&other.z()))
}
}
impl core::cmp::PartialOrd for Vec3 {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
Expand Down
26 changes: 25 additions & 1 deletion src/idl_gen_rust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2625,7 +2625,7 @@ class RustGenerator : public BaseGenerator {
// hold for PartialOrd/Ord.
code_ += "// struct {{STRUCT_TY}}, aligned to {{ALIGN}}";
code_ += "#[repr(transparent)]";
code_ += "#[derive(Clone, Copy, PartialEq)]";
code_ += "#[derive(Clone, Copy, PartialEq, Eq)]";
code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}(pub [u8; {{STRUCT_SIZE}}]);";
code_ += "impl Default for {{STRUCT_TY}} { ";
code_ += " fn default() -> Self { ";
Expand All @@ -2646,6 +2646,30 @@ class RustGenerator : public BaseGenerator {
code_ += " .finish()";
code_ += " }";
code_ += "}";

// Ord for structs.
code_ += "impl core::cmp::Ord for {{STRUCT_TY}} {";
code_ += " fn cmp(&self, other: &Self) -> core::cmp::Ordering {";
bool first = true;
ForAllStructFields(struct_def, [&](const FieldDef &field) {
// Floating point types don't impl Ord, use `total_cmp` instead.
const auto cmp_fn =
IsFloat(field.value.type.base_type) ? "total_cmp" : "cmp";
const auto cmp_expr = "self." + namer_.Field(field) + "()." + cmp_fn +
"(&other." + namer_.Field(field) + "())";
// If we are not the first comparison, we use `then` to chain.
code_ += first ? " " + cmp_expr : " .then(" + cmp_expr + ")";
first = false;
});
code_ += " }";
code_ += "}";

// PartialOrd for structs.
code_ += "impl core::cmp::PartialOrd for {{STRUCT_TY}} {";
code_ += " fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {";
code_ += " Some(self.cmp(other))";
code_ += " }";
code_ += "}";
code_ += "";

// Generate impls for SafeSliceAccess (because all structs are endian-safe),
Expand Down
17 changes: 16 additions & 1 deletion tests/arrays_test/my_game/example/array_struct_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct ArrayStruct, aligned to 8
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ArrayStruct(pub [u8; 160]);
impl Default for ArrayStruct {
fn default() -> Self {
Expand All @@ -30,6 +30,21 @@ impl core::fmt::Debug for ArrayStruct {
.finish()
}
}
impl core::cmp::Ord for ArrayStruct {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().total_cmp(&other.a())
.then(self.b().cmp(&other.b()))
.then(self.c().cmp(&other.c()))
.then(self.d().cmp(&other.d()))
.then(self.e().cmp(&other.e()))
.then(self.f().cmp(&other.f()))
}
}
impl core::cmp::PartialOrd for ArrayStruct {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for ArrayStruct {}
impl<'a> flatbuffers::Follow<'a> for ArrayStruct {
Expand Down
15 changes: 14 additions & 1 deletion tests/arrays_test/my_game/example/nested_struct_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct NestedStruct, aligned to 8
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct NestedStruct(pub [u8; 32]);
impl Default for NestedStruct {
fn default() -> Self {
Expand All @@ -28,6 +28,19 @@ impl core::fmt::Debug for NestedStruct {
.finish()
}
}
impl core::cmp::Ord for NestedStruct {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
.then(self.b().cmp(&other.b()))
.then(self.c().cmp(&other.c()))
.then(self.d().cmp(&other.d()))
}
}
impl core::cmp::PartialOrd for NestedStruct {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for NestedStruct {}
impl<'a> flatbuffers::Follow<'a> for NestedStruct {
Expand Down
12 changes: 11 additions & 1 deletion tests/include_test1/my_game/other_name_space/unused_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Unused, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Unused(pub [u8; 4]);
impl Default for Unused {
fn default() -> Self {
Expand All @@ -25,6 +25,16 @@ impl core::fmt::Debug for Unused {
.finish()
}
}
impl core::cmp::Ord for Unused {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
}
}
impl core::cmp::PartialOrd for Unused {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Unused {}
impl<'a> flatbuffers::Follow<'a> for Unused {
Expand Down
12 changes: 11 additions & 1 deletion tests/include_test2/my_game/other_name_space/unused_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Unused, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Unused(pub [u8; 4]);
impl Default for Unused {
fn default() -> Self {
Expand All @@ -25,6 +25,16 @@ impl core::fmt::Debug for Unused {
.finish()
}
}
impl core::cmp::Ord for Unused {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
}
}
impl core::cmp::PartialOrd for Unused {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Unused {}
impl<'a> flatbuffers::Follow<'a> for Unused {
Expand Down
13 changes: 12 additions & 1 deletion tests/monster_test/my_game/example/ability_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Ability, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Ability(pub [u8; 8]);
impl Default for Ability {
fn default() -> Self {
Expand All @@ -26,6 +26,17 @@ impl core::fmt::Debug for Ability {
.finish()
}
}
impl core::cmp::Ord for Ability {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.id().cmp(&other.id())
.then(self.distance().cmp(&other.distance()))
}
}
impl core::cmp::PartialOrd for Ability {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Ability {}
impl<'a> flatbuffers::Follow<'a> for Ability {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct StructOfStructs, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct StructOfStructs(pub [u8; 20]);
impl Default for StructOfStructs {
fn default() -> Self {
Expand All @@ -27,6 +27,18 @@ impl core::fmt::Debug for StructOfStructs {
.finish()
}
}
impl core::cmp::Ord for StructOfStructs {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
.then(self.b().cmp(&other.b()))
.then(self.c().cmp(&other.c()))
}
}
impl core::cmp::PartialOrd for StructOfStructs {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for StructOfStructs {}
impl<'a> flatbuffers::Follow<'a> for StructOfStructs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct StructOfStructsOfStructs, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct StructOfStructsOfStructs(pub [u8; 20]);
impl Default for StructOfStructsOfStructs {
fn default() -> Self {
Expand All @@ -25,6 +25,16 @@ impl core::fmt::Debug for StructOfStructsOfStructs {
.finish()
}
}
impl core::cmp::Ord for StructOfStructsOfStructs {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
}
}
impl core::cmp::PartialOrd for StructOfStructsOfStructs {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for StructOfStructsOfStructs {}
impl<'a> flatbuffers::Follow<'a> for StructOfStructsOfStructs {
Expand Down
13 changes: 12 additions & 1 deletion tests/monster_test/my_game/example/test_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Test, aligned to 2
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Test(pub [u8; 4]);
impl Default for Test {
fn default() -> Self {
Expand All @@ -26,6 +26,17 @@ impl core::fmt::Debug for Test {
.finish()
}
}
impl core::cmp::Ord for Test {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
.then(self.b().cmp(&other.b()))
}
}
impl core::cmp::PartialOrd for Test {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Test {}
impl<'a> flatbuffers::Follow<'a> for Test {
Expand Down
17 changes: 16 additions & 1 deletion tests/monster_test/my_game/example/vec_3_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Vec3, aligned to 8
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Vec3(pub [u8; 32]);
impl Default for Vec3 {
fn default() -> Self {
Expand All @@ -30,6 +30,21 @@ impl core::fmt::Debug for Vec3 {
.finish()
}
}
impl core::cmp::Ord for Vec3 {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.x().total_cmp(&other.x())
.then(self.y().total_cmp(&other.y()))
.then(self.z().total_cmp(&other.z()))
.then(self.test1().total_cmp(&other.test1()))
.then(self.test2().cmp(&other.test2()))
.then(self.test3().cmp(&other.test3()))
}
}
impl core::cmp::PartialOrd for Vec3 {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
Expand Down
12 changes: 11 additions & 1 deletion tests/monster_test/my_game/other_name_space/unused_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Unused, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Unused(pub [u8; 4]);
impl Default for Unused {
fn default() -> Self {
Expand All @@ -25,6 +25,16 @@ impl core::fmt::Debug for Unused {
.finish()
}
}
impl core::cmp::Ord for Unused {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
}
}
impl core::cmp::PartialOrd for Unused {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Unused {}
impl<'a> flatbuffers::Follow<'a> for Unused {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct Ability, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Ability(pub [u8; 8]);
impl Default for Ability {
fn default() -> Self {
Expand All @@ -28,6 +28,17 @@ impl core::fmt::Debug for Ability {
.finish()
}
}
impl core::cmp::Ord for Ability {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.id().cmp(&other.id())
.then(self.distance().cmp(&other.distance()))
}
}
impl core::cmp::PartialOrd for Ability {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for Ability {}
impl<'a> flatbuffers::Follow<'a> for Ability {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use self::flatbuffers::{EndianScalar, Follow};
use super::*;
// struct StructOfStructs, aligned to 4
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct StructOfStructs(pub [u8; 20]);
impl Default for StructOfStructs {
fn default() -> Self {
Expand All @@ -29,6 +29,18 @@ impl core::fmt::Debug for StructOfStructs {
.finish()
}
}
impl core::cmp::Ord for StructOfStructs {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.a().cmp(&other.a())
.then(self.b().cmp(&other.b()))
.then(self.c().cmp(&other.c()))
}
}
impl core::cmp::PartialOrd for StructOfStructs {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl flatbuffers::SimpleToVerifyInSlice for StructOfStructs {}
impl<'a> flatbuffers::Follow<'a> for StructOfStructs {
Expand Down
Loading