mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-03 04:21:13 +00:00
Rust Object API (#6070)
* inital commit of rust object api * Required fields support. * clang fallthrough * Fix unused variables * just don't fall through * remove comment * s/panic/unreachable * Tests for object API * Added defaults * deleted unintentionally added files and updated .bat file * fix bat file * clang format * Cargo clippy checks * remove commented out code * clippy allows * Remove matches! macro since we're not yet at Rust v1.42 * install clippy in RustTest.sh * move line Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
@@ -242,9 +242,7 @@ impl<'a> Builder {
|
||||
let address = self.buffer.len();
|
||||
for &b in xs.iter() {
|
||||
self.buffer.push(b as u8);
|
||||
for _ in 0..width as u8 {
|
||||
self.buffer.push(0); // Well this seems wasteful.
|
||||
}
|
||||
self.buffer.resize(self.buffer.len() + width as usize, 0);
|
||||
}
|
||||
self.values.push(Value::Reference {
|
||||
fxb_type: FlexBufferType::VectorBool,
|
||||
|
||||
@@ -129,9 +129,10 @@ impl Value {
|
||||
!self.is_inline()
|
||||
}
|
||||
pub fn is_key(&self) -> bool {
|
||||
match self {
|
||||
Value::Key(_) => true,
|
||||
_ => false,
|
||||
if let Value::Key(_) = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
pub fn is_typed_vector_or_map(&self) -> bool {
|
||||
|
||||
@@ -134,7 +134,7 @@ impl FlexBufferType {
|
||||
/// Returns true if called on a map, vector, typed vector, or fixed length typed vector.
|
||||
pub fn is_vector(self) -> bool {
|
||||
let d = self as u8;
|
||||
9 <= d && d < 25 || self == VectorBool
|
||||
(9..25).contains(&d) || self == VectorBool
|
||||
}
|
||||
/// True iff the binary format stores the length.
|
||||
/// This applies to Blob, String, Maps, and Vectors of variable length.
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
// Serializable structs are Pushable
|
||||
// Serde with maps - field names and type names.
|
||||
|
||||
// Until flat/flexbuffers is on Rust v1.42, we cannot use the previously unstable matches! macro.
|
||||
#![allow(clippy::unknown_clippy_lints)]
|
||||
#![allow(clippy::match_like_matches_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate byteorder;
|
||||
|
||||
@@ -38,7 +38,7 @@ pub const ENUM_VALUES_COLOR: [Color; 3] = [
|
||||
Color::Blue,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct Color(pub i8);
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -125,7 +125,7 @@ pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [
|
||||
Equipment::Weapon,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct Equipment(pub u8);
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -157,7 +157,6 @@ impl std::fmt::Debug for Equipment {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct EquipmentUnionTableOffset {}
|
||||
impl<'a> flatbuffers::Follow<'a> for Equipment {
|
||||
type Inner = Self;
|
||||
#[inline]
|
||||
@@ -199,9 +198,57 @@ impl<'a> flatbuffers::Verifiable for Equipment {
|
||||
}
|
||||
|
||||
impl flatbuffers::SimpleToVerifyInSlice for Equipment {}
|
||||
pub struct EquipmentUnionTableOffset {}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum EquipmentT {
|
||||
NONE,
|
||||
Weapon(Box<WeaponT>),
|
||||
}
|
||||
impl Default for EquipmentT {
|
||||
fn default() -> Self {
|
||||
Self::NONE
|
||||
}
|
||||
}
|
||||
impl EquipmentT {
|
||||
fn equipment_type(&self) -> Equipment {
|
||||
match self {
|
||||
Self::NONE => Equipment::NONE,
|
||||
Self::Weapon(_) => Equipment::Weapon,
|
||||
}
|
||||
}
|
||||
pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder) -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>> {
|
||||
match self {
|
||||
Self::NONE => None,
|
||||
Self::Weapon(v) => Some(v.pack(fbb).as_union_value()),
|
||||
}
|
||||
}
|
||||
/// If the union variant matches, return the owned WeaponT, setting the union to NONE.
|
||||
pub fn take_weapon(&mut self) -> Option<Box<WeaponT>> {
|
||||
if let Self::Weapon(_) = self {
|
||||
let v = std::mem::replace(self, Self::NONE);
|
||||
if let Self::Weapon(w) = v {
|
||||
Some(w)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
/// If the union variant matches, return a reference to the WeaponT.
|
||||
pub fn as_weapon(&self) -> Option<&WeaponT> {
|
||||
if let Self::Weapon(v) = self { Some(v.as_ref()) } else { None }
|
||||
}
|
||||
/// If the union variant matches, return a mutable reference to the WeaponT.
|
||||
pub fn as_weapon_mut(&mut self) -> Option<&mut WeaponT> {
|
||||
if let Self::Weapon(v) = self { Some(v.as_mut()) } else { None }
|
||||
}
|
||||
}
|
||||
// struct Vec3, aligned to 4
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Default)]
|
||||
pub struct Vec3(pub [u8; 12]);
|
||||
impl std::fmt::Debug for Vec3 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
@@ -343,6 +390,29 @@ impl Vec3 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> Vec3T {
|
||||
Vec3T {
|
||||
x: self.x(),
|
||||
y: self.y(),
|
||||
z: self.z(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct Vec3T {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
impl Vec3T {
|
||||
pub fn pack(&self) -> Vec3 {
|
||||
Vec3::new(
|
||||
self.x,
|
||||
self.y,
|
||||
self.z,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MonsterOffset {}
|
||||
@@ -363,9 +433,7 @@ impl<'a> flatbuffers::Follow<'a> for Monster<'a> {
|
||||
impl<'a> Monster<'a> {
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
Monster {
|
||||
_tab: table,
|
||||
}
|
||||
Monster { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -385,6 +453,46 @@ impl<'a> Monster<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> MonsterT {
|
||||
let pos = self.pos().map(|x| {
|
||||
x.unpack()
|
||||
});
|
||||
let mana = self.mana();
|
||||
let hp = self.hp();
|
||||
let name = self.name().map(|x| {
|
||||
x.to_string()
|
||||
});
|
||||
let inventory = self.inventory().map(|x| {
|
||||
x.to_vec()
|
||||
});
|
||||
let color = self.color();
|
||||
let weapons = self.weapons().map(|x| {
|
||||
x.iter().map(|t| t.unpack()).collect()
|
||||
});
|
||||
let equipped = match self.equipped_type() {
|
||||
Equipment::NONE => EquipmentT::NONE,
|
||||
Equipment::Weapon => EquipmentT::Weapon(Box::new(
|
||||
self.equipped_as_weapon()
|
||||
.expect("Invalid union table, expected `Equipment::Weapon`.")
|
||||
.unpack()
|
||||
)),
|
||||
_ => EquipmentT::NONE,
|
||||
};
|
||||
let path = self.path().map(|x| {
|
||||
x.iter().map(|t| t.unpack()).collect()
|
||||
});
|
||||
MonsterT {
|
||||
pos,
|
||||
mana,
|
||||
hp,
|
||||
name,
|
||||
inventory,
|
||||
color,
|
||||
weapons,
|
||||
equipped,
|
||||
path,
|
||||
}
|
||||
}
|
||||
pub const VT_POS: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_MANA: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_HP: flatbuffers::VOffsetT = 8;
|
||||
@@ -590,6 +698,57 @@ impl std::fmt::Debug for Monster<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct MonsterT {
|
||||
pub pos: Option<Vec3T>,
|
||||
pub mana: i16,
|
||||
pub hp: i16,
|
||||
pub name: Option<String>,
|
||||
pub inventory: Option<Vec<u8>>,
|
||||
pub color: Color,
|
||||
pub weapons: Option<Vec<WeaponT>>,
|
||||
pub equipped: EquipmentT,
|
||||
pub path: Option<Vec<Vec3T>>,
|
||||
}
|
||||
impl MonsterT {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<Monster<'b>> {
|
||||
let pos_tmp = self.pos.as_ref().map(|x| x.pack());
|
||||
let pos = pos_tmp.as_ref();
|
||||
let mana = self.mana;
|
||||
let hp = self.hp;
|
||||
let name = self.name.as_ref().map(|x|{
|
||||
_fbb.create_string(x)
|
||||
});
|
||||
let inventory = self.inventory.as_ref().map(|x|{
|
||||
_fbb.create_vector(x)
|
||||
});
|
||||
let color = self.color;
|
||||
let weapons = self.weapons.as_ref().map(|x|{
|
||||
let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
|
||||
});
|
||||
let equipped_type = self.equipped.equipment_type();
|
||||
let equipped = self.equipped.pack(_fbb);
|
||||
let path = self.path.as_ref().map(|x|{
|
||||
let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
|
||||
});
|
||||
Monster::create(_fbb, &MonsterArgs{
|
||||
pos,
|
||||
mana,
|
||||
hp,
|
||||
name,
|
||||
inventory,
|
||||
color,
|
||||
weapons,
|
||||
equipped_type,
|
||||
equipped,
|
||||
path,
|
||||
})
|
||||
}
|
||||
}
|
||||
pub enum WeaponOffset {}
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
||||
@@ -608,9 +767,7 @@ impl<'a> flatbuffers::Follow<'a> for Weapon<'a> {
|
||||
impl<'a> Weapon<'a> {
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
Weapon {
|
||||
_tab: table,
|
||||
}
|
||||
Weapon { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -622,6 +779,16 @@ impl<'a> Weapon<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> WeaponT {
|
||||
let name = self.name().map(|x| {
|
||||
x.to_string()
|
||||
});
|
||||
let damage = self.damage();
|
||||
WeaponT {
|
||||
name,
|
||||
damage,
|
||||
}
|
||||
}
|
||||
pub const VT_NAME: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_DAMAGE: flatbuffers::VOffsetT = 6;
|
||||
|
||||
@@ -697,6 +864,27 @@ impl std::fmt::Debug for Weapon<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct WeaponT {
|
||||
pub name: Option<String>,
|
||||
pub damage: i16,
|
||||
}
|
||||
impl WeaponT {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<Weapon<'b>> {
|
||||
let name = self.name.as_ref().map(|x|{
|
||||
_fbb.create_string(x)
|
||||
});
|
||||
let damage = self.damage;
|
||||
Weapon::create(_fbb, &WeaponArgs{
|
||||
name,
|
||||
damage,
|
||||
})
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
||||
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
|
||||
|
||||
@@ -19,6 +19,7 @@ extern crate flatbuffers;
|
||||
|
||||
// import the generated code
|
||||
#[path = "./monster_generated.rs"]
|
||||
#[allow(clippy::approx_constant)] // We use low precision PI as a default value.
|
||||
mod monster_generated;
|
||||
pub use monster_generated::my_game::sample::{Color, Equipment,
|
||||
Monster, MonsterArgs,
|
||||
@@ -27,7 +28,7 @@ pub use monster_generated::my_game::sample::{Color, Equipment,
|
||||
|
||||
|
||||
// Example how to use FlatBuffers to create and read binary buffers.
|
||||
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn main() {
|
||||
// Build up a serialized buffer algorithmically.
|
||||
// Initialize it with a capacity of 1024 bytes.
|
||||
|
||||
@@ -31,6 +31,7 @@ use flexbuffers::{BitWidth, Builder, Reader, ReaderError};
|
||||
// {"damage": 15, "name": "great axe"},
|
||||
// {"damage": 5, "name": "hammer"}]
|
||||
// }
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn main() {
|
||||
// Create a new Flexbuffer builder.
|
||||
let mut builder = Builder::default();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,33 +21,30 @@ if [[ "$1" == "mips-unknown-linux-gnu" ]]; then
|
||||
export CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER="qemu-mips -L /usr/mips-linux-gnu"
|
||||
fi
|
||||
|
||||
|
||||
function check_test_result() {
|
||||
if [[ $? == 0 ]]; then
|
||||
echo OK: $1 passed.
|
||||
else
|
||||
echo KO: $1 failed.
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
cd ./rust_usage_test
|
||||
cargo test $TARGET_FLAG -- --quiet
|
||||
TEST_RESULT=$?
|
||||
if [[ $TEST_RESULT == 0 ]]; then
|
||||
echo "OK: Rust tests passed."
|
||||
else
|
||||
echo "KO: Rust tests failed."
|
||||
exit 1
|
||||
fi
|
||||
check_test_result "Rust tests"
|
||||
|
||||
|
||||
cargo run $TARGET_FLAG --bin=flatbuffers_alloc_check
|
||||
TEST_RESULT=$?
|
||||
if [[ $TEST_RESULT == 0 ]]; then
|
||||
echo "OK: Rust heap alloc test passed."
|
||||
else
|
||||
echo "KO: Rust heap alloc test failed."
|
||||
exit 1
|
||||
fi
|
||||
check_test_result "Rust flatbuffers heap alloc test"
|
||||
|
||||
cargo run $TARGET_FLAG --bin=flexbuffers_alloc_check
|
||||
TEST_RESULT=$?
|
||||
if [[ $TEST_RESULT == 0 ]]; then
|
||||
echo "OK: Rust heap alloc test passed."
|
||||
else
|
||||
echo "KO: Rust heap alloc test failed."
|
||||
exit 1
|
||||
fi
|
||||
check_test_result "Rust flexbuffers heap alloc test"
|
||||
|
||||
rustup component add clippy
|
||||
cargo clippy $TARGET_FLAG
|
||||
check_test_result "No Cargo clippy lints test"
|
||||
|
||||
cargo bench $TARGET_FLAG
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes
|
||||
..\%buildtype%\flatc.exe --cpp %TEST_BASE_FLAGS% --cpp-ptr-type flatbuffers::unique_ptr native_type_test.fbs || goto FAIL
|
||||
|
||||
@rem Generate the optional scalar code for tests.
|
||||
..\%buildtype%\flatc.exe --java --kotlin --rust --lobster --ts optional_scalars.fbs || goto FAIL
|
||||
..\%buildtype%\flatc.exe --csharp --gen-object-api optional_scalars.fbs || goto FAIL
|
||||
..\%buildtype%\flatc.exe --java --kotlin --lobster --ts optional_scalars.fbs || goto FAIL
|
||||
..\%buildtype%\flatc.exe --csharp --rust --gen-object-api optional_scalars.fbs || goto FAIL
|
||||
..\%buildtype%\flatc.exe %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% --cpp optional_scalars.fbs || goto FAIL
|
||||
|
||||
@rem Generate the schema evolution tests
|
||||
|
||||
@@ -53,8 +53,8 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_JS_TS_FLAGS -o namespace
|
||||
../flatc --dart monster_extra.fbs
|
||||
|
||||
# Generate optional scalar code for tests.
|
||||
../flatc --java --kotlin --rust --lobster --ts optional_scalars.fbs
|
||||
../flatc --csharp --gen-object-api optional_scalars.fbs
|
||||
../flatc --java --kotlin --lobster --ts optional_scalars.fbs
|
||||
../flatc --csharp --rust --gen-object-api optional_scalars.fbs
|
||||
../flatc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS --cpp optional_scalars.fbs
|
||||
|
||||
# Generate the schema evolution tests
|
||||
|
||||
@@ -28,9 +28,7 @@ impl<'a> flatbuffers::Follow<'a> for TableA<'a> {
|
||||
impl<'a> TableA<'a> {
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
TableA {
|
||||
_tab: table,
|
||||
}
|
||||
TableA { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
|
||||
@@ -39,7 +39,7 @@ pub const ENUM_VALUES_FROM_INCLUDE: [FromInclude; 1] = [
|
||||
FromInclude::IncludeVal,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct FromInclude(pub i64);
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -111,7 +111,7 @@ impl<'a> flatbuffers::Verifiable for FromInclude {
|
||||
impl flatbuffers::SimpleToVerifyInSlice for FromInclude {}
|
||||
// struct Unused, aligned to 4
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Default)]
|
||||
pub struct Unused(pub [u8; 4]);
|
||||
impl std::fmt::Debug for Unused {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
@@ -221,9 +221,7 @@ impl<'a> flatbuffers::Follow<'a> for TableB<'a> {
|
||||
impl<'a> TableB<'a> {
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
TableB {
|
||||
_tab: table,
|
||||
}
|
||||
TableB { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@ pub const ENUM_VALUES_ENUM_IN_NESTED_NS: [EnumInNestedNS; 3] = [
|
||||
EnumInNestedNS::C,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct EnumInNestedNS(pub i8);
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -116,7 +116,7 @@ impl<'a> flatbuffers::Verifiable for EnumInNestedNS {
|
||||
impl flatbuffers::SimpleToVerifyInSlice for EnumInNestedNS {}
|
||||
// struct StructInNestedNS, aligned to 4
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Default)]
|
||||
pub struct StructInNestedNS(pub [u8; 8]);
|
||||
impl std::fmt::Debug for StructInNestedNS {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
@@ -236,6 +236,26 @@ impl StructInNestedNS {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> StructInNestedNST {
|
||||
StructInNestedNST {
|
||||
a: self.a(),
|
||||
b: self.b(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct StructInNestedNST {
|
||||
pub a: i32,
|
||||
pub b: i32,
|
||||
}
|
||||
impl StructInNestedNST {
|
||||
pub fn pack(&self) -> StructInNestedNS {
|
||||
StructInNestedNS::new(
|
||||
self.a,
|
||||
self.b,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TableInNestedNSOffset {}
|
||||
@@ -260,9 +280,7 @@ impl<'a> TableInNestedNS<'a> {
|
||||
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
TableInNestedNS {
|
||||
_tab: table,
|
||||
}
|
||||
TableInNestedNS { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -273,6 +291,12 @@ impl<'a> TableInNestedNS<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> TableInNestedNST {
|
||||
let foo = self.foo();
|
||||
TableInNestedNST {
|
||||
foo,
|
||||
}
|
||||
}
|
||||
pub const VT_FOO: flatbuffers::VOffsetT = 4;
|
||||
|
||||
#[inline]
|
||||
@@ -335,6 +359,22 @@ impl std::fmt::Debug for TableInNestedNS<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct TableInNestedNST {
|
||||
pub foo: i32,
|
||||
}
|
||||
impl TableInNestedNST {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<TableInNestedNS<'b>> {
|
||||
let foo = self.foo;
|
||||
TableInNestedNS::create(_fbb, &TableInNestedNSArgs{
|
||||
foo,
|
||||
})
|
||||
}
|
||||
}
|
||||
} // pub mod NamespaceB
|
||||
} // pub mod NamespaceA
|
||||
|
||||
|
||||
@@ -42,9 +42,7 @@ impl<'a> TableInFirstNS<'a> {
|
||||
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
TableInFirstNS {
|
||||
_tab: table,
|
||||
}
|
||||
TableInFirstNS { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -57,6 +55,20 @@ impl<'a> TableInFirstNS<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> TableInFirstNST {
|
||||
let foo_table = self.foo_table().map(|x| {
|
||||
Box::new(x.unpack())
|
||||
});
|
||||
let foo_enum = self.foo_enum();
|
||||
let foo_struct = self.foo_struct().map(|x| {
|
||||
x.unpack()
|
||||
});
|
||||
TableInFirstNST {
|
||||
foo_table,
|
||||
foo_enum,
|
||||
foo_struct,
|
||||
}
|
||||
}
|
||||
pub const VT_FOO_TABLE: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_FOO_ENUM: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_FOO_STRUCT: flatbuffers::VOffsetT = 8;
|
||||
@@ -145,6 +157,31 @@ impl std::fmt::Debug for TableInFirstNS<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct TableInFirstNST {
|
||||
pub foo_table: Option<Box<namespace_b::TableInNestedNST>>,
|
||||
pub foo_enum: namespace_b::EnumInNestedNS,
|
||||
pub foo_struct: Option<namespace_b::StructInNestedNST>,
|
||||
}
|
||||
impl TableInFirstNST {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<TableInFirstNS<'b>> {
|
||||
let foo_table = self.foo_table.as_ref().map(|x|{
|
||||
x.pack(_fbb)
|
||||
});
|
||||
let foo_enum = self.foo_enum;
|
||||
let foo_struct_tmp = self.foo_struct.as_ref().map(|x| x.pack());
|
||||
let foo_struct = foo_struct_tmp.as_ref();
|
||||
TableInFirstNS::create(_fbb, &TableInFirstNSArgs{
|
||||
foo_table,
|
||||
foo_enum,
|
||||
foo_struct,
|
||||
})
|
||||
}
|
||||
}
|
||||
pub enum SecondTableInAOffset {}
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
||||
@@ -167,9 +204,7 @@ impl<'a> SecondTableInA<'a> {
|
||||
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
SecondTableInA {
|
||||
_tab: table,
|
||||
}
|
||||
SecondTableInA { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -180,6 +215,14 @@ impl<'a> SecondTableInA<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> SecondTableInAT {
|
||||
let refer_to_c = self.refer_to_c().map(|x| {
|
||||
Box::new(x.unpack())
|
||||
});
|
||||
SecondTableInAT {
|
||||
refer_to_c,
|
||||
}
|
||||
}
|
||||
pub const VT_REFER_TO_C: flatbuffers::VOffsetT = 4;
|
||||
|
||||
#[inline]
|
||||
@@ -242,6 +285,24 @@ impl std::fmt::Debug for SecondTableInA<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct SecondTableInAT {
|
||||
pub refer_to_c: Option<Box<super::namespace_c::TableInCT>>,
|
||||
}
|
||||
impl SecondTableInAT {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<SecondTableInA<'b>> {
|
||||
let refer_to_c = self.refer_to_c.as_ref().map(|x|{
|
||||
x.pack(_fbb)
|
||||
});
|
||||
SecondTableInA::create(_fbb, &SecondTableInAArgs{
|
||||
refer_to_c,
|
||||
})
|
||||
}
|
||||
}
|
||||
} // pub mod NamespaceA
|
||||
|
||||
#[allow(unused_imports, dead_code)]
|
||||
@@ -276,9 +337,7 @@ impl<'a> TableInC<'a> {
|
||||
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
TableInC {
|
||||
_tab: table,
|
||||
}
|
||||
TableInC { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -290,6 +349,18 @@ impl<'a> TableInC<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> TableInCT {
|
||||
let refer_to_a1 = self.refer_to_a1().map(|x| {
|
||||
Box::new(x.unpack())
|
||||
});
|
||||
let refer_to_a2 = self.refer_to_a2().map(|x| {
|
||||
Box::new(x.unpack())
|
||||
});
|
||||
TableInCT {
|
||||
refer_to_a1,
|
||||
refer_to_a2,
|
||||
}
|
||||
}
|
||||
pub const VT_REFER_TO_A1: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_REFER_TO_A2: flatbuffers::VOffsetT = 6;
|
||||
|
||||
@@ -365,5 +436,28 @@ impl std::fmt::Debug for TableInC<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct TableInCT {
|
||||
pub refer_to_a1: Option<Box<super::namespace_a::TableInFirstNST>>,
|
||||
pub refer_to_a2: Option<Box<super::namespace_a::SecondTableInAT>>,
|
||||
}
|
||||
impl TableInCT {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<TableInC<'b>> {
|
||||
let refer_to_a1 = self.refer_to_a1.as_ref().map(|x|{
|
||||
x.pack(_fbb)
|
||||
});
|
||||
let refer_to_a2 = self.refer_to_a2.as_ref().map(|x|{
|
||||
x.pack(_fbb)
|
||||
});
|
||||
TableInC::create(_fbb, &TableInCArgs{
|
||||
refer_to_a1,
|
||||
refer_to_a2,
|
||||
})
|
||||
}
|
||||
}
|
||||
} // pub mod NamespaceC
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ pub const ENUM_VALUES_OPTIONAL_BYTE: [OptionalByte; 3] = [
|
||||
OptionalByte::Two,
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct OptionalByte(pub i8);
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -124,9 +124,7 @@ impl<'a> flatbuffers::Follow<'a> for ScalarStuff<'a> {
|
||||
impl<'a> ScalarStuff<'a> {
|
||||
#[inline]
|
||||
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
ScalarStuff {
|
||||
_tab: table,
|
||||
}
|
||||
ScalarStuff { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
@@ -172,6 +170,82 @@ impl<'a> ScalarStuff<'a> {
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
pub fn unpack(&self) -> ScalarStuffT {
|
||||
let just_i8 = self.just_i8();
|
||||
let maybe_i8 = self.maybe_i8();
|
||||
let default_i8 = self.default_i8();
|
||||
let just_u8 = self.just_u8();
|
||||
let maybe_u8 = self.maybe_u8();
|
||||
let default_u8 = self.default_u8();
|
||||
let just_i16 = self.just_i16();
|
||||
let maybe_i16 = self.maybe_i16();
|
||||
let default_i16 = self.default_i16();
|
||||
let just_u16 = self.just_u16();
|
||||
let maybe_u16 = self.maybe_u16();
|
||||
let default_u16 = self.default_u16();
|
||||
let just_i32 = self.just_i32();
|
||||
let maybe_i32 = self.maybe_i32();
|
||||
let default_i32 = self.default_i32();
|
||||
let just_u32 = self.just_u32();
|
||||
let maybe_u32 = self.maybe_u32();
|
||||
let default_u32 = self.default_u32();
|
||||
let just_i64 = self.just_i64();
|
||||
let maybe_i64 = self.maybe_i64();
|
||||
let default_i64 = self.default_i64();
|
||||
let just_u64 = self.just_u64();
|
||||
let maybe_u64 = self.maybe_u64();
|
||||
let default_u64 = self.default_u64();
|
||||
let just_f32 = self.just_f32();
|
||||
let maybe_f32 = self.maybe_f32();
|
||||
let default_f32 = self.default_f32();
|
||||
let just_f64 = self.just_f64();
|
||||
let maybe_f64 = self.maybe_f64();
|
||||
let default_f64 = self.default_f64();
|
||||
let just_bool = self.just_bool();
|
||||
let maybe_bool = self.maybe_bool();
|
||||
let default_bool = self.default_bool();
|
||||
let just_enum = self.just_enum();
|
||||
let maybe_enum = self.maybe_enum();
|
||||
let default_enum = self.default_enum();
|
||||
ScalarStuffT {
|
||||
just_i8,
|
||||
maybe_i8,
|
||||
default_i8,
|
||||
just_u8,
|
||||
maybe_u8,
|
||||
default_u8,
|
||||
just_i16,
|
||||
maybe_i16,
|
||||
default_i16,
|
||||
just_u16,
|
||||
maybe_u16,
|
||||
default_u16,
|
||||
just_i32,
|
||||
maybe_i32,
|
||||
default_i32,
|
||||
just_u32,
|
||||
maybe_u32,
|
||||
default_u32,
|
||||
just_i64,
|
||||
maybe_i64,
|
||||
default_i64,
|
||||
just_u64,
|
||||
maybe_u64,
|
||||
default_u64,
|
||||
just_f32,
|
||||
maybe_f32,
|
||||
default_f32,
|
||||
just_f64,
|
||||
maybe_f64,
|
||||
default_f64,
|
||||
just_bool,
|
||||
maybe_bool,
|
||||
default_bool,
|
||||
just_enum,
|
||||
maybe_enum,
|
||||
default_enum,
|
||||
}
|
||||
}
|
||||
pub const VT_JUST_I8: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_MAYBE_I8: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_DEFAULT_I8: flatbuffers::VOffsetT = 8;
|
||||
@@ -689,6 +763,127 @@ impl std::fmt::Debug for ScalarStuff<'_> {
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct ScalarStuffT {
|
||||
pub just_i8: i8,
|
||||
pub maybe_i8: Option<i8>,
|
||||
pub default_i8: i8,
|
||||
pub just_u8: u8,
|
||||
pub maybe_u8: Option<u8>,
|
||||
pub default_u8: u8,
|
||||
pub just_i16: i16,
|
||||
pub maybe_i16: Option<i16>,
|
||||
pub default_i16: i16,
|
||||
pub just_u16: u16,
|
||||
pub maybe_u16: Option<u16>,
|
||||
pub default_u16: u16,
|
||||
pub just_i32: i32,
|
||||
pub maybe_i32: Option<i32>,
|
||||
pub default_i32: i32,
|
||||
pub just_u32: u32,
|
||||
pub maybe_u32: Option<u32>,
|
||||
pub default_u32: u32,
|
||||
pub just_i64: i64,
|
||||
pub maybe_i64: Option<i64>,
|
||||
pub default_i64: i64,
|
||||
pub just_u64: u64,
|
||||
pub maybe_u64: Option<u64>,
|
||||
pub default_u64: u64,
|
||||
pub just_f32: f32,
|
||||
pub maybe_f32: Option<f32>,
|
||||
pub default_f32: f32,
|
||||
pub just_f64: f64,
|
||||
pub maybe_f64: Option<f64>,
|
||||
pub default_f64: f64,
|
||||
pub just_bool: bool,
|
||||
pub maybe_bool: Option<bool>,
|
||||
pub default_bool: bool,
|
||||
pub just_enum: OptionalByte,
|
||||
pub maybe_enum: Option<OptionalByte>,
|
||||
pub default_enum: OptionalByte,
|
||||
}
|
||||
impl ScalarStuffT {
|
||||
pub fn pack<'b>(
|
||||
&self,
|
||||
_fbb: &mut flatbuffers::FlatBufferBuilder<'b>
|
||||
) -> flatbuffers::WIPOffset<ScalarStuff<'b>> {
|
||||
let just_i8 = self.just_i8;
|
||||
let maybe_i8 = self.maybe_i8;
|
||||
let default_i8 = self.default_i8;
|
||||
let just_u8 = self.just_u8;
|
||||
let maybe_u8 = self.maybe_u8;
|
||||
let default_u8 = self.default_u8;
|
||||
let just_i16 = self.just_i16;
|
||||
let maybe_i16 = self.maybe_i16;
|
||||
let default_i16 = self.default_i16;
|
||||
let just_u16 = self.just_u16;
|
||||
let maybe_u16 = self.maybe_u16;
|
||||
let default_u16 = self.default_u16;
|
||||
let just_i32 = self.just_i32;
|
||||
let maybe_i32 = self.maybe_i32;
|
||||
let default_i32 = self.default_i32;
|
||||
let just_u32 = self.just_u32;
|
||||
let maybe_u32 = self.maybe_u32;
|
||||
let default_u32 = self.default_u32;
|
||||
let just_i64 = self.just_i64;
|
||||
let maybe_i64 = self.maybe_i64;
|
||||
let default_i64 = self.default_i64;
|
||||
let just_u64 = self.just_u64;
|
||||
let maybe_u64 = self.maybe_u64;
|
||||
let default_u64 = self.default_u64;
|
||||
let just_f32 = self.just_f32;
|
||||
let maybe_f32 = self.maybe_f32;
|
||||
let default_f32 = self.default_f32;
|
||||
let just_f64 = self.just_f64;
|
||||
let maybe_f64 = self.maybe_f64;
|
||||
let default_f64 = self.default_f64;
|
||||
let just_bool = self.just_bool;
|
||||
let maybe_bool = self.maybe_bool;
|
||||
let default_bool = self.default_bool;
|
||||
let just_enum = self.just_enum;
|
||||
let maybe_enum = self.maybe_enum;
|
||||
let default_enum = self.default_enum;
|
||||
ScalarStuff::create(_fbb, &ScalarStuffArgs{
|
||||
just_i8,
|
||||
maybe_i8,
|
||||
default_i8,
|
||||
just_u8,
|
||||
maybe_u8,
|
||||
default_u8,
|
||||
just_i16,
|
||||
maybe_i16,
|
||||
default_i16,
|
||||
just_u16,
|
||||
maybe_u16,
|
||||
default_u16,
|
||||
just_i32,
|
||||
maybe_i32,
|
||||
default_i32,
|
||||
just_u32,
|
||||
maybe_u32,
|
||||
default_u32,
|
||||
just_i64,
|
||||
maybe_i64,
|
||||
default_i64,
|
||||
just_u64,
|
||||
maybe_u64,
|
||||
default_u64,
|
||||
just_f32,
|
||||
maybe_f32,
|
||||
default_f32,
|
||||
just_f64,
|
||||
maybe_f64,
|
||||
default_f64,
|
||||
just_bool,
|
||||
maybe_bool,
|
||||
default_bool,
|
||||
just_enum,
|
||||
maybe_enum,
|
||||
default_enum,
|
||||
})
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")]
|
||||
pub fn get_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> {
|
||||
|
||||
@@ -36,7 +36,7 @@ pub mod include_test1_generated;
|
||||
#[path = "../../include_test/sub/include_test2_generated.rs"]
|
||||
pub mod include_test2_generated;
|
||||
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[allow(dead_code, unused_imports, clippy::approx_constant)]
|
||||
#[path = "../../monster_test_generated.rs"]
|
||||
mod monster_test_generated;
|
||||
pub use monster_test_generated::my_game;
|
||||
|
||||
@@ -8,7 +8,7 @@ pub mod include_test1_generated;
|
||||
#[path = "../../include_test/sub/include_test2_generated.rs"]
|
||||
pub mod include_test2_generated;
|
||||
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[allow(dead_code, unused_imports, clippy::approx_constant)]
|
||||
#[path = "../../monster_test_generated.rs"]
|
||||
mod monster_test_generated;
|
||||
pub use monster_test_generated::my_game;
|
||||
|
||||
@@ -227,6 +227,50 @@ fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_require
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_object_api_reads_correctly() -> Result<(), &'static str>{
|
||||
let mut fbb = flatbuffers::FlatBufferBuilder::new();
|
||||
create_serialized_example_with_library_code(&mut fbb);
|
||||
|
||||
let m = my_game::example::root_as_monster(fbb.finished_data()).unwrap().unpack();
|
||||
|
||||
check_eq!(m.hp, 80)?;
|
||||
check_eq!(m.mana, 150)?;
|
||||
check_eq!(m.name, "MyMonster")?;
|
||||
|
||||
let pos = m.pos.as_ref().unwrap();
|
||||
check_eq!(pos.x, 1.0f32)?;
|
||||
check_eq!(pos.y, 2.0f32)?;
|
||||
check_eq!(pos.z, 3.0f32)?;
|
||||
check_eq!(pos.test1, 3.0f64)?;
|
||||
check_eq!(pos.test2, my_game::example::Color::Green)?;
|
||||
|
||||
let pos_test3 = &pos.test3;
|
||||
check_eq!(pos_test3.a, 5i16)?;
|
||||
check_eq!(pos_test3.b, 6i8)?;
|
||||
|
||||
let monster2 = m.test.as_monster().unwrap();
|
||||
check_eq!(monster2.name, "Fred")?;
|
||||
|
||||
let inv = m.inventory.as_ref().unwrap();
|
||||
check_eq!(inv.len(), 5)?;
|
||||
check_eq!(inv.iter().sum::<u8>(), 10u8)?;
|
||||
check_eq!(inv.iter().rev().sum::<u8>(), 10u8)?;
|
||||
|
||||
let test4 = m.test4.as_ref().unwrap();
|
||||
check_eq!(test4.len(), 2)?;
|
||||
check_eq!(test4[0].a as i32 + test4[0].b as i32 +
|
||||
test4[1].a as i32 + test4[1].b as i32, 100)?;
|
||||
|
||||
let testarrayofstring = m.testarrayofstring.as_ref().unwrap();
|
||||
check_eq!(testarrayofstring.len(), 2)?;
|
||||
check_eq!(testarrayofstring[0], "test1")?;
|
||||
check_eq!(testarrayofstring[1], "test2")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Disabled due to Windows CI limitations.
|
||||
// #[test]
|
||||
// fn builder_initializes_with_maximum_buffer_size() {
|
||||
|
||||
@@ -37,6 +37,16 @@ macro_rules! make_test {
|
||||
assert_eq!(s.$just(), $zero);
|
||||
assert_eq!(s.$default(), $fortytwo);
|
||||
assert_eq!(s.$maybe(), None);
|
||||
|
||||
// Same for object API
|
||||
let s = flatbuffers::root::<ScalarStuff>(builder.finished_data()).unwrap().unpack();
|
||||
assert_eq!(s.$just, $five);
|
||||
assert_eq!(s.$default, $five);
|
||||
assert_eq!(s.$maybe, Some($five));
|
||||
let s = flatbuffers::root::<ScalarStuff>(&[0; 8]).unwrap().unpack();
|
||||
assert_eq!(s.$just, $zero);
|
||||
assert_eq!(s.$default, $fortytwo);
|
||||
assert_eq!(s.$maybe, None);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user