mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-30 23:01:37 +00:00
Refactor idl_gen_rust (#6206)
* Refactor idl_gen_rust to a ForAllX continuation pattern. * Updated rust sample code Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
@@ -26,37 +26,50 @@ pub mod sample {
|
|||||||
extern crate flatbuffers;
|
extern crate flatbuffers;
|
||||||
use self::flatbuffers::EndianScalar;
|
use self::flatbuffers::EndianScalar;
|
||||||
|
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
|
pub const ENUM_MIN_COLOR: i8 = 0;
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
|
pub const ENUM_MAX_COLOR: i8 = 2;
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub const ENUM_VALUES_COLOR: [Color; 3] = [
|
||||||
|
Color::Red,
|
||||||
|
Color::Green,
|
||||||
|
Color::Blue,
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct Color(pub i8);
|
pub struct Color(pub i8);
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl Color {
|
impl Color {
|
||||||
pub const ENUM_MIN: i8 = 0;
|
|
||||||
pub const ENUM_MAX: i8 = 2;
|
|
||||||
pub const Red: Self = Self(0);
|
pub const Red: Self = Self(0);
|
||||||
pub const Green: Self = Self(1);
|
pub const Green: Self = Self(1);
|
||||||
pub const Blue: Self = Self(2);
|
pub const Blue: Self = Self(2);
|
||||||
|
|
||||||
|
pub const ENUM_MIN: i8 = 0;
|
||||||
|
pub const ENUM_MAX: i8 = 2;
|
||||||
pub const ENUM_VALUES: &'static [Self] = &[
|
pub const ENUM_VALUES: &'static [Self] = &[
|
||||||
Self::Red,
|
Self::Red,
|
||||||
Self::Green,
|
Self::Green,
|
||||||
Self::Blue,
|
Self::Blue,
|
||||||
];
|
];
|
||||||
/// Returns the variant's name or "" if unknown.
|
/// Returns the variant's name or "" if unknown.
|
||||||
pub fn variant_name(self) -> &'static str {
|
pub fn variant_name(self) -> Option<&'static str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Red => "Red",
|
Self::Red => Some("Red"),
|
||||||
Self::Green => "Green",
|
Self::Green => Some("Green"),
|
||||||
Self::Blue => "Blue",
|
Self::Blue => Some("Blue"),
|
||||||
_ => "",
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Debug for Color {
|
impl std::fmt::Debug for Color {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let name = self.variant_name();
|
if let Some(name) = self.variant_name() {
|
||||||
if name.is_empty() {
|
|
||||||
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
|
|
||||||
} else {
|
|
||||||
f.write_str(name)
|
f.write_str(name)
|
||||||
|
} else {
|
||||||
|
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,41 +100,46 @@ impl flatbuffers::EndianScalar for Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
|
pub const ENUM_MIN_EQUIPMENT: u8 = 0;
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
|
pub const ENUM_MAX_EQUIPMENT: u8 = 1;
|
||||||
|
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub const ENUM_VALUES_COLOR: [Color; 3] = [
|
pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [
|
||||||
Color::Red,
|
Equipment::NONE,
|
||||||
Color::Green,
|
Equipment::Weapon,
|
||||||
Color::Blue
|
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct Equipment(pub u8);
|
pub struct Equipment(pub u8);
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
impl Equipment {
|
impl Equipment {
|
||||||
pub const ENUM_MIN: u8 = 0;
|
|
||||||
pub const ENUM_MAX: u8 = 1;
|
|
||||||
pub const NONE: Self = Self(0);
|
pub const NONE: Self = Self(0);
|
||||||
pub const Weapon: Self = Self(1);
|
pub const Weapon: Self = Self(1);
|
||||||
|
|
||||||
|
pub const ENUM_MIN: u8 = 0;
|
||||||
|
pub const ENUM_MAX: u8 = 1;
|
||||||
pub const ENUM_VALUES: &'static [Self] = &[
|
pub const ENUM_VALUES: &'static [Self] = &[
|
||||||
Self::NONE,
|
Self::NONE,
|
||||||
Self::Weapon,
|
Self::Weapon,
|
||||||
];
|
];
|
||||||
/// Returns the variant's name or "" if unknown.
|
/// Returns the variant's name or "" if unknown.
|
||||||
pub fn variant_name(self) -> &'static str {
|
pub fn variant_name(self) -> Option<&'static str> {
|
||||||
match self {
|
match self {
|
||||||
Self::NONE => "NONE",
|
Self::NONE => Some("NONE"),
|
||||||
Self::Weapon => "Weapon",
|
Self::Weapon => Some("Weapon"),
|
||||||
_ => "",
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Debug for Equipment {
|
impl std::fmt::Debug for Equipment {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let name = self.variant_name();
|
if let Some(name) = self.variant_name() {
|
||||||
if name.is_empty() {
|
|
||||||
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
|
|
||||||
} else {
|
|
||||||
f.write_str(name)
|
f.write_str(name)
|
||||||
|
} else {
|
||||||
|
f.write_fmt(format_args!("<UNKNOWN {:?}>", self.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,12 +170,6 @@ impl flatbuffers::EndianScalar for Equipment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub const ENUM_VALUES_EQUIPMENT: [Equipment; 2] = [
|
|
||||||
Equipment::NONE,
|
|
||||||
Equipment::Weapon
|
|
||||||
];
|
|
||||||
|
|
||||||
pub struct EquipmentUnionTableOffset {}
|
pub struct EquipmentUnionTableOffset {}
|
||||||
// struct Vec3, aligned to 4
|
// struct Vec3, aligned to 4
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
|
|||||||
@@ -344,27 +344,6 @@ class RustGenerator : public BaseGenerator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if a Type needs to be copied (for endian safety) when used in a
|
|
||||||
// Struct.
|
|
||||||
bool StructMemberAccessNeedsCopy(const Type &type) const {
|
|
||||||
switch (GetFullType(type)) {
|
|
||||||
case ftInteger: // requires endian swap
|
|
||||||
case ftFloat: // requires endian swap
|
|
||||||
case ftBool: // no endian-swap, but do the copy for UX consistency
|
|
||||||
case ftEnumKey: {
|
|
||||||
return true;
|
|
||||||
} // requires endian swap
|
|
||||||
case ftStruct: {
|
|
||||||
return false;
|
|
||||||
} // no endian swap
|
|
||||||
default: {
|
|
||||||
// logic error: no other types can be struct members.
|
|
||||||
FLATBUFFERS_ASSERT(false && "invalid struct member type");
|
|
||||||
return false; // only to satisfy compiler's return analysis
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EscapeKeyword(const std::string &name) const {
|
std::string EscapeKeyword(const std::string &name) const {
|
||||||
return keywords_.find(name) == keywords_.end() ? name : name + "_";
|
return keywords_.find(name) == keywords_.end() ? name : name + "_";
|
||||||
}
|
}
|
||||||
@@ -828,25 +807,6 @@ class RustGenerator : public BaseGenerator {
|
|||||||
return "INVALID_CODE_GENERATION"; // for return analysis
|
return "INVALID_CODE_GENERATION"; // for return analysis
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TableBuilderArgsDefaultValue(const FieldDef &field) {
|
|
||||||
return GetDefaultScalarValue(field);
|
|
||||||
}
|
|
||||||
std::string TableBuilderAddFuncDefaultValue(const FieldDef &field) {
|
|
||||||
// All branches of switch do the same action!
|
|
||||||
switch (GetFullType(field.value.type)) {
|
|
||||||
case ftUnionKey:
|
|
||||||
case ftEnumKey: {
|
|
||||||
const std::string basetype =
|
|
||||||
GetTypeBasic(field.value.type); //<- never used
|
|
||||||
return GetDefaultScalarValue(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return GetDefaultScalarValue(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TableBuilderArgsAddFuncType(const FieldDef &field,
|
std::string TableBuilderArgsAddFuncType(const FieldDef &field,
|
||||||
const std::string &lifetime) {
|
const std::string &lifetime) {
|
||||||
const Type &type = field.value.type;
|
const Type &type = field.value.type;
|
||||||
@@ -1177,6 +1137,47 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "";
|
code_ += "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ForAllUnionVariantsBesidesNone(
|
||||||
|
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;
|
||||||
|
// 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",
|
||||||
|
WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
|
||||||
|
ev.union_type.struct_def->name));
|
||||||
|
code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(ev)));
|
||||||
|
cb(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 FieldDef& field) {
|
||||||
|
if (field.deprecated) return;
|
||||||
|
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));
|
||||||
|
cb(field);
|
||||||
|
};
|
||||||
|
const auto &fields = struct_def.fields.vec;
|
||||||
|
if (reversed) {
|
||||||
|
for (auto it = fields.rbegin(); it != fields.rend(); ++it) go(**it);
|
||||||
|
} else {
|
||||||
|
for (auto it = fields.begin(); it != fields.end(); ++it) go(**it);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Generate an accessor struct, builder struct, and create function for a
|
// Generate an accessor struct, builder struct, and create function for a
|
||||||
// table.
|
// table.
|
||||||
void GenTable(const StructDef &struct_def) {
|
void GenTable(const StructDef &struct_def) {
|
||||||
@@ -1236,45 +1237,29 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += " let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);";
|
code_ += " let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);";
|
||||||
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
|
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
|
||||||
size; size /= 2) {
|
size; size /= 2) {
|
||||||
for (auto it = struct_def.fields.vec.rbegin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.rend(); ++it) {
|
if (struct_def.sortbysize && size != SizeOf(field.value.type.base_type))
|
||||||
const auto &field = **it;
|
return;
|
||||||
// TODO(rw): fully understand this sortbysize usage
|
if (TableFieldReturnsOption(field)) {
|
||||||
if (!field.deprecated && (!struct_def.sortbysize ||
|
code_ +=
|
||||||
size == SizeOf(field.value.type.base_type))) {
|
" if let Some(x) = args.{{FIELD_NAME}} "
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
"{ builder.add_{{FIELD_NAME}}(x); }";
|
||||||
if (TableFieldReturnsOption(field)) {
|
} else {
|
||||||
code_ +=
|
code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
|
||||||
" 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_ += " builder.finish()";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
// Generate field id constants.
|
// Generate field id constants.
|
||||||
if (struct_def.fields.vec.size() > 0) {
|
ForAllTableFields(struct_def, [&](const FieldDef &unused){
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
(void) unused;
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
code_ += " pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
|
||||||
const auto &field = **it;
|
"{{OFFSET_VALUE}};";
|
||||||
if (field.deprecated) {
|
});
|
||||||
// Deprecated fields won't be accessible.
|
if (struct_def.fields.vec.size() > 0) code_ += "";
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
|
|
||||||
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
|
|
||||||
code_ +=
|
|
||||||
" pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
|
|
||||||
"{{OFFSET_VALUE}};";
|
|
||||||
}
|
|
||||||
code_ += "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the accessors. Each has one of two forms:
|
// Generate the accessors. Each has one of two forms:
|
||||||
//
|
//
|
||||||
@@ -1288,21 +1273,13 @@ class RustGenerator : public BaseGenerator {
|
|||||||
// self._tab.get::<internal_type>(offset, defaultval).unwrap()
|
// self._tab.get::<internal_type>(offset, defaultval).unwrap()
|
||||||
// }
|
// }
|
||||||
const auto offset_prefix = Name(struct_def);
|
const auto offset_prefix = Name(struct_def);
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
|
||||||
const auto &field = **it;
|
|
||||||
if (field.deprecated) {
|
|
||||||
// Deprecated fields won't be accessible.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
|
||||||
code_.SetValue("RETURN_TYPE",
|
code_.SetValue("RETURN_TYPE",
|
||||||
GenTableAccessorFuncReturnType(field, "'a"));
|
GenTableAccessorFuncReturnType(field, "'a"));
|
||||||
code_.SetValue("FUNC_BODY",
|
code_.SetValue("FUNC_BODY",
|
||||||
GenTableAccessorFuncBody(field, "'a", offset_prefix));
|
GenTableAccessorFuncBody(field, "'a", offset_prefix));
|
||||||
|
|
||||||
GenComment(field.doc_comment, " ");
|
this->GenComment(field.doc_comment, " ");
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
|
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
|
||||||
code_ += " {{FUNC_BODY}}";
|
code_ += " {{FUNC_BODY}}";
|
||||||
@@ -1334,35 +1311,15 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += " })";
|
code_ += " })";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Explicit specializations for union accessors
|
// Explicit specializations for union accessors
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
if (field.value.type.base_type != BASE_TYPE_UNION) return;
|
||||||
const auto &field = **it;
|
|
||||||
if (field.deprecated || field.value.type.base_type != BASE_TYPE_UNION) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto u = field.value.type.enum_def;
|
|
||||||
|
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
|
||||||
code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
|
code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
|
||||||
|
ForAllUnionVariantsBesidesNone(
|
||||||
for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
|
*field.value.type.enum_def, [&](const EnumVal &unused){
|
||||||
auto &ev = **u_it;
|
(void) unused;
|
||||||
if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
|
|
||||||
|
|
||||||
auto table_init_type =
|
|
||||||
WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
|
|
||||||
ev.union_type.struct_def->name);
|
|
||||||
|
|
||||||
code_.SetValue(
|
|
||||||
"U_ELEMENT_ENUM_TYPE",
|
|
||||||
WrapInNameSpace(u->defined_namespace, GetEnumValue(*u, ev)));
|
|
||||||
code_.SetValue("U_ELEMENT_TABLE_TYPE", table_init_type);
|
|
||||||
code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(ev)));
|
|
||||||
|
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " #[allow(non_snake_case)]";
|
code_ += " #[allow(non_snake_case)]";
|
||||||
code_ +=
|
code_ +=
|
||||||
@@ -1398,9 +1355,9 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
code_ += "}"; // End of table impl.
|
code_ += "}"; // End of table impl.
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
@@ -1408,15 +1365,10 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_.SetValue("MAYBE_LT",
|
code_.SetValue("MAYBE_LT",
|
||||||
TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
|
TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
|
||||||
code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
|
code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
|
||||||
const auto &field = **it;
|
code_ += " pub {{FIELD_NAME}}: {{PARAM_TYPE}},";
|
||||||
if (!field.deprecated) {
|
});
|
||||||
code_.SetValue("PARAM_NAME", Name(field));
|
|
||||||
code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
|
|
||||||
code_ += " pub {{PARAM_NAME}}: {{PARAM_TYPE}},";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
|
|
||||||
// Generate an impl of Default for the *Args type:
|
// Generate an impl of Default for the *Args type:
|
||||||
@@ -1424,16 +1376,10 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
code_ += " fn default() -> Self {";
|
code_ += " fn default() -> Self {";
|
||||||
code_ += " {{STRUCT_NAME}}Args {";
|
code_ += " {{STRUCT_NAME}}Args {";
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
code_ += " {{FIELD_NAME}}: {{DEFAULT_VALUE}},\\";
|
||||||
const auto &field = **it;
|
code_ += field.required ? " // required field" : "";
|
||||||
if (!field.deprecated) {
|
});
|
||||||
code_.SetValue("PARAM_VALUE", TableBuilderArgsDefaultValue(field));
|
|
||||||
code_.SetValue("REQ", field.required ? " // required field" : "");
|
|
||||||
code_.SetValue("PARAM_NAME", Name(field));
|
|
||||||
code_ += " {{PARAM_NAME}}: {{PARAM_VALUE}},{{REQ}}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
@@ -1448,44 +1394,35 @@ class RustGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Generate builder functions:
|
// Generate builder functions:
|
||||||
code_ += "impl<'a: 'b, 'b> {{STRUCT_NAME}}Builder<'a, 'b> {";
|
code_ += "impl<'a: 'b, 'b> {{STRUCT_NAME}}Builder<'a, 'b> {";
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
const bool is_scalar = IsScalar(field.value.type.base_type);
|
||||||
const auto &field = **it;
|
std::string offset = GetFieldOffsetName(field);
|
||||||
if (!field.deprecated) {
|
// Generate functions to add data, which take one of two forms.
|
||||||
const bool is_scalar = IsScalar(field.value.type.base_type);
|
//
|
||||||
std::string offset = GetFieldOffsetName(field);
|
// If a value has a default:
|
||||||
|
// fn add_x(x_: type) {
|
||||||
// Generate functions to add data, which take one of two forms.
|
// fbb_.push_slot::<type>(offset, x_, Some(default));
|
||||||
//
|
// }
|
||||||
// If a value has a default:
|
//
|
||||||
// fn add_x(x_: type) {
|
// If a value does not have a default:
|
||||||
// fbb_.push_slot::<type>(offset, x_, Some(default));
|
// fn add_x(x_: type) {
|
||||||
// }
|
// fbb_.push_slot_always::<type>(offset, x_);
|
||||||
//
|
// }
|
||||||
// If a value does not have a default:
|
code_.SetValue("FIELD_OFFSET", Name(struct_def) + "::" + offset);
|
||||||
// fn add_x(x_: type) {
|
code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
|
||||||
// fbb_.push_slot_always::<type>(offset, x_);
|
code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
|
||||||
// }
|
code_ += " #[inline]";
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
code_ += " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
|
||||||
code_.SetValue("FIELD_OFFSET", Name(struct_def) + "::" + offset);
|
"{{FIELD_TYPE}}) {";
|
||||||
code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
|
if (is_scalar && !field.optional) {
|
||||||
code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
|
|
||||||
code_ += " #[inline]";
|
|
||||||
code_ +=
|
code_ +=
|
||||||
" pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
|
" {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
|
||||||
"{{FIELD_TYPE}}) {";
|
"{{DEFAULT_VALUE}});";
|
||||||
if (is_scalar && !field.optional) {
|
} else {
|
||||||
code_.SetValue("FIELD_DEFAULT_VALUE",
|
code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
|
||||||
TableBuilderAddFuncDefaultValue(field));
|
|
||||||
code_ +=
|
|
||||||
" {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
|
|
||||||
"{{FIELD_DEFAULT_VALUE}});";
|
|
||||||
} else {
|
|
||||||
code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
|
|
||||||
}
|
|
||||||
code_ += " }";
|
|
||||||
}
|
}
|
||||||
}
|
code_ += " }";
|
||||||
|
});
|
||||||
|
|
||||||
// Struct initializer (all fields required);
|
// Struct initializer (all fields required);
|
||||||
code_ += " #[inline]";
|
code_ += " #[inline]";
|
||||||
@@ -1507,17 +1444,12 @@ class RustGenerator : public BaseGenerator {
|
|||||||
"flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {";
|
"flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {";
|
||||||
code_ += " let o = self.fbb_.end_table(self.start_);";
|
code_ += " let o = self.fbb_.end_table(self.start_);";
|
||||||
|
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllTableFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
if (!field.required) return;
|
||||||
const auto &field = **it;
|
code_ +=
|
||||||
if (!field.deprecated && field.required) {
|
" self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}},"
|
||||||
code_.SetValue("FIELD_NAME", MakeSnakeCase(Name(field)));
|
"\"{{FIELD_NAME}}\");";
|
||||||
code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
|
});
|
||||||
code_ +=
|
|
||||||
" self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}},"
|
|
||||||
"\"{{FIELD_NAME}}\");";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code_ += " flatbuffers::WIPOffset::new(o.value())";
|
code_ += " flatbuffers::WIPOffset::new(o.value())";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
@@ -1659,6 +1591,18 @@ class RustGenerator : public BaseGenerator {
|
|||||||
*code_ptr += "padding" + NumToString((*id)++) + "__: 0,";
|
*code_ptr += "padding" + NumToString((*id)++) + "__: 0,";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ForAllStructFields(
|
||||||
|
const StructDef &struct_def,
|
||||||
|
std::function<void(const FieldDef &field)> cb
|
||||||
|
) {
|
||||||
|
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_NAME", Name(field));
|
||||||
|
cb(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Generate an accessor struct with constructor for a flatbuffers struct.
|
// Generate an accessor struct with constructor for a flatbuffers struct.
|
||||||
void GenStruct(const StructDef &struct_def) {
|
void GenStruct(const StructDef &struct_def) {
|
||||||
// Generates manual padding and alignment.
|
// Generates manual padding and alignment.
|
||||||
@@ -1678,19 +1622,14 @@ class RustGenerator : public BaseGenerator {
|
|||||||
code_ += "pub struct {{STRUCT_NAME}} {";
|
code_ += "pub struct {{STRUCT_NAME}} {";
|
||||||
|
|
||||||
int padding_id = 0;
|
int padding_id = 0;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllStructFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
|
||||||
const auto &field = **it;
|
|
||||||
code_.SetValue("FIELD_TYPE", GetTypeGet(field.value.type));
|
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
|
||||||
code_ += " {{FIELD_NAME}}_: {{FIELD_TYPE}},";
|
code_ += " {{FIELD_NAME}}_: {{FIELD_TYPE}},";
|
||||||
|
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
std::string padding;
|
std::string padding;
|
||||||
GenPadding(field, &padding, &padding_id, PaddingDefinition);
|
GenPadding(field, &padding, &padding_id, PaddingDefinition);
|
||||||
code_ += padding;
|
code_ += padding;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
code_ += "} // pub struct {{STRUCT_NAME}}";
|
code_ += "} // pub struct {{STRUCT_NAME}}";
|
||||||
|
|
||||||
@@ -1742,44 +1681,34 @@ class RustGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Generate a constructor that takes all fields as arguments.
|
// Generate a constructor that takes all fields as arguments.
|
||||||
code_ += "impl {{STRUCT_NAME}} {";
|
code_ += "impl {{STRUCT_NAME}} {";
|
||||||
std::string arg_list;
|
// TODO(cneo): Stop generating args on one line. Make it simpler.
|
||||||
std::string init_list;
|
bool first_arg = true;
|
||||||
padding_id = 0;
|
code_ += " pub fn new(\\";
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllStructFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
if (first_arg) first_arg = false; else code_ += ", \\";
|
||||||
const auto &field = **it;
|
code_.SetValue("REF", IsStruct(field.value.type) ? "&" : "");
|
||||||
const auto member_name = Name(field) + "_";
|
code_ += "_{{FIELD_NAME}}: {{REF}}{{FIELD_TYPE}}\\";
|
||||||
const auto reference =
|
});
|
||||||
StructMemberAccessNeedsCopy(field.value.type) ? "" : "&";
|
code_ += ") -> Self {";
|
||||||
const auto arg_name = "_" + Name(field);
|
|
||||||
const auto arg_type = reference + GetTypeGet(field.value.type);
|
|
||||||
|
|
||||||
if (it != struct_def.fields.vec.begin()) { arg_list += ", "; }
|
|
||||||
arg_list += arg_name + ": ";
|
|
||||||
arg_list += arg_type;
|
|
||||||
init_list += " " + member_name;
|
|
||||||
if (StructMemberAccessNeedsCopy(field.value.type)) {
|
|
||||||
init_list += ": " + arg_name + ".to_little_endian(),\n";
|
|
||||||
} else {
|
|
||||||
init_list += ": *" + arg_name + ",\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code_.SetValue("ARG_LIST", arg_list);
|
|
||||||
code_.SetValue("INIT_LIST", init_list);
|
|
||||||
code_ += " pub fn new({{ARG_LIST}}) -> Self {";
|
|
||||||
code_ += " {{STRUCT_NAME}} {";
|
code_ += " {{STRUCT_NAME}} {";
|
||||||
code_ += "{{INIT_LIST}}";
|
|
||||||
|
ForAllStructFields(struct_def, [&](const FieldDef &field) {
|
||||||
|
const bool is_struct = IsStruct(field.value.type);
|
||||||
|
code_.SetValue("DEREF", is_struct ? "*" : "");
|
||||||
|
code_.SetValue("TO_LE", is_struct ? "" : ".to_little_endian()");
|
||||||
|
code_ += " {{FIELD_NAME}}_: {{DEREF}}_{{FIELD_NAME}}{{TO_LE}},";
|
||||||
|
});
|
||||||
|
code_ += "";
|
||||||
|
|
||||||
|
// TODO(cneo): Does this padding even work? Why after all the fields?
|
||||||
padding_id = 0;
|
padding_id = 0;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllStructFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
|
||||||
const auto &field = **it;
|
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
std::string padding;
|
std::string padding;
|
||||||
GenPadding(field, &padding, &padding_id, PaddingInitializer);
|
GenPadding(field, &padding, &padding_id, PaddingInitializer);
|
||||||
code_ += " " + padding;
|
code_ += " " + padding;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
|
|
||||||
@@ -1788,33 +1717,19 @@ class RustGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate accessor methods for the struct.
|
// Generate accessor methods for the struct.
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
ForAllStructFields(struct_def, [&](const FieldDef &field) {
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
const bool is_struct = IsStruct(field.value.type);
|
||||||
const auto &field = **it;
|
code_.SetValue("REF", is_struct ? "&" : "");
|
||||||
|
code_.SetValue("FROM_LE", is_struct ? "" : ".from_little_endian()");
|
||||||
|
|
||||||
auto field_type = TableBuilderArgsAddFuncType(field, "'a");
|
this->GenComment(field.doc_comment, " ");
|
||||||
auto member = "self." + Name(field) + "_";
|
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{REF}}{{FIELD_TYPE}} {";
|
||||||
auto value = StructMemberAccessNeedsCopy(field.value.type)
|
code_ += " {{REF}}self.{{FIELD_NAME}}_{{FROM_LE}}";
|
||||||
? member + ".from_little_endian()"
|
code_ += " }";
|
||||||
: member;
|
|
||||||
|
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
|
||||||
code_.SetValue("FIELD_TYPE", field_type);
|
|
||||||
code_.SetValue("FIELD_VALUE", value);
|
|
||||||
GenComment(field.doc_comment, " ");
|
|
||||||
if (IsStruct(field.value.type)) {
|
|
||||||
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
|
|
||||||
code_ += " &{{FIELD_VALUE}}";
|
|
||||||
code_ += " }";
|
|
||||||
} else {
|
|
||||||
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
|
|
||||||
code_ += " {{FIELD_VALUE}}";
|
|
||||||
code_ += " }";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a comparison function for this field if it is a key.
|
// Generate a comparison function for this field if it is a key.
|
||||||
if (field.key) { GenKeyFieldMethods(field); }
|
if (field.key) { GenKeyFieldMethods(field); }
|
||||||
}
|
});
|
||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user