}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct MonsterT {
pub pos: Option<Vec3T>,
pub mana: i16,
pub equipped: EquipmentT,
pub path: Option<Vec<Vec3T>>,
}
+impl Default for MonsterT {
+ fn default() -> Self {
+ Self {
+ pos: None,
+ mana: 150,
+ hp: 100,
+ name: None,
+ inventory: None,
+ color: Color::Blue,
+ weapons: None,
+ equipped: EquipmentT::NONE,
+ path: None,
+ }
+ }
+}
impl MonsterT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct WeaponT {
pub name: Option<String>,
pub damage: i16,
}
+impl Default for WeaponT {
+ fn default() -> Self {
+ Self {
+ name: None,
+ damage: 0,
+ }
+ }
+}
impl WeaponT {
pub fn pack<'b>(
&self,
return "VT_" + MakeUpper(Name(field));
}
- std::string GetDefaultScalarValue(const FieldDef &field) {
+ std::string GetDefaultValue(const FieldDef &field, bool for_builder) {
+ if (for_builder) {
+ // Builders and Args structs model nonscalars "optional" even if they're
+ // required or have defaults according to the schema. I guess its because
+ // WIPOffset is not nullable.
+ if (!IsScalar(field.value.type.base_type) || field.IsOptional()) {
+ return "None";
+ }
+ } else {
+ // This for defaults in objects.
+ // Unions have a NONE variant instead of using Rust's None.
+ if (field.IsOptional() && !IsUnion(field.value.type)) { return "None"; }
+ }
switch (GetFullType(field.value.type)) {
case ftInteger:
case ftFloat: {
- return field.IsOptional() ? "None" : field.value.constant;
+ return field.value.constant;
}
case ftBool: {
- return field.IsOptional() ? "None"
- : field.value.constant == "0" ? "false" : "true";
+ return field.value.constant == "0" ? "false" : "true";
}
case ftUnionKey:
case ftEnumKey: {
- if (field.IsOptional()) { return "None"; }
auto ev = field.value.type.enum_def->FindByValue(field.value.constant);
if (!ev) return "Default::default()"; // Bitflags enum.
return WrapInNameSpace(field.value.type.enum_def->defined_namespace,
GetEnumValue(*field.value.type.enum_def, *ev));
}
-
- // All pointer-ish types have a default value of None, because they are
- // wrapped in Option.
- default: {
- return "None";
+ case ftUnionValue: {
+ return ObjectFieldType(field, true) + "::NONE";
+ }
+ case ftString: {
+ // Required strings.
+ return "String::new()"; // No default strings yet.
+ }
+ case ftVectorOfBool:
+ case ftVectorOfFloat:
+ case ftVectorOfInteger:
+ case ftVectorOfString:
+ case ftVectorOfStruct:
+ case ftVectorOfTable:
+ case ftVectorOfEnumKey:
+ case ftVectorOfUnionValue: {
+ // Required vectors.
+ return "Vec::new()"; // No default strings yet.
+ }
+ case ftStruct:
+ case ftTable: {
+ // Required struct/tables.
+ return "Default::default()"; // punt.
}
}
+ FLATBUFFERS_ASSERT("Unreachable.");
+ return "INVALID_CODE_GENERATION";
}
// Create the return type for fields in the *BuilderArgs structs that are
case ftFloat: {
const auto typname = GetTypeBasic(field.value.type);
return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
- : "self.fbb_.push_slot::<") +
+ : "self.fbb_.push_slot::<") +
typname + ">";
}
case ftEnumKey:
case ftUnionKey: {
const auto underlying_typname = GetTypeBasic(type);
return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
- : "self.fbb_.push_slot::<") +
+ : "self.fbb_.push_slot::<") +
underlying_typname + ">";
}
// Default-y fields (scalars so far) are neither optional nor required.
const std::string default_value =
!(field.IsOptional() || field.IsRequired())
- ? "Some(" + GetDefaultScalarValue(field) + ")"
+ ? "Some(" + GetDefaultValue(field, /*builder=*/true) + ")"
: "None";
const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
code_.SetValue("FIELD_NAME", Name(field));
- code_.SetValue("DEFAULT_VALUE", GetDefaultScalarValue(field));
+ code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, /*builder=*/true));
cb(field);
};
const auto &fields = struct_def.fields.vec;
code_ += " fn default() -> Self {";
code_ += " {{STRUCT_NAME}}Args {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
- code_ += " {{FIELD_NAME}}: {{DEFAULT_VALUE}},\\";
+ code_ += " {{FIELD_NAME}}: {{BLDR_DEF_VAL}},\\";
code_ += field.IsRequired() ? " // required field" : "";
});
code_ += " }";
if (is_scalar && !field.IsOptional()) {
code_ +=
" {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
- "{{DEFAULT_VALUE}});";
+ "{{BLDR_DEF_VAL}});";
} else {
code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
}
// Generate the native object.
code_ += "#[non_exhaustive]";
- code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
+ code_ += "#[derive(Debug, Clone, PartialEq)]";
code_ += "pub struct {{OBJECT_NAME}} {";
ForAllObjectTableFields(table, [&](const FieldDef &field) {
// Union objects combine both the union discriminant and value, so we
});
code_ += "}";
+ code_ += "impl Default for {{OBJECT_NAME}} {";
+ code_ += " fn default() -> Self {";
+ code_ += " Self {";
+ ForAllObjectTableFields(table, [&](const FieldDef &field) {
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
+ std::string default_value = GetDefaultValue(field, /*builder=*/false);
+ code_ += " {{FIELD_NAME}}: " + default_value + ",";
+ });
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
// TODO(cneo): Generate defaults for Native tables. However, since structs
// may be required, they, and therefore enums need defaults.
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct InParentNamespaceT {
}
+impl Default for InParentNamespaceT {
+ fn default() -> Self {
+ Self {
+ }
+ }
+}
impl InParentNamespaceT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct MonsterT {
}
+impl Default for MonsterT {
+ fn default() -> Self {
+ Self {
+ }
+ }
+}
impl MonsterT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TestSimpleTableWithEnumT {
pub color: Color,
}
+impl Default for TestSimpleTableWithEnumT {
+ fn default() -> Self {
+ Self {
+ color: Color::Green,
+ }
+ }
+}
impl TestSimpleTableWithEnumT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct StatT {
pub id: Option<String>,
pub val: i64,
pub count: u16,
}
+impl Default for StatT {
+ fn default() -> Self {
+ Self {
+ id: None,
+ val: 0,
+ count: 0,
+ }
+ }
+}
impl StatT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct ReferrableT {
pub id: u64,
}
+impl Default for ReferrableT {
+ fn default() -> Self {
+ Self {
+ id: 0,
+ }
+ }
+}
impl ReferrableT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct MonsterT {
pub pos: Option<Vec3T>,
pub mana: i16,
pub testrequirednestedflatbuffer: Option<Vec<u8>>,
pub scalar_key_sorted_tables: Option<Vec<StatT>>,
}
+impl Default for MonsterT {
+ fn default() -> Self {
+ Self {
+ pos: None,
+ mana: 150,
+ hp: 100,
+ name: String::new(),
+ inventory: None,
+ color: Color::Blue,
+ test: AnyT::NONE,
+ test4: None,
+ testarrayofstring: None,
+ testarrayoftables: None,
+ enemy: None,
+ testnestedflatbuffer: None,
+ testempty: None,
+ testbool: false,
+ testhashs32_fnv1: 0,
+ testhashu32_fnv1: 0,
+ testhashs64_fnv1: 0,
+ testhashu64_fnv1: 0,
+ testhashs32_fnv1a: 0,
+ testhashu32_fnv1a: 0,
+ testhashs64_fnv1a: 0,
+ testhashu64_fnv1a: 0,
+ testarrayofbools: None,
+ testf: 3.14159,
+ testf2: 3.0,
+ testf3: 0.0,
+ testarrayofstring2: None,
+ testarrayofsortedstruct: None,
+ flex: None,
+ test5: None,
+ vector_of_longs: None,
+ vector_of_doubles: None,
+ parent_namespace_test: None,
+ vector_of_referrables: None,
+ single_weak_reference: 0,
+ vector_of_weak_references: None,
+ vector_of_strong_referrables: None,
+ co_owning_reference: 0,
+ vector_of_co_owning_references: None,
+ non_owning_reference: 0,
+ vector_of_non_owning_references: None,
+ any_unique: AnyUniqueAliasesT::NONE,
+ any_ambiguous: AnyAmbiguousAliasesT::NONE,
+ vector_of_enums: None,
+ signed_enum: Race::None,
+ testrequirednestedflatbuffer: None,
+ scalar_key_sorted_tables: None,
+ }
+ }
+}
impl MonsterT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TypeAliasesT {
pub i8_: i8,
pub u8_: u8,
pub v8: Option<Vec<i8>>,
pub vf64: Option<Vec<f64>>,
}
+impl Default for TypeAliasesT {
+ fn default() -> Self {
+ Self {
+ i8_: 0,
+ u8_: 0,
+ i16_: 0,
+ u16_: 0,
+ i32_: 0,
+ u32_: 0,
+ i64_: 0,
+ u64_: 0,
+ f32_: 0.0,
+ f64_: 0.0,
+ v8: None,
+ vf64: None,
+ }
+ }
+}
impl TypeAliasesT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TableInNestedNST {
pub foo: i32,
}
+impl Default for TableInNestedNST {
+ fn default() -> Self {
+ Self {
+ foo: 0,
+ }
+ }
+}
impl TableInNestedNST {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TableInNestedNST {
pub foo: i32,
}
+impl Default for TableInNestedNST {
+ fn default() -> Self {
+ Self {
+ foo: 0,
+ }
+ }
+}
impl TableInNestedNST {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TableInFirstNST {
pub foo_table: Option<Box<namespace_b::TableInNestedNST>>,
pub foo_enum: namespace_b::EnumInNestedNS,
pub foo_union: namespace_b::UnionInNestedNST,
pub foo_struct: Option<namespace_b::StructInNestedNST>,
}
+impl Default for TableInFirstNST {
+ fn default() -> Self {
+ Self {
+ foo_table: None,
+ foo_enum: namespace_b::EnumInNestedNS::A,
+ foo_union: namespace_b::UnionInNestedNST::NONE,
+ foo_struct: None,
+ }
+ }
+}
impl TableInFirstNST {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct SecondTableInAT {
pub refer_to_c: Option<Box<super::namespace_c::TableInCT>>,
}
+impl Default for SecondTableInAT {
+ fn default() -> Self {
+ Self {
+ refer_to_c: None,
+ }
+ }
+}
impl SecondTableInAT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct TableInCT {
pub refer_to_a1: Option<Box<super::namespace_a::TableInFirstNST>>,
pub refer_to_a2: Option<Box<super::namespace_a::SecondTableInAT>>,
}
+impl Default for TableInCT {
+ fn default() -> Self {
+ Self {
+ refer_to_a1: None,
+ refer_to_a2: None,
+ }
+ }
+}
impl TableInCT {
pub fn pack<'b>(
&self,
}
}
#[non_exhaustive]
-#[derive(Debug, Clone, PartialEq, Default)]
+#[derive(Debug, Clone, PartialEq)]
pub struct ScalarStuffT {
pub just_i8: i8,
pub maybe_i8: Option<i8>,
pub maybe_enum: Option<OptionalByte>,
pub default_enum: OptionalByte,
}
+impl Default for ScalarStuffT {
+ fn default() -> Self {
+ Self {
+ just_i8: 0,
+ maybe_i8: None,
+ default_i8: 42,
+ just_u8: 0,
+ maybe_u8: None,
+ default_u8: 42,
+ just_i16: 0,
+ maybe_i16: None,
+ default_i16: 42,
+ just_u16: 0,
+ maybe_u16: None,
+ default_u16: 42,
+ just_i32: 0,
+ maybe_i32: None,
+ default_i32: 42,
+ just_u32: 0,
+ maybe_u32: None,
+ default_u32: 42,
+ just_i64: 0,
+ maybe_i64: None,
+ default_i64: 42,
+ just_u64: 0,
+ maybe_u64: None,
+ default_u64: 42,
+ just_f32: 0.0,
+ maybe_f32: None,
+ default_f32: 42.0,
+ just_f64: 0.0,
+ maybe_f64: None,
+ default_f64: 42.0,
+ just_bool: false,
+ maybe_bool: None,
+ default_bool: true,
+ just_enum: OptionalByte::None,
+ maybe_enum: None,
+ default_enum: OptionalByte::One,
+ }
+ }
+}
impl ScalarStuffT {
pub fn pack<'b>(
&self,
assert!(check_is_some!(none).is_err());
}
+#[test]
+fn object_api_defaults() {
+ use my_game::example::*;
+ assert_eq!(
+ Vec3T::default(), Vec3T {
+ x: 0.0,
+ y: 0.0,
+ z: 0.0,
+ test1: 0.0,
+ test2: Color::empty(),
+ test3: TestT {
+ a: 0,
+ b: 0
+ }
+ });
+ assert_eq!(
+ MonsterT::default(),
+ MonsterT {
+ pos: None,
+ hp: 100,
+ mana: 150,
+ name: String::new(), // required string => default is empty string.
+ color: Color::Blue,
+ inventory: None,
+ testarrayoftables: None,
+ testarrayofstring: None,
+ testarrayofstring2: None,
+ testarrayofbools: None,
+ testarrayofsortedstruct: None,
+ enemy: None,
+ test: AnyT::NONE,
+ test4: None,
+ test5: None,
+ testnestedflatbuffer: None,
+ testempty: None,
+ testbool: false,
+ testhashs32_fnv1: 0,
+ testhashu32_fnv1: 0,
+ testhashs64_fnv1: 0,
+ testhashu64_fnv1: 0,
+ testhashs32_fnv1a: 0,
+ testhashu32_fnv1a: 0,
+ testhashs64_fnv1a: 0,
+ testhashu64_fnv1a: 0,
+ testf: 3.14159,
+ testf2: 3.0,
+ testf3: 0.0,
+ flex: None,
+ vector_of_longs: None,
+ vector_of_doubles: None,
+ parent_namespace_test: None,
+ vector_of_referrables: None,
+ single_weak_reference: 0,
+ vector_of_weak_references: None,
+ vector_of_strong_referrables: None,
+ co_owning_reference: 0,
+ vector_of_co_owning_references: None,
+ non_owning_reference: 0,
+ vector_of_non_owning_references: None,
+ any_unique: AnyUniqueAliasesT::NONE,
+ any_ambiguous: AnyAmbiguousAliasesT::NONE,
+ vector_of_enums: None,
+ signed_enum: Race::None,
+ testrequirednestedflatbuffer: None, // despite the name, it is not required.
+ scalar_key_sorted_tables: None,
+ }
+ );
+}
fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
let mon = {
OptionalByte::None,
OptionalByte::One
);
+
+#[test]
+fn object_api_defaults() {
+ assert_eq!(
+ ScalarStuffT::default(),
+ ScalarStuffT {
+ just_i8: 0,
+ maybe_i8: None,
+ default_i8: 42,
+ just_u8: 0,
+ maybe_u8: None,
+ default_u8: 42,
+
+ just_i16: 0,
+ maybe_i16: None,
+ default_i16: 42,
+ just_u16: 0,
+ maybe_u16: None,
+ default_u16: 42,
+
+ just_i32: 0,
+ maybe_i32: None,
+ default_i32: 42,
+ just_u32: 0,
+ maybe_u32: None,
+ default_u32: 42,
+
+ just_i64: 0,
+ maybe_i64: None,
+ default_i64: 42,
+ just_u64: 0,
+ maybe_u64: None,
+ default_u64: 42,
+
+ just_f32: 0.0,
+ maybe_f32: None,
+ default_f32: 42.0,
+ just_f64: 0.0,
+ maybe_f64: None,
+ default_f64: 42.0,
+
+ just_bool: false,
+ maybe_bool: None,
+ default_bool: true,
+
+ just_enum: OptionalByte::None,
+ maybe_enum: None,
+ default_enum: OptionalByte::One,
+
+ }
+ );
+}