Rust Object API (#6070)
authorCasper <casperneo@uchicago.edu>
Fri, 22 Jan 2021 18:07:32 +0000 (13:07 -0500)
committerGitHub <noreply@github.com>
Fri, 22 Jan 2021 18:07:32 +0000 (13:07 -0500)
* 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>
21 files changed:
rust/flexbuffers/src/builder/mod.rs
rust/flexbuffers/src/builder/value.rs
rust/flexbuffers/src/flexbuffer_type.rs
rust/flexbuffers/src/lib.rs
samples/monster_generated.rs
samples/sample_binary.rs
samples/sample_flexbuffers.rs
src/idl_gen_rust.cpp
tests/RustTest.sh
tests/generate_code.bat
tests/generate_code.sh
tests/include_test/include_test1_generated.rs
tests/include_test/sub/include_test2_generated.rs
tests/monster_test_generated.rs
tests/namespace_test/namespace_test1_generated.rs
tests/namespace_test/namespace_test2_generated.rs
tests/optional_scalars_generated.rs
tests/rust_usage_test/bin/flatbuffers_alloc_check.rs
tests/rust_usage_test/bin/monster_example.rs
tests/rust_usage_test/tests/integration_test.rs
tests/rust_usage_test/tests/optional_scalars_test.rs

index e71acd0..46ee79e 100644 (file)
@@ -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,
index f230c34..88ff7b9 100644 (file)
@@ -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 {
index 5b57de8..eda5195 100644 (file)
@@ -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.
index 20983b7..5e98702 100644 (file)
 //             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;
index eb4f6c3..62a9c2d 100644 (file)
@@ -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> {
index 649babf..1b08f20 100644 (file)
@@ -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.
index efe02c3..677bcac 100644 (file)
@@ -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();
index 2f6f0b7..5fc3090 100644 (file)
@@ -179,7 +179,7 @@ bool IsBitFlagsEnum(const EnumDef &enum_def) {
   return enum_def.attributes.Lookup("bit_flags") != nullptr;
 }
 bool IsBitFlagsEnum(const FieldDef &field) {
-  EnumDefed = field.value.type.enum_def;
+  EnumDef *ed = field.value.type.enum_def;
   return ed && IsBitFlagsEnum(*ed);
 }
 
@@ -192,6 +192,7 @@ class RustGenerator : public BaseGenerator {
       : BaseGenerator(parser, path, file_name, "", "::", "rs"),
         cur_name_space_(nullptr) {
     const char *keywords[] = {
+      // clang-format off
       // list taken from:
       // https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
       //
@@ -227,7 +228,7 @@ class RustGenerator : public BaseGenerator {
 
       // used by Enum constants
       "ENUM_MAX", "ENUM_MIN", "ENUM_VALUES",
-    };
+    };  // clang-format on
     for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
   }
 
@@ -257,8 +258,7 @@ class RustGenerator : public BaseGenerator {
       for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
            ++it) {
         const auto &enum_def = **it;
-        if (enum_def.defined_namespace != ns) { continue; }
-        if (!enum_def.generated) {
+        if (enum_def.defined_namespace == ns && !enum_def.generated) {
           SetNameSpace(enum_def.defined_namespace);
           GenEnum(enum_def);
         }
@@ -268,8 +268,8 @@ class RustGenerator : public BaseGenerator {
       for (auto it = parser_.structs_.vec.begin();
            it != parser_.structs_.vec.end(); ++it) {
         const auto &struct_def = **it;
-        if (struct_def.defined_namespace != ns) { continue; }
-        if (struct_def.fixed && !struct_def.generated) {
+        if (struct_def.defined_namespace == ns && struct_def.fixed &&
+            !struct_def.generated) {
           SetNameSpace(struct_def.defined_namespace);
           GenStruct(struct_def);
         }
@@ -279,10 +279,13 @@ class RustGenerator : public BaseGenerator {
       for (auto it = parser_.structs_.vec.begin();
            it != parser_.structs_.vec.end(); ++it) {
         const auto &struct_def = **it;
-        if (struct_def.defined_namespace != ns) { continue; }
-        if (!struct_def.fixed && !struct_def.generated) {
+        if (struct_def.defined_namespace == ns && !struct_def.fixed &&
+            !struct_def.generated) {
           SetNameSpace(struct_def.defined_namespace);
           GenTable(struct_def);
+          if (parser_.opts.generate_object_based_api) {
+            GenTableObject(struct_def);
+          }
         }
       }
 
@@ -347,6 +350,13 @@ class RustGenerator : public BaseGenerator {
   std::string EscapeKeyword(const std::string &name) const {
     return keywords_.find(name) == keywords_.end() ? name : name + "_";
   }
+  std::string NamespacedNativeName(const Definition &def) {
+    return WrapInNameSpace(def.defined_namespace, NativeName(def));
+  }
+
+  std::string NativeName(const Definition &def) {
+    return parser_.opts.object_prefix + Name(def) + parser_.opts.object_suffix;
+  }
 
   std::string Name(const Definition &def) const {
     return EscapeKeyword(def.name);
@@ -499,13 +509,13 @@ class RustGenerator : public BaseGenerator {
   }
 
   std::string GetEnumValue(const EnumDef &enum_def,
-                            const EnumVal &enum_val) const {
+                           const EnumVal &enum_val) const {
     return Name(enum_def) + "::" + Name(enum_val);
   }
 
   // 1 suffix since old C++ can't figure out the overload.
   void ForAllEnumValues1(const EnumDef &enum_def,
-                        std::function<void(const EnumVal&)> cb) {
+                         std::function<void(const EnumVal &)> cb) {
     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
       const auto &ev = **it;
       code_.SetValue("VARIANT", Name(ev));
@@ -514,11 +524,11 @@ class RustGenerator : public BaseGenerator {
     }
   }
   void ForAllEnumValues(const EnumDef &enum_def, std::function<void()> cb) {
-      std::function<void(const EnumVal&)> wrapped = [&](const EnumVal& unused) {
-        (void) unused;
-        cb();
-      };
-      ForAllEnumValues1(enum_def, wrapped);
+    std::function<void(const EnumVal &)> wrapped = [&](const EnumVal &unused) {
+      (void)unused;
+      cb();
+    };
+    ForAllEnumValues1(enum_def, wrapped);
   }
   // Generate an enum declaration,
   // an enum string lookup table,
@@ -536,16 +546,17 @@ class RustGenerator : public BaseGenerator {
     code_.SetValue("ENUM_MAX_BASE_VALUE", enum_def.ToString(*maxv));
 
     if (IsBitFlagsEnum(enum_def)) {
-      // Defer to the convenient and canonical bitflags crate. We declare it in a
-      // module to #allow camel case constants in a smaller scope. This matches
-      // Flatbuffers c-modeled enums where variants are associated constants but
-      // in camel case.
+      // Defer to the convenient and canonical bitflags crate. We declare it in
+      // a module to #allow camel case constants in a smaller scope. This
+      // matches Flatbuffers c-modeled enums where variants are associated
+      // constants but in camel case.
       code_ += "#[allow(non_upper_case_globals)]";
       code_ += "mod bitflags_{{ENUM_NAME_SNAKE}} {";
       code_ += "  flatbuffers::bitflags::bitflags! {";
       GenComment(enum_def.doc_comment, "    ");
+      code_ += "    #[derive(Default)]";
       code_ += "    pub struct {{ENUM_NAME}}: {{BASE_TYPE}} {";
-      ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
+      ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
         this->GenComment(ev.doc_comment, "      ");
         code_ += "      const {{VARIANT}} = {{VALUE}};";
       });
@@ -564,30 +575,36 @@ class RustGenerator : public BaseGenerator {
           "#[deprecated(since = \"2.0.0\", note = \"Use associated constants"
           " instead. This will no longer be generated in 2021.\")]";
       code_ += deprecation_warning;
-      code_ += "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
-               " = {{ENUM_MIN_BASE_VALUE}};";
+      code_ +=
+          "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+          " = {{ENUM_MIN_BASE_VALUE}};";
       code_ += deprecation_warning;
-      code_ += "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
-               " = {{ENUM_MAX_BASE_VALUE}};";
+      code_ +=
+          "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+          " = {{ENUM_MAX_BASE_VALUE}};";
       auto num_fields = NumToString(enum_def.size());
       code_ += deprecation_warning;
       code_ += "#[allow(non_camel_case_types)]";
       code_ += "pub const ENUM_VALUES_{{ENUM_NAME_CAPS}}: [{{ENUM_NAME}}; " +
                num_fields + "] = [";
-      ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
+      ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
         code_ += "  " + GetEnumValue(enum_def, ev) + ",";
       });
       code_ += "];";
       code_ += "";
 
       GenComment(enum_def.doc_comment);
+      // Derive Default to be 0. flatc enforces this when the enum
+      // is put into a struct, though this isn't documented behavior, it is
+      // needed to derive defaults in struct objects.
       code_ +=
-          "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]";
+          "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, "
+          "Default)]";
       code_ += "#[repr(transparent)]";
       code_ += "pub struct {{ENUM_NAME}}(pub {{BASE_TYPE}});";
       code_ += "#[allow(non_upper_case_globals)]";
       code_ += "impl {{ENUM_NAME}} {";
-      ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
+      ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
         this->GenComment(ev.doc_comment, "  ");
         code_ += "  pub const {{VARIANT}}: Self = Self({{VALUE}});";
       });
@@ -596,14 +613,12 @@ class RustGenerator : public BaseGenerator {
       code_ += "  pub const ENUM_MIN: {{BASE_TYPE}} = {{ENUM_MIN_BASE_VALUE}};";
       code_ += "  pub const ENUM_MAX: {{BASE_TYPE}} = {{ENUM_MAX_BASE_VALUE}};";
       code_ += "  pub const ENUM_VALUES: &'static [Self] = &[";
-      ForAllEnumValues(enum_def, [&](){
-        code_ += "    Self::{{VARIANT}},";
-      });
+      ForAllEnumValues(enum_def, [&]() { code_ += "    Self::{{VARIANT}},"; });
       code_ += "  ];";
       code_ += "  /// Returns the variant's name or \"\" if unknown.";
       code_ += "  pub fn variant_name(self) -> Option<&'static str> {";
       code_ += "    match self {";
-      ForAllEnumValues(enum_def, [&](){
+      ForAllEnumValues(enum_def, [&]() {
         code_ += "      Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
       });
       code_ += "      _ => None,";
@@ -613,8 +628,9 @@ class RustGenerator : public BaseGenerator {
 
       // Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
       code_ += "impl std::fmt::Debug for {{ENUM_NAME}} {";
-      code_ += "  fn fmt(&self, f: &mut std::fmt::Formatter) ->"
-               " std::fmt::Result {";
+      code_ +=
+          "  fn fmt(&self, f: &mut std::fmt::Formatter) ->"
+          " std::fmt::Result {";
       code_ += "    if let Some(name) = self.variant_name() {";
       code_ += "      f.write_str(name)";
       code_ += "    } else {";
@@ -623,13 +639,6 @@ class RustGenerator : public BaseGenerator {
       code_ += "  }";
       code_ += "}";
 
-      if (enum_def.is_union) {
-        // Generate tyoesafe offset(s) for unions
-        code_.SetValue("NAME", Name(enum_def));
-        code_.SetValue("UNION_OFFSET_NAME", Name(enum_def) + "UnionTableOffset");
-        code_ += "pub struct {{UNION_OFFSET_NAME}} {}";
-      }
-
       code_.SetValue("FROM_BASE", "Self(b)");
       code_.SetValue("INTO_BASE", "self.0");
     }
@@ -639,8 +648,9 @@ class RustGenerator : public BaseGenerator {
     code_ += "  type Inner = Self;";
     code_ += "  #[inline]";
     code_ += "  fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
-    code_ += "    let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf,"
-             " loc);";
+    code_ +=
+        "    let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf,"
+        " loc);";
     code_ += "    {{FROM_BASE}}";
     code_ += "  }";
     code_ += "}";
@@ -649,8 +659,9 @@ class RustGenerator : public BaseGenerator {
     code_ += "    type Output = {{ENUM_NAME}};";
     code_ += "    #[inline]";
     code_ += "    fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
-    code_ += "        flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
-             "(dst, {{INTO_BASE}});";
+    code_ +=
+        "        flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
+        "(dst, {{INTO_BASE}});";
     code_ += "    }";
     code_ += "}";
     code_ += "";
@@ -667,6 +678,7 @@ class RustGenerator : public BaseGenerator {
     code_ += "  }";
     code_ += "}";
     code_ += "";
+
     // Generate verifier - deferring to the base type.
     code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_NAME}} {";
     code_ += "  #[inline]";
@@ -680,6 +692,126 @@ class RustGenerator : public BaseGenerator {
     code_ += "";
     // Enums are basically integers.
     code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_NAME}} {}";
+
+    if (enum_def.is_union) {
+      // Generate tyoesafe offset(s) for unions
+      code_.SetValue("NAME", Name(enum_def));
+      code_.SetValue("UNION_OFFSET_NAME", Name(enum_def) + "UnionTableOffset");
+      code_ += "pub struct {{UNION_OFFSET_NAME}} {}";
+      code_ += "";
+      if (parser_.opts.generate_object_based_api) { GenUnionObject(enum_def); }
+    }
+  }
+
+  // CASPER: dedup Object versions from non object versions.
+  void ForAllUnionObjectVariantsBesidesNone(const EnumDef &enum_def,
+                                            std::function<void()> cb) {
+    for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+      auto &enum_val = **it;
+      if (enum_val.union_type.base_type == BASE_TYPE_NONE) continue;
+      code_.SetValue("VARIANT_NAME", Name(enum_val));
+      code_.SetValue("NATIVE_VARIANT", MakeCamel(Name(enum_val)));
+      code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(enum_val)));
+      code_.SetValue("U_ELEMENT_TABLE_TYPE",
+                     NamespacedNativeName(*enum_val.union_type.struct_def));
+      cb();
+    }
+  }
+  void GenUnionObject(const EnumDef &enum_def) {
+    code_.SetValue("ENUM_NAME", Name(enum_def));
+    code_.SetValue("ENUM_NAME_SNAKE", MakeSnakeCase(Name(enum_def)));
+    code_.SetValue("NATIVE_NAME", NativeName(enum_def));
+
+    // Generate native union.
+    code_ += "#[non_exhaustive]";
+    code_ += "#[derive(Debug, Clone, PartialEq)]";
+    code_ += "pub enum {{NATIVE_NAME}} {";
+    code_ += "  NONE,";
+    ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+      code_ += "  {{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
+    });
+    code_ += "}";
+    // Generate Default (NONE).
+    code_ += "impl Default for {{NATIVE_NAME}} {";
+    code_ += "  fn default() -> Self {";
+    code_ += "    Self::NONE";
+    code_ += "  }";
+    code_ += "}";
+
+    // Generate native union methods.
+    code_ += "impl {{NATIVE_NAME}} {";
+
+    // Get flatbuffers union key.
+    // CASPER: add docstrings?
+    code_ += "  fn {{ENUM_NAME_SNAKE}}_type(&self) -> {{ENUM_NAME}} {";
+    code_ += "    match self {";
+    code_ += "      Self::NONE => {{ENUM_NAME}}::NONE,";
+    ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+      code_ +=
+          "      Self::{{NATIVE_VARIANT}}(_) => {{ENUM_NAME}}::"
+          "{{VARIANT_NAME}},";
+    });
+    code_ += "    }";
+    code_ += "  }";
+    // Pack flatbuffers union value
+    code_ +=
+        "  pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder)"
+        " -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>"
+        " {";
+    code_ += "    match self {";
+    code_ += "      Self::NONE => None,";
+    ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+      code_ +=
+          "      Self::{{NATIVE_VARIANT}}(v) => "
+          "Some(v.pack(fbb).as_union_value()),";
+    });
+    code_ += "    }";
+    code_ += "  }";
+
+    // Generate some accessors;
+    ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+      // Move accessor.
+      code_ +=
+          "  /// If the union variant matches, return the owned "
+          "{{U_ELEMENT_TABLE_TYPE}}, setting the union to NONE.";
+      code_ +=
+          "  pub fn take_{{U_ELEMENT_NAME}}(&mut self) -> "
+          "Option<Box<{{U_ELEMENT_TABLE_TYPE}}>> {";
+      code_ += "    if let Self::{{NATIVE_VARIANT}}(_) = self {";
+      code_ += "      let v = std::mem::replace(self, Self::NONE);";
+      code_ += "      if let Self::{{NATIVE_VARIANT}}(w) = v {";
+      code_ += "        Some(w)";
+      code_ += "      } else {";
+      code_ += "        unreachable!()";
+      code_ += "      }";
+      code_ += "    } else {";
+      code_ += "      None";
+      code_ += "    }";
+      code_ += "  }";
+      // Immutable reference accessor.
+      code_ +=
+          "  /// If the union variant matches, return a reference to the "
+          "{{U_ELEMENT_TABLE_TYPE}}.";
+      code_ +=
+          "  pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
+          "Option<&{{U_ELEMENT_TABLE_TYPE}}> {";
+      code_ +=
+          "    if let Self::{{NATIVE_VARIANT}}(v) = self "
+          "{ Some(v.as_ref()) } else { None }";
+      code_ += "  }";
+      // Mutable reference accessor.
+      code_ +=
+          "  /// If the union variant matches, return a mutable reference"
+          " to the {{U_ELEMENT_TABLE_TYPE}}.";
+      code_ +=
+          "  pub fn as_{{U_ELEMENT_NAME}}_mut(&mut self) -> "
+          "Option<&mut {{U_ELEMENT_TABLE_TYPE}}> {";
+      code_ +=
+          "    if let Self::{{NATIVE_VARIANT}}(v) = self "
+          "{ Some(v.as_mut()) } else { None }";
+      code_ += "  }";
+    });
+    code_ += "}";  // End union methods impl.
   }
 
   std::string GetFieldOffsetName(const FieldDef &field) {
@@ -698,11 +830,9 @@ class RustGenerator : public BaseGenerator {
       }
       case ftUnionKey:
       case ftEnumKey: {
-        if (field.optional) {
-            return "None";
-        }
+        if (field.optional) { return "None"; }
         auto ev = field.value.type.enum_def->FindByValue(field.value.constant);
-        assert(ev);
+        if (!ev) return "Default::default()";  // Bitflags enum.
         return WrapInNameSpace(field.value.type.enum_def->defined_namespace,
                                GetEnumValue(*field.value.type.enum_def, *ev));
       }
@@ -797,6 +927,77 @@ class RustGenerator : public BaseGenerator {
     return "INVALID_CODE_GENERATION";  // for return analysis
   }
 
+  std::string ObjectFieldType(const FieldDef &field, bool in_a_table) {
+    const Type &type = field.value.type;
+    std::string ty;
+    switch (GetFullType(type)) {
+      case ftInteger:
+      case ftBool:
+      case ftFloat: {
+        ty = GetTypeBasic(type);
+        break;
+      }
+      case ftString: {
+        ty = "String";
+        break;
+      }
+      case ftStruct: {
+        ty = NamespacedNativeName(*type.struct_def);
+        break;
+      }
+      case ftTable: {
+        // Since Tables can contain themselves, Box is required to avoid
+        // infinite types.
+        ty = "Box<" + NamespacedNativeName(*type.struct_def) + ">";
+        break;
+      }
+      case ftUnionKey: {
+        // There is no native "UnionKey", natively, unions are rust enums with
+        // newtype-struct-variants.
+        return "INVALID_CODE_GENERATION";
+      }
+      case ftUnionValue: {
+        ty = NamespacedNativeName(*type.enum_def);
+        break;
+      }
+      case ftEnumKey: {
+        ty = WrapInNameSpace(*type.enum_def);
+        break;
+      }
+      // Vectors are in tables and are optional
+      case ftVectorOfEnumKey: {
+        ty = "Vec<" + WrapInNameSpace(*type.VectorType().enum_def) + ">";
+        break;
+      }
+      case ftVectorOfInteger:
+      case ftVectorOfBool:
+      case ftVectorOfFloat: {
+        ty = "Vec<" + GetTypeBasic(type.VectorType()) + ">";
+        break;
+      }
+      case ftVectorOfString: {
+        ty = "Vec<String>";
+        break;
+      }
+      case ftVectorOfTable:
+      case ftVectorOfStruct: {
+        ty = NamespacedNativeName(*type.VectorType().struct_def);
+        ty = "Vec<" + ty + ">";
+        break;
+      }
+      case ftVectorOfUnionValue: {
+        FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
+        return "INVALID_CODE_GENERATION";  // OH NO!
+      }
+    }
+    if (in_a_table && !IsUnion(type) &&
+        (IsScalar(type.base_type) ? field.optional : !field.required)) {
+      return "Option<" + ty + ">";
+    } else {
+      return ty;
+    }
+  }
+
   std::string TableBuilderArgsAddFuncType(const FieldDef &field,
                                           const std::string &lifetime) {
     const Type &type = field.value.type;
@@ -834,7 +1035,8 @@ class RustGenerator : public BaseGenerator {
                ", flatbuffers::ForwardsUOffset<flatbuffers::Table<" + lifetime +
                ">>>";
       }
-      case ftEnumKey: {
+      case ftEnumKey:
+      case ftUnionKey: {
         const auto typname = WrapInNameSpace(*type.enum_def);
         return typname;
       }
@@ -854,10 +1056,6 @@ class RustGenerator : public BaseGenerator {
       case ftString: {
         return "flatbuffers::WIPOffset<&" + lifetime + " str>";
       }
-      case ftUnionKey: {
-        const auto typname = WrapInNameSpace(*type.enum_def);
-        return typname;
-      }
       case ftUnionValue: {
         return "flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>";
       }
@@ -881,9 +1079,9 @@ class RustGenerator : public BaseGenerator {
       case ftEnumKey:
       case ftUnionKey: {
         const auto underlying_typname = GetTypeBasic(type);
-        return (field.optional ?
-                   "self.fbb_.push_slot_always::<" :
-                   "self.fbb_.push_slot::<") + underlying_typname + ">";
+        return (field.optional ? "self.fbb_.push_slot_always::<"
+                               : "self.fbb_.push_slot::<") +
+               underlying_typname + ">";
       }
 
       case ftStruct: {
@@ -1013,7 +1211,7 @@ class RustGenerator : public BaseGenerator {
       }
       case ftUnionKey:
       case ftEnumKey: {
-        return  WrapInNameSpace(*type.enum_def);
+        return WrapInNameSpace(*type.enum_def);
       }
       case ftTable: {
         const auto typname = WrapInNameSpace(*type.struct_def);
@@ -1034,7 +1232,6 @@ class RustGenerator : public BaseGenerator {
       case ftVectorOfEnumKey: {
         const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
         return WrapForwardsUOffset(WrapVector(typname));
-
       }
       case ftVectorOfStruct: {
         const auto typname = WrapInNameSpace(*type.struct_def);
@@ -1045,8 +1242,8 @@ class RustGenerator : public BaseGenerator {
         return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(typname)));
       }
       case ftVectorOfString: {
-        return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(
-          "&" + lifetime + " str")));
+        return WrapForwardsUOffset(
+            WrapVector(WrapForwardsUOffset("&" + lifetime + " str")));
       }
       case ftVectorOfUnionValue: {
         FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
@@ -1061,21 +1258,25 @@ class RustGenerator : public BaseGenerator {
     const std::string vt_offset = GetFieldOffsetName(field);
     const std::string typname = FollowType(field.value.type, lifetime);
     // Default-y fields (scalars so far) are neither optional nor required.
-    const std::string default_value = !(field.optional || field.required) ?
-      "Some(" + GetDefaultScalarValue(field) + ")" : "None";
+    const std::string default_value =
+        !(field.optional || field.required)
+            ? "Some(" + GetDefaultScalarValue(field) + ")"
+            : "None";
     const std::string unwrap = field.optional ? "" : ".unwrap()";
 
     const auto t = GetFullType(field.value.type);
 
     // TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
-    const std::string safe_slice = (
-      t == ftVectorOfStruct ||
-      ((t == ftVectorOfBool || t == ftVectorOfFloat || t == ftVectorOfInteger)
-      && IsOneByte(field.value.type.VectorType().base_type))
-    ) ? ".map(|v| v.safe_slice())" : "";
-
-    return "self._tab.get::<" + typname + ">({{STRUCT_NAME}}::" +
-          vt_offset + ", " + default_value + ")" + safe_slice + unwrap;
+    const std::string safe_slice =
+        (t == ftVectorOfStruct ||
+         ((t == ftVectorOfBool || t == ftVectorOfFloat ||
+           t == ftVectorOfInteger) &&
+          IsOneByte(field.value.type.VectorType().base_type)))
+            ? ".map(|v| v.safe_slice())"
+            : "";
+
+    return "self._tab.get::<" + typname + ">({{STRUCT_NAME}}::" + vt_offset +
+           ", " + default_value + ")" + safe_slice + unwrap;
   }
 
   bool TableFieldReturnsOption(const FieldDef &field) {
@@ -1101,19 +1302,18 @@ class RustGenerator : public BaseGenerator {
   }
 
   void ForAllUnionVariantsBesidesNone(
-    const EnumDef &def,
-    std::function<void(const EnumVal &ev)> cb
-  ) {
+      const EnumDef &def, std::function<void(const EnumVal &ev)> cb) {
     FLATBUFFERS_ASSERT(def.is_union);
 
     for (auto it = def.Vals().begin(); it != def.Vals().end(); ++it) {
-      const EnumVal & ev = **it;
+      const EnumVal &ev = **it;
       // TODO(cneo): Can variants be deprecated, should we skip them?
       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
       code_.SetValue(
           "U_ELEMENT_ENUM_TYPE",
           WrapInNameSpace(def.defined_namespace, GetEnumValue(def, ev)));
-      code_.SetValue("U_ELEMENT_TABLE_TYPE",
+      code_.SetValue(
+          "U_ELEMENT_TABLE_TYPE",
           WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
                           ev.union_type.struct_def->name));
       code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(ev)));
@@ -1121,12 +1321,12 @@ class RustGenerator : public BaseGenerator {
     }
   }
 
-  void ForAllTableFields(
-    const StructDef &struct_def,
-    std::function<void(const FieldDef&)> cb, bool reversed=false) {
+  void ForAllTableFields(const StructDef &struct_def,
+                         std::function<void(const FieldDef &)> cb,
+                         bool reversed = false) {
     // TODO(cneo): Remove `reversed` overload. It's only here to minimize the
     // diff when refactoring to the `ForAllX` helper functions.
-    auto go = [&](const FieldDeffield) {
+    auto go = [&](const FieldDef &field) {
       if (field.deprecated) return;
       code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
       code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
@@ -1178,9 +1378,7 @@ class RustGenerator : public BaseGenerator {
     code_ +=
         "    pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
         "Self {";
-    code_ += "        {{STRUCT_NAME}} {";
-    code_ += "            _tab: table,";
-    code_ += "        }";
+    code_ += "        {{STRUCT_NAME}} { _tab: table }";
     code_ += "    }";
 
     // Generate a convenient create* function that uses the above builder
@@ -1200,27 +1398,140 @@ class RustGenerator : public BaseGenerator {
     code_ += "      let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);";
     for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
          size; size /= 2) {
-      ForAllTableFields(struct_def, [&](const FieldDef &field) {
-        if (struct_def.sortbysize && size != SizeOf(field.value.type.base_type))
-          return;
-        if (TableFieldReturnsOption(field)) {
-          code_ +=
-              "      if let Some(x) = args.{{FIELD_NAME}} "
-              "{ builder.add_{{FIELD_NAME}}(x); }";
-        } else {
-          code_ += "      builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
-        }
-      }, /*reverse=*/true);
+      ForAllTableFields(
+          struct_def,
+          [&](const FieldDef &field) {
+            if (struct_def.sortbysize &&
+                size != SizeOf(field.value.type.base_type))
+              return;
+            if (TableFieldReturnsOption(field)) {
+              code_ +=
+                  "      if let Some(x) = args.{{FIELD_NAME}} "
+                  "{ builder.add_{{FIELD_NAME}}(x); }";
+            } else {
+              code_ += "      builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
+            }
+          },
+          /*reverse=*/true);
     }
     code_ += "      builder.finish()";
     code_ += "    }";
     code_ += "";
+    // Generate Object API Packer function.
+    if (parser_.opts.generate_object_based_api) {
+      // TODO(cneo): Replace more for loops with ForAllX stuff.
+      // TODO(cneo): Manage indentation with IncrementIdentLevel?
+      code_.SetValue("OBJECT_NAME", NativeName(struct_def));
+      code_ += "    pub fn unpack(&self) -> {{OBJECT_NAME}} {";
+      ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
+        const Type &type = field.value.type;
+        switch (GetFullType(type)) {
+          case ftInteger:
+          case ftBool:
+          case ftFloat:
+          case ftEnumKey: {
+            code_ += "      let {{FIELD_NAME}} = self.{{FIELD_NAME}}();";
+            return;
+          }
+          case ftUnionKey: return;
+          case ftUnionValue: {
+            const auto &enum_def = *type.enum_def;
+            code_.SetValue("ENUM_NAME", Name(enum_def));
+            code_.SetValue("NATIVE_ENUM_NAME", NativeName(enum_def));
+            code_ +=
+                "      let {{FIELD_NAME}} = match "
+                "self.{{FIELD_NAME}}_type() {";
+            code_ +=
+                "        {{ENUM_NAME}}::NONE =>"
+                " {{NATIVE_ENUM_NAME}}::NONE,";
+            ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+              code_ +=
+                  "        {{ENUM_NAME}}::{{VARIANT_NAME}} => "
+                  "{{NATIVE_ENUM_NAME}}::{{NATIVE_VARIANT}}(Box::new(";
+              code_ +=
+                  "          self.{{FIELD_NAME}}_as_"
+                  "{{U_ELEMENT_NAME}}()";
+              code_ +=
+                  "              .expect(\"Invalid union table, "
+                  "expected `{{ENUM_NAME}}::{{VARIANT_NAME}}`.\")";
+              code_ += "              .unpack()";
+              code_ += "        )),";
+            });
+            // Maybe we shouldn't throw away unknown discriminants?
+            code_ += "        _ => {{NATIVE_ENUM_NAME}}::NONE,";
+            code_ += "      };";
+            return;
+          }
+          // The rest of the types need special handling based on if the field
+          // is optional or not.
+          case ftString: {
+            code_.SetValue("EXPR", "x.to_string()");
+            break;
+          }
+          case ftStruct: {
+            code_.SetValue("EXPR", "x.unpack()");
+            break;
+          }
+          case ftTable: {
+            code_.SetValue("EXPR", "Box::new(x.unpack())");
+            break;
+          }
+          case ftVectorOfInteger:
+          case ftVectorOfBool: {
+            if (IsOneByte(type.VectorType().base_type)) {
+              // 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector
+              // and thus needs to be cloned out of the slice.
+              code_.SetValue("EXPR", "x.to_vec()");
+              break;
+            }
+            code_.SetValue("EXPR", "x.into_iter().collect()");
+            break;
+          }
+          case ftVectorOfFloat:
+          case ftVectorOfEnumKey: {
+            code_.SetValue("EXPR", "x.into_iter().collect()");
+            break;
+          }
+          case ftVectorOfString: {
+            code_.SetValue("EXPR", "x.iter().map(|s| s.to_string()).collect()");
+            break;
+          }
+          case ftVectorOfStruct:
+          case ftVectorOfTable: {
+            code_.SetValue("EXPR", "x.iter().map(|t| t.unpack()).collect()");
+            break;
+          }
+          case ftVectorOfUnionValue: {
+            FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
+            return;
+          }
+        }
+        if (field.optional) {
+          code_ += "      let {{FIELD_NAME}} = self.{{FIELD_NAME}}().map(|x| {";
+          code_ += "        {{EXPR}}";
+          code_ += "      });";
+        } else {
+          code_ += "      let {{FIELD_NAME}} = {";
+          code_ += "        let x = self.{{FIELD_NAME}}();";
+          code_ += "        {{EXPR}}";
+          code_ += "      };";
+        }
+      });
+      code_ += "      {{OBJECT_NAME}} {";
+      ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
+        if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
+        code_ += "        {{FIELD_NAME}},";
+      });
+      code_ += "      }";
+      code_ += "    }";
+    }
 
     // Generate field id constants.
-    ForAllTableFields(struct_def, [&](const FieldDef &unused){
-      (void) unused;
-      code_ += "    pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
-               "{{OFFSET_VALUE}};";
+    ForAllTableFields(struct_def, [&](const FieldDef &unused) {
+      (void)unused;
+      code_ +=
+          "    pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
+          "{{OFFSET_VALUE}};";
     });
     if (struct_def.fields.vec.size() > 0) code_ += "";
 
@@ -1261,20 +1572,21 @@ class RustGenerator : public BaseGenerator {
         FLATBUFFERS_ASSERT(nested_root);  // Guaranteed to exist by parser.
 
         code_.SetValue("NESTED", WrapInNameSpace(*nested_root));
-        code_ +=
-            "  pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> \\";
+        code_ += "  pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> \\";
         if (field.required) {
           code_ += "{{NESTED}}<'a> {";
           code_ += "    let data = self.{{FIELD_NAME}}();";
           code_ += "    use flatbuffers::Follow;";
-          code_ += "    <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
-                   "::follow(data, 0)";
+          code_ +=
+              "    <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+              "::follow(data, 0)";
         } else {
           code_ += "Option<{{NESTED}}<'a>> {";
           code_ += "    self.{{FIELD_NAME}}().map(|data| {";
           code_ += "      use flatbuffers::Follow;";
-          code_ += "      <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
-                   "::follow(data, 0)";
+          code_ +=
+              "      <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+              "::follow(data, 0)";
           code_ += "    })";
         }
         code_ += "  }";
@@ -1286,45 +1598,45 @@ class RustGenerator : public BaseGenerator {
       if (field.value.type.base_type != BASE_TYPE_UNION) return;
       code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
       ForAllUnionVariantsBesidesNone(
-        *field.value.type.enum_def, [&](const EnumVal &unused){
-        (void) unused;
-        code_ += "  #[inline]";
-        code_ += "  #[allow(non_snake_case)]";
-        code_ +=
-            "  pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> "
-            "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {";
-        // If the user defined schemas name a field that clashes with a
-        // language reserved word, flatc will try to escape the field name by
-        // appending an underscore. This works well for most cases, except
-        // one. When generating union accessors (and referring to them
-        // internally within the code generated here), an extra underscore
-        // will be appended to the name, causing build failures.
-        //
-        // This only happens when unions have members that overlap with
-        // language reserved words.
-        //
-        // To avoid this problem the type field name is used unescaped here:
-        code_ +=
-            "    if self.{{FIELD_TYPE_FIELD_NAME}}_type() == "
-            "{{U_ELEMENT_ENUM_TYPE}} {";
-
-        // The following logic is not tested in the integration test,
-        // as of April 10, 2020
-        if (field.required) {
-          code_ += "      let u = self.{{FIELD_NAME}}();";
-          code_ += "      Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
-        } else {
-          code_ +=
-              "      self.{{FIELD_NAME}}().map("
-              "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
-        }
-        code_ += "    } else {";
-        code_ += "      None";
-        code_ += "    }";
-        code_ += "  }";
-        code_ += "";
-
-      });
+          *field.value.type.enum_def, [&](const EnumVal &unused) {
+            (void)unused;
+            code_ += "  #[inline]";
+            code_ += "  #[allow(non_snake_case)]";
+            code_ +=
+                "  pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> "
+                "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {";
+            // If the user defined schemas name a field that clashes with a
+            // language reserved word, flatc will try to escape the field name
+            // by appending an underscore. This works well for most cases,
+            // except one. When generating union accessors (and referring to
+            // them internally within the code generated here), an extra
+            // underscore will be appended to the name, causing build failures.
+            //
+            // This only happens when unions have members that overlap with
+            // language reserved words.
+            //
+            // To avoid this problem the type field name is used unescaped here:
+            code_ +=
+                "    if self.{{FIELD_TYPE_FIELD_NAME}}_type() == "
+                "{{U_ELEMENT_ENUM_TYPE}} {";
+
+            // The following logic is not tested in the integration test,
+            // as of April 10, 2020
+            if (field.required) {
+              code_ += "      let u = self.{{FIELD_NAME}}();";
+              code_ +=
+                  "      Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
+            } else {
+              code_ +=
+                  "      self.{{FIELD_NAME}}().map("
+                  "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
+            }
+            code_ += "    } else {";
+            code_ += "      None";
+            code_ += "    }";
+            code_ += "  }";
+            code_ += "";
+          });
     });
     code_ += "}";  // End of table impl.
     code_ += "";
@@ -1346,23 +1658,26 @@ class RustGenerator : public BaseGenerator {
       if (GetFullType(field.value.type) != ftUnionValue) {
         // All types besides unions.
         code_.SetValue("TY", FollowType(field.value.type, "'_"));
-        code_ += "\n     .visit_field::<{{TY}}>(&\"{{FIELD_NAME}}\", "
-                 "Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
-          return;
+        code_ +=
+            "\n     .visit_field::<{{TY}}>(&\"{{FIELD_NAME}}\", "
+            "Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
+        return;
       }
       // Unions.
       EnumDef &union_def = *field.value.type.enum_def;
       code_.SetValue("UNION_TYPE", Name(union_def));
-      code_ += "\n     .visit_union::<{{UNION_TYPE}}, _>("
-               "&\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, "
-               "&\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
-               "|key, v, pos| {";
+      code_ +=
+          "\n     .visit_union::<{{UNION_TYPE}}, _>("
+          "&\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, "
+          "&\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
+          "|key, v, pos| {";
       code_ += "        match key {";
       ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
-        (void) unused;
-        code_ += "          {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
-                 "<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
-                 "\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
+        (void)unused;
+        code_ +=
+            "          {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
+            "<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
+            "\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
       });
       code_ += "          _ => Ok(()),";
       code_ += "        }";
@@ -1424,8 +1739,9 @@ class RustGenerator : public BaseGenerator {
       code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
       code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
       code_ += "  #[inline]";
-      code_ += "  pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
-               "{{FIELD_TYPE}}) {";
+      code_ +=
+          "  pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
+          "{{FIELD_TYPE}}) {";
       if (is_scalar && !field.optional) {
         code_ +=
             "    {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
@@ -1468,30 +1784,35 @@ class RustGenerator : public BaseGenerator {
     code_ += "";
 
     code_ += "impl std::fmt::Debug for {{STRUCT_NAME}}<'_> {";
-    code_ += "  fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
-             ") -> std::fmt::Result {";
+    code_ +=
+        "  fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
+        ") -> std::fmt::Result {";
     code_ += "    let mut ds = f.debug_struct(\"{{STRUCT_NAME}}\");";
     ForAllTableFields(struct_def, [&](const FieldDef &field) {
       if (GetFullType(field.value.type) == ftUnionValue) {
         // Generate a match statement to handle unions properly.
         code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
         code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
-        code_.SetValue("UNION_ERR", "&\"InvalidFlatbuffer: Union discriminant"
-                                    " does not match value.\"");
+        code_.SetValue("UNION_ERR",
+                       "&\"InvalidFlatbuffer: Union discriminant"
+                       " does not match value.\"");
 
         code_ += "      match self.{{FIELD_NAME}}_type() {";
-        ForAllUnionVariantsBesidesNone(*field.value.type.enum_def,
-                                       [&](const EnumVal &unused){
-          (void) unused;
-          code_ += "        {{U_ELEMENT_ENUM_TYPE}} => {";
-          code_ += "          if let Some(x) = self.{{FIELD_TYPE_FIELD_NAME}}_as_"
-                   "{{U_ELEMENT_NAME}}() {";
-          code_ += "            ds.field(\"{{FIELD_NAME}}\", &x)";
-          code_ += "          } else {";
-          code_ += "            ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
-          code_ += "          }";
-          code_ += "        },";
-        });
+        ForAllUnionVariantsBesidesNone(
+            *field.value.type.enum_def, [&](const EnumVal &unused) {
+              (void)unused;
+              code_ += "        {{U_ELEMENT_ENUM_TYPE}} => {";
+              code_ +=
+                  "          if let Some(x) = "
+                  "self.{{FIELD_TYPE_FIELD_NAME}}_as_"
+                  "{{U_ELEMENT_NAME}}() {";
+              code_ += "            ds.field(\"{{FIELD_NAME}}\", &x)";
+              code_ += "          } else {";
+              code_ +=
+                  "            ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
+              code_ += "          }";
+              code_ += "        },";
+            });
         code_ += "        _ => { ";
         code_ += "          let x: Option<()> = None;";
         code_ += "          ds.field(\"{{FIELD_NAME}}\", &x)";
@@ -1507,6 +1828,150 @@ class RustGenerator : public BaseGenerator {
     code_ += "}";
   }
 
+  void GenTableObject(const StructDef &table) {
+    code_.SetValue("OBJECT_NAME", NativeName(table));
+    code_.SetValue("STRUCT_NAME", Name(table));
+
+    // Generate the native object.
+    code_ += "#[non_exhaustive]";
+    code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
+    code_ += "pub struct {{OBJECT_NAME}} {";
+    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;
+      code_ += "  pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
+    });
+    code_ += "}";
+
+    // TODO(cneo): Generate defaults for Native tables. However, since structs
+    // may be required, they, and therefore enums need defaults.
+
+    // Generate pack function.
+    code_ += "impl {{OBJECT_NAME}} {";
+    code_ += "  pub fn pack<'b>(";
+    code_ += "    &self,";
+    code_ += "    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>";
+    code_ += "  ) -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'b>> {";
+    // First we generate variables for each field and then later assemble them
+    // using "StructArgs" to more easily manage ownership of the builder.
+    ForAllObjectTableFields(table, [&](const FieldDef &field) {
+      const Type &type = field.value.type;
+      switch (GetFullType(type)) {
+        case ftInteger:
+        case ftBool:
+        case ftFloat:
+        case ftEnumKey: {
+          code_ += "    let {{FIELD_NAME}} = self.{{FIELD_NAME}};";
+          return;
+        }
+        case ftUnionKey: return;  // Generate union type with union value.
+        case ftUnionValue: {
+          code_.SetValue("SNAKE_CASE_ENUM_NAME",
+                         MakeSnakeCase(Name(*field.value.type.enum_def)));
+          code_ +=
+              "    let {{FIELD_NAME}}_type = "
+              "self.{{FIELD_NAME}}.{{SNAKE_CASE_ENUM_NAME}}_type();";
+          code_ += "    let {{FIELD_NAME}} = self.{{FIELD_NAME}}.pack(_fbb);";
+          return;
+        }
+        // The rest of the types require special casing around optionalness
+        // due to "required" annotation.
+        case ftString: {
+          MapNativeTableField(field, "_fbb.create_string(x)");
+          return;
+        }
+        case ftStruct: {
+          // Hold the struct in a variable so we can reference it.
+          if (field.required) {
+            code_ +=
+                "    let {{FIELD_NAME}}_tmp = "
+                "Some(self.{{FIELD_NAME}}.pack());";
+          } else {
+            code_ +=
+                "    let {{FIELD_NAME}}_tmp = self.{{FIELD_NAME}}"
+                ".as_ref().map(|x| x.pack());";
+          }
+          code_ += "    let {{FIELD_NAME}} = {{FIELD_NAME}}_tmp.as_ref();";
+
+          return;
+        }
+        case ftTable: {
+          MapNativeTableField(field, "x.pack(_fbb)");
+          return;
+        }
+        case ftVectorOfEnumKey:
+        case ftVectorOfInteger:
+        case ftVectorOfBool:
+        case ftVectorOfFloat: {
+          MapNativeTableField(field, "_fbb.create_vector(x)");
+          return;
+        }
+        case ftVectorOfStruct: {
+          MapNativeTableField(
+              field,
+              "let w: Vec<_> = x.iter().map(|t| t.pack()).collect();"
+              "_fbb.create_vector(&w)");
+          return;
+        }
+        case ftVectorOfString: {
+          // TODO(cneo): create_vector* should be more generic to avoid
+          // allocations.
+
+          MapNativeTableField(
+              field,
+              "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
+              "_fbb.create_vector_of_strings(&w)");
+          return;
+        }
+        case ftVectorOfTable: {
+          MapNativeTableField(
+              field,
+              "let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();"
+              "_fbb.create_vector(&w)");
+          return;
+        }
+        case ftVectorOfUnionValue: {
+          FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
+          return;
+        }
+      }
+    });
+    code_ += "    {{STRUCT_NAME}}::create(_fbb, &{{STRUCT_NAME}}Args{";
+    ForAllObjectTableFields(table, [&](const FieldDef &field) {
+      (void)field;  // Unused.
+      code_ += "      {{FIELD_NAME}},";
+    });
+    code_ += "    })";
+    code_ += "  }";
+    code_ += "}";
+  }
+  void ForAllObjectTableFields(const StructDef &table,
+                               std::function<void(const FieldDef &)> cb) {
+    const std::vector<FieldDef *> &v = table.fields.vec;
+    for (auto it = v.begin(); it != v.end(); it++) {
+      const FieldDef &field = **it;
+      if (field.deprecated) continue;
+      code_.SetValue("FIELD_NAME", Name(field));
+      code_.SetValue("FIELD_OBJECT_TYPE", ObjectFieldType(field, true));
+      cb(field);
+    }
+  }
+  void MapNativeTableField(const FieldDef &field, const std::string &expr) {
+    if (field.required) {
+      // For some reason Args has optional types for required fields.
+      // TODO(cneo): Fix this... but its a breaking change?
+      code_ += "    let {{FIELD_NAME}} = Some({";
+      code_ += "      let x = &self.{{FIELD_NAME}};";
+      code_ += "      " + expr;
+      code_ += "    });";
+    } else {
+      code_ += "    let {{FIELD_NAME}} = self.{{FIELD_NAME}}.as_ref().map(|x|{";
+      code_ += "      " + expr;
+      code_ += "    });";
+    }
+  }
+
   // Generate functions to compare tables and structs by key. This function
   // must only be called if the field key is defined.
   void GenKeyFieldMethods(const FieldDef &field) {
@@ -1542,19 +2007,22 @@ class RustGenerator : public BaseGenerator {
 
     // The root datatype accessors:
     code_ += "#[inline]";
-    code_ += "#[deprecated(since=\"2.0.0\", "
-             "note=\"Deprecated in favor of `root_as...` methods.\")]";
+    code_ +=
+        "#[deprecated(since=\"2.0.0\", "
+        "note=\"Deprecated in favor of `root_as...` methods.\")]";
     code_ +=
         "pub fn get_root_as_{{STRUCT_NAME_SNAKECASE}}<'a>(buf: &'a [u8])"
         " -> {{STRUCT_NAME}}<'a> {";
-    code_ += "  unsafe { flatbuffers::root_unchecked::<{{STRUCT_NAME}}"
-             "<'a>>(buf) }";
+    code_ +=
+        "  unsafe { flatbuffers::root_unchecked::<{{STRUCT_NAME}}"
+        "<'a>>(buf) }";
     code_ += "}";
     code_ += "";
 
     code_ += "#[inline]";
-    code_ += "#[deprecated(since=\"2.0.0\", "
-             "note=\"Deprecated in favor of `root_as...` methods.\")]";
+    code_ +=
+        "#[deprecated(since=\"2.0.0\", "
+        "note=\"Deprecated in favor of `root_as...` methods.\")]";
     code_ +=
         "pub fn get_size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
         "<'a>(buf: &'a [u8]) -> {{STRUCT_NAME}}<'a> {";
@@ -1571,8 +2039,9 @@ class RustGenerator : public BaseGenerator {
     code_ += "/// catch every error, or be maximally performant. For the";
     code_ += "/// previous, unchecked, behavior use";
     code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
-    code_ += "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}(buf: &[u8]) "
-             "-> Result<{{STRUCT_NAME}}, flatbuffers::InvalidFlatbuffer> {";
+    code_ +=
+        "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}(buf: &[u8]) "
+        "-> Result<{{STRUCT_NAME}}, flatbuffers::InvalidFlatbuffer> {";
     code_ += "  flatbuffers::root::<{{STRUCT_NAME}}>(buf)";
     code_ += "}";
     code_ += "#[inline]";
@@ -1582,9 +2051,10 @@ class RustGenerator : public BaseGenerator {
     code_ += "/// catch every error, or be maximally performant. For the";
     code_ += "/// previous, unchecked, behavior use";
     code_ += "/// `size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
-    code_ += "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
-             "(buf: &[u8]) -> Result<{{STRUCT_NAME}}, "
-             "flatbuffers::InvalidFlatbuffer> {";
+    code_ +=
+        "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
+        "(buf: &[u8]) -> Result<{{STRUCT_NAME}}, "
+        "flatbuffers::InvalidFlatbuffer> {";
     code_ += "  flatbuffers::size_prefixed_root::<{{STRUCT_NAME}}>(buf)";
     code_ += "}";
     // Verifier with options root fns.
@@ -1598,8 +2068,9 @@ class RustGenerator : public BaseGenerator {
     code_ += "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts<'b, 'o>(";
     code_ += "  opts: &'o flatbuffers::VerifierOptions,";
     code_ += "  buf: &'b [u8],";
-    code_ += ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
-             " {";
+    code_ +=
+        ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+        " {";
     code_ += "  flatbuffers::root_with_opts::<{{STRUCT_NAME}}<'b>>(opts, buf)";
     code_ += "}";
     code_ += "#[inline]";
@@ -1609,39 +2080,48 @@ class RustGenerator : public BaseGenerator {
     code_ += "/// catch every error, or be maximally performant. For the";
     code_ += "/// previous, unchecked, behavior use";
     code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
-    code_ += "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts"
-             "<'b, 'o>(";
+    code_ +=
+        "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts"
+        "<'b, 'o>(";
     code_ += "  opts: &'o flatbuffers::VerifierOptions,";
     code_ += "  buf: &'b [u8],";
-    code_ += ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
-             " {";
-    code_ += "  flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_NAME}}"
-             "<'b>>(opts, buf)";
+    code_ +=
+        ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+        " {";
+    code_ +=
+        "  flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_NAME}}"
+        "<'b>>(opts, buf)";
     code_ += "}";
     // Unchecked root fns.
     code_ += "#[inline]";
-    code_ += "/// Assumes, without verification, that a buffer of bytes "
-             "contains a {{STRUCT_NAME}} and returns it.";
+    code_ +=
+        "/// Assumes, without verification, that a buffer of bytes "
+        "contains a {{STRUCT_NAME}} and returns it.";
     code_ += "/// # Safety";
-    code_ += "/// Callers must trust the given bytes do indeed contain a valid"
-             " `{{STRUCT_NAME}}`.";
-    code_ += "pub unsafe fn root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked"
-             "(buf: &[u8]) -> {{STRUCT_NAME}} {";
+    code_ +=
+        "/// Callers must trust the given bytes do indeed contain a valid"
+        " `{{STRUCT_NAME}}`.";
+    code_ +=
+        "pub unsafe fn root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked"
+        "(buf: &[u8]) -> {{STRUCT_NAME}} {";
     code_ += "  flatbuffers::root_unchecked::<{{STRUCT_NAME}}>(buf)";
     code_ += "}";
     code_ += "#[inline]";
-    code_ += "/// Assumes, without verification, that a buffer of bytes "
-             "contains a size prefixed {{STRUCT_NAME}} and returns it.";
+    code_ +=
+        "/// Assumes, without verification, that a buffer of bytes "
+        "contains a size prefixed {{STRUCT_NAME}} and returns it.";
     code_ += "/// # Safety";
-    code_ += "/// Callers must trust the given bytes do indeed contain a valid"
-             " size prefixed `{{STRUCT_NAME}}`.";
-    code_ += "pub unsafe fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
-             "_unchecked(buf: &[u8]) -> {{STRUCT_NAME}} {";
-    code_ += "  flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}>"
-             "(buf)";
+    code_ +=
+        "/// Callers must trust the given bytes do indeed contain a valid"
+        " size prefixed `{{STRUCT_NAME}}`.";
+    code_ +=
+        "pub unsafe fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
+        "_unchecked(buf: &[u8]) -> {{STRUCT_NAME}} {";
+    code_ +=
+        "  flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}>"
+        "(buf)";
     code_ += "}";
 
-
     if (parser_.file_identifier_.length()) {
       // Declare the identifier
       // (no lifetime needed as constants have static lifetimes by default)
@@ -1725,15 +2205,14 @@ class RustGenerator : public BaseGenerator {
     *code_ptr += "padding" + NumToString((*id)++) + "__: 0,";
   }
 
-  void ForAllStructFields(
-    const StructDef &struct_def,
-    std::function<void(const FieldDef &field)> cb
-  ) {
+  void ForAllStructFields(const StructDef &struct_def,
+                          std::function<void(const FieldDef &field)> cb) {
     size_t offset_to_field = 0;
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       const auto &field = **it;
       code_.SetValue("FIELD_TYPE", GetTypeGet(field.value.type));
+      code_.SetValue("FIELD_OBJECT_TYPE", ObjectFieldType(field, false));
       code_.SetValue("FIELD_NAME", Name(field));
       code_.SetValue("FIELD_OFFSET", NumToString(offset_to_field));
       code_.SetValue("REF", IsStruct(field.value.type) ? "&" : "");
@@ -1759,16 +2238,17 @@ class RustGenerator : public BaseGenerator {
     // hold for PartialOrd/Ord.
     code_ += "// struct {{STRUCT_NAME}}, aligned to {{ALIGN}}";
     code_ += "#[repr(transparent)]";
-    code_ += "#[derive(Clone, Copy, PartialEq)]";
+    code_ += "#[derive(Clone, Copy, PartialEq, Default)]";
     code_ += "pub struct {{STRUCT_NAME}}(pub [u8; {{STRUCT_SIZE}}]);";
 
     // Debug for structs.
     code_ += "impl std::fmt::Debug for {{STRUCT_NAME}} {";
-    code_ += "  fn fmt(&self, f: &mut std::fmt::Formatter"
-             ") -> std::fmt::Result {";
+    code_ +=
+        "  fn fmt(&self, f: &mut std::fmt::Formatter"
+        ") -> std::fmt::Result {";
     code_ += "    f.debug_struct(\"{{STRUCT_NAME}}\")";
     ForAllStructFields(struct_def, [&](const FieldDef &unused) {
-      (void) unused;
+      (void)unused;
       code_ += "      .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
     });
     code_ += "      .finish()";
@@ -1776,7 +2256,6 @@ class RustGenerator : public BaseGenerator {
     code_ += "}";
     code_ += "";
 
-
     // Generate impls for SafeSliceAccess (because all structs are endian-safe),
     // Follow for the value type, Follow for the reference type, Push for the
     // value type, and Push for the reference type.
@@ -1906,14 +2385,54 @@ class RustGenerator : public BaseGenerator {
       // Generate a comparison function for this field if it is a key.
       if (field.key) { GenKeyFieldMethods(field); }
     });
-    code_ += "}";
+
+    // Generate Object API unpack method.
+    if (parser_.opts.generate_object_based_api) {
+      code_.SetValue("NATIVE_STRUCT_NAME", NativeName(struct_def));
+      code_ += "  pub fn unpack(&self) -> {{NATIVE_STRUCT_NAME}} {";
+      code_ += "    {{NATIVE_STRUCT_NAME}} {";
+      ForAllStructFields(struct_def, [&](const FieldDef &field) {
+        std::string unpack = IsStruct(field.value.type) ? ".unpack()" : "";
+        code_ += "      {{FIELD_NAME}}: self.{{FIELD_NAME}}()" + unpack + ",";
+      });
+      code_ += "    }";
+      code_ += "  }";
+    }
+
+    code_ += "}";  // End impl Struct methods.
     code_ += "";
+
+    // Generate Struct Object.
+    if (parser_.opts.generate_object_based_api) {
+      // Struct declaration
+      code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
+      code_ += "pub struct {{NATIVE_STRUCT_NAME}} {";
+      ForAllStructFields(struct_def, [&](const FieldDef &field) {
+        (void)field;  // unused.
+        code_ += "  pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
+      });
+      code_ += "}";
+      // The `pack` method that turns the native struct into its Flatbuffers
+      // counterpart.
+      code_ += "impl {{NATIVE_STRUCT_NAME}} {";
+      code_ += "  pub fn pack(&self) -> {{STRUCT_NAME}} {";
+      code_ += "    {{STRUCT_NAME}}::new(";
+      ForAllStructFields(struct_def, [&](const FieldDef &field) {
+        if (IsStruct(field.value.type)) {
+          code_ += "      &self.{{FIELD_NAME}}.pack(),";
+        } else {
+          code_ += "      self.{{FIELD_NAME}},";
+        }
+      });
+      code_ += "    )";
+      code_ += "  }";
+      code_ += "}";
+      code_ += "";
+    }
   }
 
   void GenNamespaceImports(const int white_spaces) {
-    if (white_spaces == 0) {
-      code_ += "#![allow(unused_imports, dead_code)]";
-    }
+    if (white_spaces == 0) { code_ += "#![allow(unused_imports, dead_code)]"; }
     std::string indent = std::string(white_spaces, ' ');
     code_ += "";
     if (!parser_.opts.generate_all) {
@@ -1935,7 +2454,6 @@ class RustGenerator : public BaseGenerator {
         }
       }
     }
-
     code_ += indent + "use std::mem;";
     code_ += indent + "use std::cmp::Ordering;";
     code_ += "";
index a74690a..7fa6492 100755 (executable)
@@ -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
 
index 045e688..7972d1c 100644 (file)
@@ -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
index e074462..f8229c4 100755 (executable)
@@ -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
index 23c0d3f..4015a3c 100644 (file)
@@ -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>(
index a0137b9..9b3c7ee 100644 (file)
@@ -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>(
index 59c8f14..3f8714b 100644 (file)
@@ -44,9 +44,7 @@ impl<'a> InParentNamespace<'a> {
 
     #[inline]
     pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
-        InParentNamespace {
-            _tab: table,
-        }
+        InParentNamespace { _tab: table }
     }
     #[allow(unused_mut)]
     pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
@@ -56,6 +54,10 @@ impl<'a> InParentNamespace<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> InParentNamespaceT {
+      InParentNamespaceT {
+      }
+    }
 }
 
 impl flatbuffers::Verifiable for InParentNamespace<'_> {
@@ -104,6 +106,19 @@ impl std::fmt::Debug for InParentNamespace<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct InParentNamespaceT {
+}
+impl InParentNamespaceT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<InParentNamespace<'b>> {
+    InParentNamespace::create(_fbb, &InParentNamespaceArgs{
+    })
+  }
+}
 #[allow(unused_imports, dead_code)]
 pub mod example_2 {
 
@@ -137,9 +152,7 @@ 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>(
@@ -149,6 +162,10 @@ impl<'a> Monster<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> MonsterT {
+      MonsterT {
+      }
+    }
 }
 
 impl flatbuffers::Verifiable for Monster<'_> {
@@ -197,6 +214,19 @@ impl std::fmt::Debug for Monster<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct MonsterT {
+}
+impl MonsterT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<Monster<'b>> {
+    Monster::create(_fbb, &MonsterArgs{
+    })
+  }
+}
 }  // pub mod Example2
 
 #[allow(unused_imports, dead_code)]
@@ -214,6 +244,7 @@ pub mod example {
 mod bitflags_color {
   flatbuffers::bitflags::bitflags! {
     /// Composite components of Monster color.
+    #[derive(Default)]
     pub struct Color: u8 {
       const Red = 1;
       /// \brief color Green
@@ -280,7 +311,7 @@ pub const ENUM_VALUES_RACE: [Race; 4] = [
   Race::Elf,
 ];
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
 #[repr(transparent)]
 pub struct Race(pub i8);
 #[allow(non_upper_case_globals)]
@@ -372,7 +403,7 @@ pub const ENUM_VALUES_ANY: [Any; 4] = [
   Any::MyGame_Example2_Monster,
 ];
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
 #[repr(transparent)]
 pub struct Any(pub u8);
 #[allow(non_upper_case_globals)]
@@ -410,7 +441,6 @@ impl std::fmt::Debug for Any {
     }
   }
 }
-pub struct AnyUnionTableOffset {}
 impl<'a> flatbuffers::Follow<'a> for Any {
   type Inner = Self;
   #[inline]
@@ -452,6 +482,102 @@ impl<'a> flatbuffers::Verifiable for Any {
 }
 
 impl flatbuffers::SimpleToVerifyInSlice for Any {}
+pub struct AnyUnionTableOffset {}
+
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq)]
+pub enum AnyT {
+  NONE,
+  Monster(Box<MonsterT>),
+  TestSimpleTableWithEnum(Box<TestSimpleTableWithEnumT>),
+  MyGameExample2Monster(Box<super::example_2::MonsterT>),
+}
+impl Default for AnyT {
+  fn default() -> Self {
+    Self::NONE
+  }
+}
+impl AnyT {
+  fn any_type(&self) -> Any {
+    match self {
+      Self::NONE => Any::NONE,
+      Self::Monster(_) => Any::Monster,
+      Self::TestSimpleTableWithEnum(_) => Any::TestSimpleTableWithEnum,
+      Self::MyGameExample2Monster(_) => Any::MyGame_Example2_Monster,
+    }
+  }
+  pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder) -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>> {
+    match self {
+      Self::NONE => None,
+      Self::Monster(v) => Some(v.pack(fbb).as_union_value()),
+      Self::TestSimpleTableWithEnum(v) => Some(v.pack(fbb).as_union_value()),
+      Self::MyGameExample2Monster(v) => Some(v.pack(fbb).as_union_value()),
+    }
+  }
+  /// If the union variant matches, return the owned MonsterT, setting the union to NONE.
+  pub fn take_monster(&mut self) -> Option<Box<MonsterT>> {
+    if let Self::Monster(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::Monster(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the MonsterT.
+  pub fn as_monster(&self) -> Option<&MonsterT> {
+    if let Self::Monster(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the MonsterT.
+  pub fn as_monster_mut(&mut self) -> Option<&mut MonsterT> {
+    if let Self::Monster(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned TestSimpleTableWithEnumT, setting the union to NONE.
+  pub fn take_test_simple_table_with_enum(&mut self) -> Option<Box<TestSimpleTableWithEnumT>> {
+    if let Self::TestSimpleTableWithEnum(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::TestSimpleTableWithEnum(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the TestSimpleTableWithEnumT.
+  pub fn as_test_simple_table_with_enum(&self) -> Option<&TestSimpleTableWithEnumT> {
+    if let Self::TestSimpleTableWithEnum(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the TestSimpleTableWithEnumT.
+  pub fn as_test_simple_table_with_enum_mut(&mut self) -> Option<&mut TestSimpleTableWithEnumT> {
+    if let Self::TestSimpleTableWithEnum(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned super::example_2::MonsterT, setting the union to NONE.
+  pub fn take_my_game_example_2_monster(&mut self) -> Option<Box<super::example_2::MonsterT>> {
+    if let Self::MyGameExample2Monster(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::MyGameExample2Monster(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the super::example_2::MonsterT.
+  pub fn as_my_game_example_2_monster(&self) -> Option<&super::example_2::MonsterT> {
+    if let Self::MyGameExample2Monster(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the super::example_2::MonsterT.
+  pub fn as_my_game_example_2_monster_mut(&mut self) -> Option<&mut super::example_2::MonsterT> {
+    if let Self::MyGameExample2Monster(v) = self { Some(v.as_mut()) } else { None }
+  }
+}
 #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
 pub const ENUM_MIN_ANY_UNIQUE_ALIASES: u8 = 0;
 #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -465,7 +591,7 @@ pub const ENUM_VALUES_ANY_UNIQUE_ALIASES: [AnyUniqueAliases; 4] = [
   AnyUniqueAliases::M2,
 ];
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
 #[repr(transparent)]
 pub struct AnyUniqueAliases(pub u8);
 #[allow(non_upper_case_globals)]
@@ -503,7 +629,6 @@ impl std::fmt::Debug for AnyUniqueAliases {
     }
   }
 }
-pub struct AnyUniqueAliasesUnionTableOffset {}
 impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases {
   type Inner = Self;
   #[inline]
@@ -545,6 +670,102 @@ impl<'a> flatbuffers::Verifiable for AnyUniqueAliases {
 }
 
 impl flatbuffers::SimpleToVerifyInSlice for AnyUniqueAliases {}
+pub struct AnyUniqueAliasesUnionTableOffset {}
+
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq)]
+pub enum AnyUniqueAliasesT {
+  NONE,
+  M(Box<MonsterT>),
+  TS(Box<TestSimpleTableWithEnumT>),
+  M2(Box<super::example_2::MonsterT>),
+}
+impl Default for AnyUniqueAliasesT {
+  fn default() -> Self {
+    Self::NONE
+  }
+}
+impl AnyUniqueAliasesT {
+  fn any_unique_aliases_type(&self) -> AnyUniqueAliases {
+    match self {
+      Self::NONE => AnyUniqueAliases::NONE,
+      Self::M(_) => AnyUniqueAliases::M,
+      Self::TS(_) => AnyUniqueAliases::TS,
+      Self::M2(_) => AnyUniqueAliases::M2,
+    }
+  }
+  pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder) -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>> {
+    match self {
+      Self::NONE => None,
+      Self::M(v) => Some(v.pack(fbb).as_union_value()),
+      Self::TS(v) => Some(v.pack(fbb).as_union_value()),
+      Self::M2(v) => Some(v.pack(fbb).as_union_value()),
+    }
+  }
+  /// If the union variant matches, return the owned MonsterT, setting the union to NONE.
+  pub fn take_m(&mut self) -> Option<Box<MonsterT>> {
+    if let Self::M(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::M(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the MonsterT.
+  pub fn as_m(&self) -> Option<&MonsterT> {
+    if let Self::M(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the MonsterT.
+  pub fn as_m_mut(&mut self) -> Option<&mut MonsterT> {
+    if let Self::M(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned TestSimpleTableWithEnumT, setting the union to NONE.
+  pub fn take_ts(&mut self) -> Option<Box<TestSimpleTableWithEnumT>> {
+    if let Self::TS(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::TS(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the TestSimpleTableWithEnumT.
+  pub fn as_ts(&self) -> Option<&TestSimpleTableWithEnumT> {
+    if let Self::TS(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the TestSimpleTableWithEnumT.
+  pub fn as_ts_mut(&mut self) -> Option<&mut TestSimpleTableWithEnumT> {
+    if let Self::TS(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned super::example_2::MonsterT, setting the union to NONE.
+  pub fn take_m2(&mut self) -> Option<Box<super::example_2::MonsterT>> {
+    if let Self::M2(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::M2(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the super::example_2::MonsterT.
+  pub fn as_m2(&self) -> Option<&super::example_2::MonsterT> {
+    if let Self::M2(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the super::example_2::MonsterT.
+  pub fn as_m2_mut(&mut self) -> Option<&mut super::example_2::MonsterT> {
+    if let Self::M2(v) = self { Some(v.as_mut()) } else { None }
+  }
+}
 #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
 pub const ENUM_MIN_ANY_AMBIGUOUS_ALIASES: u8 = 0;
 #[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -558,7 +779,7 @@ pub const ENUM_VALUES_ANY_AMBIGUOUS_ALIASES: [AnyAmbiguousAliases; 4] = [
   AnyAmbiguousAliases::M3,
 ];
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
 #[repr(transparent)]
 pub struct AnyAmbiguousAliases(pub u8);
 #[allow(non_upper_case_globals)]
@@ -596,7 +817,6 @@ impl std::fmt::Debug for AnyAmbiguousAliases {
     }
   }
 }
-pub struct AnyAmbiguousAliasesUnionTableOffset {}
 impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases {
   type Inner = Self;
   #[inline]
@@ -638,9 +858,105 @@ impl<'a> flatbuffers::Verifiable for AnyAmbiguousAliases {
 }
 
 impl flatbuffers::SimpleToVerifyInSlice for AnyAmbiguousAliases {}
+pub struct AnyAmbiguousAliasesUnionTableOffset {}
+
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq)]
+pub enum AnyAmbiguousAliasesT {
+  NONE,
+  M1(Box<MonsterT>),
+  M2(Box<MonsterT>),
+  M3(Box<MonsterT>),
+}
+impl Default for AnyAmbiguousAliasesT {
+  fn default() -> Self {
+    Self::NONE
+  }
+}
+impl AnyAmbiguousAliasesT {
+  fn any_ambiguous_aliases_type(&self) -> AnyAmbiguousAliases {
+    match self {
+      Self::NONE => AnyAmbiguousAliases::NONE,
+      Self::M1(_) => AnyAmbiguousAliases::M1,
+      Self::M2(_) => AnyAmbiguousAliases::M2,
+      Self::M3(_) => AnyAmbiguousAliases::M3,
+    }
+  }
+  pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder) -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>> {
+    match self {
+      Self::NONE => None,
+      Self::M1(v) => Some(v.pack(fbb).as_union_value()),
+      Self::M2(v) => Some(v.pack(fbb).as_union_value()),
+      Self::M3(v) => Some(v.pack(fbb).as_union_value()),
+    }
+  }
+  /// If the union variant matches, return the owned MonsterT, setting the union to NONE.
+  pub fn take_m1(&mut self) -> Option<Box<MonsterT>> {
+    if let Self::M1(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::M1(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the MonsterT.
+  pub fn as_m1(&self) -> Option<&MonsterT> {
+    if let Self::M1(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the MonsterT.
+  pub fn as_m1_mut(&mut self) -> Option<&mut MonsterT> {
+    if let Self::M1(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned MonsterT, setting the union to NONE.
+  pub fn take_m2(&mut self) -> Option<Box<MonsterT>> {
+    if let Self::M2(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::M2(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the MonsterT.
+  pub fn as_m2(&self) -> Option<&MonsterT> {
+    if let Self::M2(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the MonsterT.
+  pub fn as_m2_mut(&mut self) -> Option<&mut MonsterT> {
+    if let Self::M2(v) = self { Some(v.as_mut()) } else { None }
+  }
+  /// If the union variant matches, return the owned MonsterT, setting the union to NONE.
+  pub fn take_m3(&mut self) -> Option<Box<MonsterT>> {
+    if let Self::M3(_) = self {
+      let v = std::mem::replace(self, Self::NONE);
+      if let Self::M3(w) = v {
+        Some(w)
+      } else {
+        unreachable!()
+      }
+    } else {
+      None
+    }
+  }
+  /// If the union variant matches, return a reference to the MonsterT.
+  pub fn as_m3(&self) -> Option<&MonsterT> {
+    if let Self::M3(v) = self { Some(v.as_ref()) } else { None }
+  }
+  /// If the union variant matches, return a mutable reference to the MonsterT.
+  pub fn as_m3_mut(&mut self) -> Option<&mut MonsterT> {
+    if let Self::M3(v) = self { Some(v.as_mut()) } else { None }
+  }
+}
 // struct Test, aligned to 2
 #[repr(transparent)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Default)]
 pub struct Test(pub [u8; 4]);
 impl std::fmt::Debug for Test {
   fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
@@ -760,11 +1076,31 @@ impl Test {
     }
   }
 
+  pub fn unpack(&self) -> TestT {
+    TestT {
+      a: self.a(),
+      b: self.b(),
+    }
+  }
+}
+
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct TestT {
+  pub a: i16,
+  pub b: i8,
+}
+impl TestT {
+  pub fn pack(&self) -> Test {
+    Test::new(
+      self.a,
+      self.b,
+    )
+  }
 }
 
 // struct Vec3, aligned to 8
 #[repr(transparent)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Default)]
 pub struct Vec3(pub [u8; 32]);
 impl std::fmt::Debug for Vec3 {
   fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
@@ -973,11 +1309,43 @@ impl Vec3 {
     self.0[26..26+4].copy_from_slice(&x.0)
   }
 
+  pub fn unpack(&self) -> Vec3T {
+    Vec3T {
+      x: self.x(),
+      y: self.y(),
+      z: self.z(),
+      test1: self.test1(),
+      test2: self.test2(),
+      test3: self.test3().unpack(),
+    }
+  }
+}
+
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct Vec3T {
+  pub x: f32,
+  pub y: f32,
+  pub z: f32,
+  pub test1: f64,
+  pub test2: Color,
+  pub test3: TestT,
+}
+impl Vec3T {
+  pub fn pack(&self) -> Vec3 {
+    Vec3::new(
+      self.x,
+      self.y,
+      self.z,
+      self.test1,
+      self.test2,
+      &self.test3.pack(),
+    )
+  }
 }
 
 // struct Ability, aligned to 4
 #[repr(transparent)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Default)]
 pub struct Ability(pub [u8; 8]);
 impl std::fmt::Debug for Ability {
   fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
@@ -1107,6 +1475,26 @@ impl Ability {
     }
   }
 
+  pub fn unpack(&self) -> AbilityT {
+    AbilityT {
+      id: self.id(),
+      distance: self.distance(),
+    }
+  }
+}
+
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct AbilityT {
+  pub id: u32,
+  pub distance: u32,
+}
+impl AbilityT {
+  pub fn pack(&self) -> Ability {
+    Ability::new(
+      self.id,
+      self.distance,
+    )
+  }
 }
 
 pub enum TestSimpleTableWithEnumOffset {}
@@ -1131,9 +1519,7 @@ impl<'a> TestSimpleTableWithEnum<'a> {
 
     #[inline]
     pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
-        TestSimpleTableWithEnum {
-            _tab: table,
-        }
+        TestSimpleTableWithEnum { _tab: table }
     }
     #[allow(unused_mut)]
     pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
@@ -1144,6 +1530,12 @@ impl<'a> TestSimpleTableWithEnum<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> TestSimpleTableWithEnumT {
+      let color = self.color();
+      TestSimpleTableWithEnumT {
+        color,
+      }
+    }
     pub const VT_COLOR: flatbuffers::VOffsetT = 4;
 
   #[inline]
@@ -1206,6 +1598,22 @@ impl std::fmt::Debug for TestSimpleTableWithEnum<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct TestSimpleTableWithEnumT {
+  pub color: Color,
+}
+impl TestSimpleTableWithEnumT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<TestSimpleTableWithEnum<'b>> {
+    let color = self.color;
+    TestSimpleTableWithEnum::create(_fbb, &TestSimpleTableWithEnumArgs{
+      color,
+    })
+  }
+}
 pub enum StatOffset {}
 #[derive(Copy, Clone, PartialEq)]
 
@@ -1228,9 +1636,7 @@ impl<'a> Stat<'a> {
 
     #[inline]
     pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
-        Stat {
-            _tab: table,
-        }
+        Stat { _tab: table }
     }
     #[allow(unused_mut)]
     pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
@@ -1243,6 +1649,18 @@ impl<'a> Stat<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> StatT {
+      let id = self.id().map(|x| {
+        x.to_string()
+      });
+      let val = self.val();
+      let count = self.count();
+      StatT {
+        id,
+        val,
+        count,
+      }
+    }
     pub const VT_ID: flatbuffers::VOffsetT = 4;
     pub const VT_VAL: flatbuffers::VOffsetT = 6;
     pub const VT_COUNT: flatbuffers::VOffsetT = 8;
@@ -1341,6 +1759,30 @@ impl std::fmt::Debug for Stat<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct StatT {
+  pub id: Option<String>,
+  pub val: i64,
+  pub count: u16,
+}
+impl StatT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<Stat<'b>> {
+    let id = self.id.as_ref().map(|x|{
+      _fbb.create_string(x)
+    });
+    let val = self.val;
+    let count = self.count;
+    Stat::create(_fbb, &StatArgs{
+      id,
+      val,
+      count,
+    })
+  }
+}
 pub enum ReferrableOffset {}
 #[derive(Copy, Clone, PartialEq)]
 
@@ -1363,9 +1805,7 @@ impl<'a> Referrable<'a> {
 
     #[inline]
     pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
-        Referrable {
-            _tab: table,
-        }
+        Referrable { _tab: table }
     }
     #[allow(unused_mut)]
     pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
@@ -1376,6 +1816,12 @@ impl<'a> Referrable<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> ReferrableT {
+      let id = self.id();
+      ReferrableT {
+        id,
+      }
+    }
     pub const VT_ID: flatbuffers::VOffsetT = 4;
 
   #[inline]
@@ -1448,6 +1894,22 @@ impl std::fmt::Debug for Referrable<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct ReferrableT {
+  pub id: u64,
+}
+impl ReferrableT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<Referrable<'b>> {
+    let id = self.id;
+    Referrable::create(_fbb, &ReferrableArgs{
+      id,
+    })
+  }
+}
 pub enum MonsterOffset {}
 #[derive(Copy, Clone, PartialEq)]
 
@@ -1471,9 +1933,7 @@ 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>(
@@ -1533,6 +1993,209 @@ 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 = {
+        let x = self.name();
+        x.to_string()
+      };
+      let inventory = self.inventory().map(|x| {
+        x.to_vec()
+      });
+      let color = self.color();
+      let test = match self.test_type() {
+        Any::NONE => AnyT::NONE,
+        Any::Monster => AnyT::Monster(Box::new(
+          self.test_as_monster()
+              .expect("Invalid union table, expected `Any::Monster`.")
+              .unpack()
+        )),
+        Any::TestSimpleTableWithEnum => AnyT::TestSimpleTableWithEnum(Box::new(
+          self.test_as_test_simple_table_with_enum()
+              .expect("Invalid union table, expected `Any::TestSimpleTableWithEnum`.")
+              .unpack()
+        )),
+        Any::MyGame_Example2_Monster => AnyT::MyGameExample2Monster(Box::new(
+          self.test_as_my_game_example_2_monster()
+              .expect("Invalid union table, expected `Any::MyGame_Example2_Monster`.")
+              .unpack()
+        )),
+        _ => AnyT::NONE,
+      };
+      let test4 = self.test4().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let testarrayofstring = self.testarrayofstring().map(|x| {
+        x.iter().map(|s| s.to_string()).collect()
+      });
+      let testarrayoftables = self.testarrayoftables().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let enemy = self.enemy().map(|x| {
+        Box::new(x.unpack())
+      });
+      let testnestedflatbuffer = self.testnestedflatbuffer().map(|x| {
+        x.to_vec()
+      });
+      let testempty = self.testempty().map(|x| {
+        Box::new(x.unpack())
+      });
+      let testbool = self.testbool();
+      let testhashs32_fnv1 = self.testhashs32_fnv1();
+      let testhashu32_fnv1 = self.testhashu32_fnv1();
+      let testhashs64_fnv1 = self.testhashs64_fnv1();
+      let testhashu64_fnv1 = self.testhashu64_fnv1();
+      let testhashs32_fnv1a = self.testhashs32_fnv1a();
+      let testhashu32_fnv1a = self.testhashu32_fnv1a();
+      let testhashs64_fnv1a = self.testhashs64_fnv1a();
+      let testhashu64_fnv1a = self.testhashu64_fnv1a();
+      let testarrayofbools = self.testarrayofbools().map(|x| {
+        x.to_vec()
+      });
+      let testf = self.testf();
+      let testf2 = self.testf2();
+      let testf3 = self.testf3();
+      let testarrayofstring2 = self.testarrayofstring2().map(|x| {
+        x.iter().map(|s| s.to_string()).collect()
+      });
+      let testarrayofsortedstruct = self.testarrayofsortedstruct().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let flex = self.flex().map(|x| {
+        x.to_vec()
+      });
+      let test5 = self.test5().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let vector_of_longs = self.vector_of_longs().map(|x| {
+        x.into_iter().collect()
+      });
+      let vector_of_doubles = self.vector_of_doubles().map(|x| {
+        x.into_iter().collect()
+      });
+      let parent_namespace_test = self.parent_namespace_test().map(|x| {
+        Box::new(x.unpack())
+      });
+      let vector_of_referrables = self.vector_of_referrables().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let single_weak_reference = self.single_weak_reference();
+      let vector_of_weak_references = self.vector_of_weak_references().map(|x| {
+        x.into_iter().collect()
+      });
+      let vector_of_strong_referrables = self.vector_of_strong_referrables().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      let co_owning_reference = self.co_owning_reference();
+      let vector_of_co_owning_references = self.vector_of_co_owning_references().map(|x| {
+        x.into_iter().collect()
+      });
+      let non_owning_reference = self.non_owning_reference();
+      let vector_of_non_owning_references = self.vector_of_non_owning_references().map(|x| {
+        x.into_iter().collect()
+      });
+      let any_unique = match self.any_unique_type() {
+        AnyUniqueAliases::NONE => AnyUniqueAliasesT::NONE,
+        AnyUniqueAliases::M => AnyUniqueAliasesT::M(Box::new(
+          self.any_unique_as_m()
+              .expect("Invalid union table, expected `AnyUniqueAliases::M`.")
+              .unpack()
+        )),
+        AnyUniqueAliases::TS => AnyUniqueAliasesT::TS(Box::new(
+          self.any_unique_as_ts()
+              .expect("Invalid union table, expected `AnyUniqueAliases::TS`.")
+              .unpack()
+        )),
+        AnyUniqueAliases::M2 => AnyUniqueAliasesT::M2(Box::new(
+          self.any_unique_as_m2()
+              .expect("Invalid union table, expected `AnyUniqueAliases::M2`.")
+              .unpack()
+        )),
+        _ => AnyUniqueAliasesT::NONE,
+      };
+      let any_ambiguous = match self.any_ambiguous_type() {
+        AnyAmbiguousAliases::NONE => AnyAmbiguousAliasesT::NONE,
+        AnyAmbiguousAliases::M1 => AnyAmbiguousAliasesT::M1(Box::new(
+          self.any_ambiguous_as_m1()
+              .expect("Invalid union table, expected `AnyAmbiguousAliases::M1`.")
+              .unpack()
+        )),
+        AnyAmbiguousAliases::M2 => AnyAmbiguousAliasesT::M2(Box::new(
+          self.any_ambiguous_as_m2()
+              .expect("Invalid union table, expected `AnyAmbiguousAliases::M2`.")
+              .unpack()
+        )),
+        AnyAmbiguousAliases::M3 => AnyAmbiguousAliasesT::M3(Box::new(
+          self.any_ambiguous_as_m3()
+              .expect("Invalid union table, expected `AnyAmbiguousAliases::M3`.")
+              .unpack()
+        )),
+        _ => AnyAmbiguousAliasesT::NONE,
+      };
+      let vector_of_enums = self.vector_of_enums().map(|x| {
+        x.into_iter().collect()
+      });
+      let signed_enum = self.signed_enum();
+      let testrequirednestedflatbuffer = self.testrequirednestedflatbuffer().map(|x| {
+        x.to_vec()
+      });
+      let scalar_key_sorted_tables = self.scalar_key_sorted_tables().map(|x| {
+        x.iter().map(|t| t.unpack()).collect()
+      });
+      MonsterT {
+        pos,
+        mana,
+        hp,
+        name,
+        inventory,
+        color,
+        test,
+        test4,
+        testarrayofstring,
+        testarrayoftables,
+        enemy,
+        testnestedflatbuffer,
+        testempty,
+        testbool,
+        testhashs32_fnv1,
+        testhashu32_fnv1,
+        testhashs64_fnv1,
+        testhashu64_fnv1,
+        testhashs32_fnv1a,
+        testhashu32_fnv1a,
+        testhashs64_fnv1a,
+        testhashu64_fnv1a,
+        testarrayofbools,
+        testf,
+        testf2,
+        testf3,
+        testarrayofstring2,
+        testarrayofsortedstruct,
+        flex,
+        test5,
+        vector_of_longs,
+        vector_of_doubles,
+        parent_namespace_test,
+        vector_of_referrables,
+        single_weak_reference,
+        vector_of_weak_references,
+        vector_of_strong_referrables,
+        co_owning_reference,
+        vector_of_co_owning_references,
+        non_owning_reference,
+        vector_of_non_owning_references,
+        any_unique,
+        any_ambiguous,
+        vector_of_enums,
+        signed_enum,
+        testrequirednestedflatbuffer,
+        scalar_key_sorted_tables,
+      }
+    }
     pub const VT_POS: flatbuffers::VOffsetT = 4;
     pub const VT_MANA: flatbuffers::VOffsetT = 6;
     pub const VT_HP: flatbuffers::VOffsetT = 8;
@@ -2443,6 +3106,216 @@ 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: String,
+  pub inventory: Option<Vec<u8>>,
+  pub color: Color,
+  pub test: AnyT,
+  pub test4: Option<Vec<TestT>>,
+  pub testarrayofstring: Option<Vec<String>>,
+  pub testarrayoftables: Option<Vec<MonsterT>>,
+  pub enemy: Option<Box<MonsterT>>,
+  pub testnestedflatbuffer: Option<Vec<u8>>,
+  pub testempty: Option<Box<StatT>>,
+  pub testbool: bool,
+  pub testhashs32_fnv1: i32,
+  pub testhashu32_fnv1: u32,
+  pub testhashs64_fnv1: i64,
+  pub testhashu64_fnv1: u64,
+  pub testhashs32_fnv1a: i32,
+  pub testhashu32_fnv1a: u32,
+  pub testhashs64_fnv1a: i64,
+  pub testhashu64_fnv1a: u64,
+  pub testarrayofbools: Option<Vec<bool>>,
+  pub testf: f32,
+  pub testf2: f32,
+  pub testf3: f32,
+  pub testarrayofstring2: Option<Vec<String>>,
+  pub testarrayofsortedstruct: Option<Vec<AbilityT>>,
+  pub flex: Option<Vec<u8>>,
+  pub test5: Option<Vec<TestT>>,
+  pub vector_of_longs: Option<Vec<i64>>,
+  pub vector_of_doubles: Option<Vec<f64>>,
+  pub parent_namespace_test: Option<Box<super::InParentNamespaceT>>,
+  pub vector_of_referrables: Option<Vec<ReferrableT>>,
+  pub single_weak_reference: u64,
+  pub vector_of_weak_references: Option<Vec<u64>>,
+  pub vector_of_strong_referrables: Option<Vec<ReferrableT>>,
+  pub co_owning_reference: u64,
+  pub vector_of_co_owning_references: Option<Vec<u64>>,
+  pub non_owning_reference: u64,
+  pub vector_of_non_owning_references: Option<Vec<u64>>,
+  pub any_unique: AnyUniqueAliasesT,
+  pub any_ambiguous: AnyAmbiguousAliasesT,
+  pub vector_of_enums: Option<Vec<Color>>,
+  pub signed_enum: Race,
+  pub testrequirednestedflatbuffer: Option<Vec<u8>>,
+  pub scalar_key_sorted_tables: Option<Vec<StatT>>,
+}
+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 = Some({
+      let x = &self.name;
+      _fbb.create_string(x)
+    });
+    let inventory = self.inventory.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let color = self.color;
+    let test_type = self.test.any_type();
+    let test = self.test.pack(_fbb);
+    let test4 = self.test4.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
+    });
+    let testarrayofstring = self.testarrayofstring.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w)
+    });
+    let testarrayoftables = self.testarrayoftables.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
+    });
+    let enemy = self.enemy.as_ref().map(|x|{
+      x.pack(_fbb)
+    });
+    let testnestedflatbuffer = self.testnestedflatbuffer.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let testempty = self.testempty.as_ref().map(|x|{
+      x.pack(_fbb)
+    });
+    let testbool = self.testbool;
+    let testhashs32_fnv1 = self.testhashs32_fnv1;
+    let testhashu32_fnv1 = self.testhashu32_fnv1;
+    let testhashs64_fnv1 = self.testhashs64_fnv1;
+    let testhashu64_fnv1 = self.testhashu64_fnv1;
+    let testhashs32_fnv1a = self.testhashs32_fnv1a;
+    let testhashu32_fnv1a = self.testhashu32_fnv1a;
+    let testhashs64_fnv1a = self.testhashs64_fnv1a;
+    let testhashu64_fnv1a = self.testhashu64_fnv1a;
+    let testarrayofbools = self.testarrayofbools.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let testf = self.testf;
+    let testf2 = self.testf2;
+    let testf3 = self.testf3;
+    let testarrayofstring2 = self.testarrayofstring2.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w)
+    });
+    let testarrayofsortedstruct = self.testarrayofsortedstruct.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
+    });
+    let flex = self.flex.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let test5 = self.test5.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w)
+    });
+    let vector_of_longs = self.vector_of_longs.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let vector_of_doubles = self.vector_of_doubles.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let parent_namespace_test = self.parent_namespace_test.as_ref().map(|x|{
+      x.pack(_fbb)
+    });
+    let vector_of_referrables = self.vector_of_referrables.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
+    });
+    let single_weak_reference = self.single_weak_reference;
+    let vector_of_weak_references = self.vector_of_weak_references.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let vector_of_strong_referrables = self.vector_of_strong_referrables.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
+    });
+    let co_owning_reference = self.co_owning_reference;
+    let vector_of_co_owning_references = self.vector_of_co_owning_references.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let non_owning_reference = self.non_owning_reference;
+    let vector_of_non_owning_references = self.vector_of_non_owning_references.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let any_unique_type = self.any_unique.any_unique_aliases_type();
+    let any_unique = self.any_unique.pack(_fbb);
+    let any_ambiguous_type = self.any_ambiguous.any_ambiguous_aliases_type();
+    let any_ambiguous = self.any_ambiguous.pack(_fbb);
+    let vector_of_enums = self.vector_of_enums.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let signed_enum = self.signed_enum;
+    let testrequirednestedflatbuffer = self.testrequirednestedflatbuffer.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let scalar_key_sorted_tables = self.scalar_key_sorted_tables.as_ref().map(|x|{
+      let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w)
+    });
+    Monster::create(_fbb, &MonsterArgs{
+      pos,
+      mana,
+      hp,
+      name,
+      inventory,
+      color,
+      test_type,
+      test,
+      test4,
+      testarrayofstring,
+      testarrayoftables,
+      enemy,
+      testnestedflatbuffer,
+      testempty,
+      testbool,
+      testhashs32_fnv1,
+      testhashu32_fnv1,
+      testhashs64_fnv1,
+      testhashu64_fnv1,
+      testhashs32_fnv1a,
+      testhashu32_fnv1a,
+      testhashs64_fnv1a,
+      testhashu64_fnv1a,
+      testarrayofbools,
+      testf,
+      testf2,
+      testf3,
+      testarrayofstring2,
+      testarrayofsortedstruct,
+      flex,
+      test5,
+      vector_of_longs,
+      vector_of_doubles,
+      parent_namespace_test,
+      vector_of_referrables,
+      single_weak_reference,
+      vector_of_weak_references,
+      vector_of_strong_referrables,
+      co_owning_reference,
+      vector_of_co_owning_references,
+      non_owning_reference,
+      vector_of_non_owning_references,
+      any_unique_type,
+      any_unique,
+      any_ambiguous_type,
+      any_ambiguous,
+      vector_of_enums,
+      signed_enum,
+      testrequirednestedflatbuffer,
+      scalar_key_sorted_tables,
+    })
+  }
+}
 pub enum TypeAliasesOffset {}
 #[derive(Copy, Clone, PartialEq)]
 
@@ -2465,9 +3338,7 @@ impl<'a> TypeAliases<'a> {
 
     #[inline]
     pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
-        TypeAliases {
-            _tab: table,
-        }
+        TypeAliases { _tab: table }
     }
     #[allow(unused_mut)]
     pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
@@ -2489,6 +3360,38 @@ impl<'a> TypeAliases<'a> {
       builder.finish()
     }
 
+    pub fn unpack(&self) -> TypeAliasesT {
+      let i8_ = self.i8_();
+      let u8_ = self.u8_();
+      let i16_ = self.i16_();
+      let u16_ = self.u16_();
+      let i32_ = self.i32_();
+      let u32_ = self.u32_();
+      let i64_ = self.i64_();
+      let u64_ = self.u64_();
+      let f32_ = self.f32_();
+      let f64_ = self.f64_();
+      let v8 = self.v8().map(|x| {
+        x.to_vec()
+      });
+      let vf64 = self.vf64().map(|x| {
+        x.into_iter().collect()
+      });
+      TypeAliasesT {
+        i8_,
+        u8_,
+        i16_,
+        u16_,
+        i32_,
+        u32_,
+        i64_,
+        u64_,
+        f32_,
+        f64_,
+        v8,
+        vf64,
+      }
+    }
     pub const VT_I8_: flatbuffers::VOffsetT = 4;
     pub const VT_U8_: flatbuffers::VOffsetT = 6;
     pub const VT_I16_: flatbuffers::VOffsetT = 8;
@@ -2694,6 +3597,59 @@ impl std::fmt::Debug for TypeAliases<'_> {
       ds.finish()
   }
 }
+#[non_exhaustive]
+#[derive(Debug, Clone, PartialEq, Default)]
+pub struct TypeAliasesT {
+  pub i8_: i8,
+  pub u8_: u8,
+  pub i16_: i16,
+  pub u16_: u16,
+  pub i32_: i32,
+  pub u32_: u32,
+  pub i64_: i64,
+  pub u64_: u64,
+  pub f32_: f32,
+  pub f64_: f64,
+  pub v8: Option<Vec<i8>>,
+  pub vf64: Option<Vec<f64>>,
+}
+impl TypeAliasesT {
+  pub fn pack<'b>(
+    &self,
+    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>
+  ) -> flatbuffers::WIPOffset<TypeAliases<'b>> {
+    let i8_ = self.i8_;
+    let u8_ = self.u8_;
+    let i16_ = self.i16_;
+    let u16_ = self.u16_;
+    let i32_ = self.i32_;
+    let u32_ = self.u32_;
+    let i64_ = self.i64_;
+    let u64_ = self.u64_;
+    let f32_ = self.f32_;
+    let f64_ = self.f64_;
+    let v8 = self.v8.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    let vf64 = self.vf64.as_ref().map(|x|{
+      _fbb.create_vector(x)
+    });
+    TypeAliases::create(_fbb, &TypeAliasesArgs{
+      i8_,
+      u8_,
+      i16_,
+      u16_,
+      i32_,
+      u32_,
+      i64_,
+      u64_,
+      f32_,
+      f64_,
+      v8,
+      vf64,
+    })
+  }
+}
 #[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> {
index e3a58b6..516c9b8 100644 (file)
@@ -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
 
index 490dd6b..a774dbf 100644 (file)
@@ -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
 
index 702df82..73ebee3 100644 (file)
@@ -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> {
index 7cf2db5..84abd1e 100644 (file)
@@ -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;
index a3c4300..2e3c7ac 100644 (file)
@@ -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;
index a307128..c5a0a56 100644 (file)
@@ -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() {
index 5a66241..32e9372 100644 (file)
@@ -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);
         }
     };
 }