Refactor idl_gen_rust and Rust generated code to use consistent whitespace (#6809)

* Remove dead code in idl_gen_rust

* Use 2space indentation in mod.rs

* use In/DecrementIdentValue in idl_gen_rust

Fix some whitespace too in generated code.

* make default fn 2space ident

* More 2space formatting

* git clang format

* make vs2015 happy

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2021-08-23 18:53:10 -04:00
committed by GitHub
parent 273f6084e5
commit f89e0b1a6c
42 changed files with 1904 additions and 1879 deletions

View File

@@ -182,31 +182,9 @@ FullType GetFullType(const Type &type) {
return ftBool;
}
// If the second parameter is false then wrap the first with Option<...>
std::string WrapInOptionIfNotRequired(std::string s, bool required) {
if (required) {
return s;
} else {
return "Option<" + s + ">";
}
}
// If the second parameter is false then add .unwrap()
std::string AddUnwrapIfRequired(std::string s, bool required) {
if (required) {
return s + ".unwrap()";
} else {
return s;
}
}
bool IsBitFlagsEnum(const EnumDef &enum_def) {
return enum_def.attributes.Lookup("bit_flags") != nullptr;
}
bool IsBitFlagsEnum(const FieldDef &field) {
EnumDef *ed = field.value.type.enum_def;
return ed && IsBitFlagsEnum(*ed);
}
// TableArgs make required non-scalars "Option<_>".
// TODO(cneo): Rework how we do defaults and stuff.
@@ -259,7 +237,7 @@ bool GenerateRustModuleRootFile(const Parser &parser,
it++) {
root_module.Insert(*it, parser.opts.filename_suffix);
}
CodeWriter code(" ");
CodeWriter code(" ");
// TODO(caspern): Move generated warning out of BaseGenerator.
code +=
"// Automatically generated by the Flatbuffers compiler. "
@@ -384,6 +362,7 @@ class RustGenerator : public BaseGenerator {
// clang-format on
};
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
code_.SetPadding(" ");
}
bool generate() {
@@ -639,9 +618,9 @@ class RustGenerator : public BaseGenerator {
// Generate a comment from the schema.
void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
std::string text;
::flatbuffers::GenComment(dc, &text, nullptr, prefix);
code_ += text + "\\";
for (auto it = dc.begin(); it != dc.end(); it++) {
code_ += std::string(prefix) + "///" + *it;
}
}
// Return a Rust type from the table in idl.h.
@@ -738,7 +717,9 @@ class RustGenerator : public BaseGenerator {
const auto &ev = **it;
code_.SetValue("VARIANT", Name(ev));
code_.SetValue("VALUE", enum_def.ToString(ev));
code_.IncrementIdentLevel();
cb(ev);
code_.DecrementIdentLevel();
}
}
void ForAllEnumValues(const EnumDef &enum_def, std::function<void()> cb) {
@@ -775,8 +756,8 @@ class RustGenerator : public BaseGenerator {
code_ += " #[derive(Default)]";
code_ += " pub struct {{ENUM_NAME}}: {{BASE_TYPE}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
this->GenComment(ev.doc_comment, " ");
code_ += " const {{VARIANT}} = {{VALUE}};";
this->GenComment(ev.doc_comment, " ");
code_ += " const {{VARIANT}} = {{VALUE}};";
});
code_ += " }";
code_ += " }";
@@ -806,7 +787,7 @@ class RustGenerator : public BaseGenerator {
code_ += "pub const ENUM_VALUES_{{ENUM_NAME_CAPS}}: [{{ENUM_NAME}}; " +
num_fields + "] = [";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
code_ += " " + GetEnumValue(enum_def, ev) + ",";
code_ += GetEnumValue(enum_def, ev) + ",";
});
code_ += "];";
code_ += "";
@@ -823,21 +804,21 @@ class RustGenerator : public BaseGenerator {
code_ += "#[allow(non_upper_case_globals)]";
code_ += "impl {{ENUM_NAME}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
this->GenComment(ev.doc_comment, " ");
code_ += " pub const {{VARIANT}}: Self = Self({{VALUE}});";
this->GenComment(ev.doc_comment);
code_ += "pub const {{VARIANT}}: Self = Self({{VALUE}});";
});
code_ += "";
// Generate Associated constants
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, [&]() {
code_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
code_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
});
code_ += " _ => None,";
code_ += " }";
@@ -933,7 +914,9 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(enum_val)));
code_.SetValue("U_ELEMENT_TABLE_TYPE",
NamespacedNativeName(*enum_val.union_type.struct_def));
code_.IncrementIdentLevel();
cb();
code_.DecrementIdentLevel();
}
}
void GenUnionObject(const EnumDef &enum_def) {
@@ -949,7 +932,7 @@ class RustGenerator : public BaseGenerator {
code_ += "pub enum {{NATIVE_NAME}} {";
code_ += " NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ += " {{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
code_ += "{{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
});
code_ += "}";
// Generate Default (NONE).
@@ -969,7 +952,7 @@ class RustGenerator : public BaseGenerator {
code_ += " Self::NONE => {{ENUM_NAME}}::NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ +=
" Self::{{NATIVE_VARIANT}}(_) => {{ENUM_NAME}}::"
" Self::{{NATIVE_VARIANT}}(_) => {{ENUM_NAME}}::"
"{{VARIANT_NAME}},";
});
code_ += " }";
@@ -982,9 +965,8 @@ class RustGenerator : public BaseGenerator {
code_ += " match self {";
code_ += " Self::NONE => None,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ +=
" Self::{{NATIVE_VARIANT}}(v) => "
"Some(v.pack(fbb).as_union_value()),";
code_ += " Self::{{NATIVE_VARIANT}}(v) => \\";
code_ += "Some(v.pack(fbb).as_union_value()),";
});
code_ += " }";
code_ += " }";
@@ -993,44 +975,44 @@ class RustGenerator : public BaseGenerator {
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
// Move accessor.
code_ +=
" /// If the union variant matches, return the owned "
"/// 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) -> "
"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_ += " 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_ += " None";
code_ += " unreachable!()";
code_ += " }";
code_ += " } else {";
code_ += " None";
code_ += " }";
code_ += "}";
// Immutable reference accessor.
code_ +=
" /// If the union variant matches, return a reference to the "
"/// If the union variant matches, return a reference to the "
"{{U_ELEMENT_TABLE_TYPE}}.";
code_ +=
" pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
"pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
"Option<&{{U_ELEMENT_TABLE_TYPE}}> {";
code_ +=
" if let Self::{{NATIVE_VARIANT}}(v) = self "
" if let Self::{{NATIVE_VARIANT}}(v) = self "
"{ Some(v.as_ref()) } else { None }";
code_ += " }";
code_ += "}";
// Mutable reference accessor.
code_ +=
" /// If the union variant matches, return a mutable reference"
"/// 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) -> "
"pub fn as_{{U_ELEMENT_NAME}}_mut(&mut self) -> "
"Option<&mut {{U_ELEMENT_TABLE_TYPE}}> {";
code_ +=
" if let Self::{{NATIVE_VARIANT}}(v) = self "
" if let Self::{{NATIVE_VARIANT}}(v) = self "
"{ Some(v.as_mut()) } else { None }";
code_ += " }";
code_ += "}";
});
code_ += "}"; // End union methods impl.
}
@@ -1600,10 +1582,11 @@ class RustGenerator : public BaseGenerator {
// Generates a fully-qualified name getter for use with --gen-name-strings
void GenFullyQualifiedNameGetter(const StructDef &struct_def,
const std::string &name) {
code_ += " pub const fn get_fully_qualified_name() -> &'static str {";
code_ += " \"" +
struct_def.defined_namespace->GetFullyQualifiedName(name) + "\"";
code_ += " }";
const std::string fully_qualified_name =
struct_def.defined_namespace->GetFullyQualifiedName(name);
code_ += " pub const fn get_fully_qualified_name() -> &'static str {";
code_ += " \"" + fully_qualified_name + "\"";
code_ += " }";
code_ += "";
}
@@ -1639,7 +1622,9 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder));
code_.SetValue("DISCRIMINANT", UnionTypeFieldName(field));
code_.IncrementIdentLevel();
cb(field);
code_.DecrementIdentLevel();
};
const auto &fields = struct_def.fields.vec;
if (reversed) {
@@ -1668,41 +1653,47 @@ class RustGenerator : public BaseGenerator {
code_ += "}";
code_ += "";
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_NAME}}<'a> {";
code_ += " type Inner = {{STRUCT_NAME}}<'a>;";
code_ += " #[inline]";
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " Self { _tab: flatbuffers::Table { buf, loc } }";
code_ += " }";
code_ += " type Inner = {{STRUCT_NAME}}<'a>;";
code_ += " #[inline]";
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " Self { _tab: flatbuffers::Table { buf, loc } }";
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl<'a> {{STRUCT_NAME}}<'a> {";
// Generate field id constants.
ForAllTableFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
code_ +=
"pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
"{{OFFSET_VALUE}};";
});
code_ += "";
if (parser_.opts.generate_name_strings) {
GenFullyQualifiedNameGetter(struct_def, struct_def.name);
}
code_ += " #[inline]";
code_ += " #[inline]";
code_ +=
" pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
" pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
"Self {";
code_ += " {{STRUCT_NAME}} { _tab: table }";
code_ += " }";
code_ += " {{STRUCT_NAME}} { _tab: table }";
code_ += " }";
// Generate a convenient create* function that uses the above builder
// to create a table in one function call.
code_.SetValue("MAYBE_US", struct_def.fields.vec.size() == 0 ? "_" : "");
code_.SetValue("MAYBE_LT",
TableBuilderArgsNeedsLifetime(struct_def) ? "<'args>" : "");
code_ += " #[allow(unused_mut)]";
code_ += " pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(";
code_ +=
" _fbb: "
"&'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,";
code_ +=
" {{MAYBE_US}}args: &'args {{STRUCT_NAME}}Args{{MAYBE_LT}})"
" -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'bldr>> {";
code_ += " #[allow(unused_mut)]";
code_ += " pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(";
code_ += " _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,";
code_ += " {{MAYBE_US}}args: &'args {{STRUCT_NAME}}Args{{MAYBE_LT}}";
code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'bldr>> {";
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;
size; size /= 2) {
ForAllTableFields(
@@ -1713,23 +1704,23 @@ class RustGenerator : public BaseGenerator {
return;
if (IsOptionalToBuilder(field)) {
code_ +=
" if let Some(x) = args.{{FIELD_NAME}} "
" if let Some(x) = args.{{FIELD_NAME}} "
"{ builder.add_{{FIELD_NAME}}(x); }";
} else {
code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
}
},
/*reverse=*/true);
}
code_ += " builder.finish()";
code_ += " }";
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}} {";
code_ += " pub fn unpack(&self) -> {{OBJECT_NAME}} {";
ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
const Type &type = field.value.type;
switch (GetFullType(type)) {
@@ -1737,7 +1728,7 @@ class RustGenerator : public BaseGenerator {
case ftBool:
case ftFloat:
case ftEnumKey: {
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}();";
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}();";
return;
}
case ftUnionKey: return;
@@ -1746,27 +1737,22 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("ENUM_NAME", WrapInNameSpace(enum_def));
code_.SetValue("NATIVE_ENUM_NAME", NamespacedNativeName(enum_def));
code_ +=
" let {{FIELD_NAME}} = match "
"self.{{FIELD_NAME}}_type() {";
code_ +=
" {{ENUM_NAME}}::NONE =>"
" {{NATIVE_ENUM_NAME}}::NONE,";
" let {{FIELD_NAME}} = match self.{{FIELD_NAME}}_type() {";
code_ += " {{ENUM_NAME}}::NONE => {{NATIVE_ENUM_NAME}}::NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ +=
" {{ENUM_NAME}}::{{VARIANT_NAME}} => "
" {{ENUM_NAME}}::{{VARIANT_NAME}} => "
"{{NATIVE_ENUM_NAME}}::{{NATIVE_VARIANT}}(Box::new(";
code_ += " self.{{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}()";
code_ +=
" self.{{FIELD_NAME}}_as_"
"{{U_ELEMENT_NAME}}()";
code_ +=
" .expect(\"Invalid union table, "
" .expect(\"Invalid union table, "
"expected `{{ENUM_NAME}}::{{VARIANT_NAME}}`.\")";
code_ += " .unpack()";
code_ += " )),";
code_ += " .unpack()";
code_ += " )),";
});
// Maybe we shouldn't throw away unknown discriminants?
code_ += " _ => {{NATIVE_ENUM_NAME}}::NONE,";
code_ += " };";
code_ += " _ => {{NATIVE_ENUM_NAME}}::NONE,";
code_ += " };";
return;
}
// The rest of the types need special handling based on if the field
@@ -1821,32 +1807,25 @@ class RustGenerator : public BaseGenerator {
}
}
if (field.IsOptional()) {
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}().map(|x| {";
code_ += " {{EXPR}}";
code_ += " });";
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_ += " let {{FIELD_NAME}} = {";
code_ += " let x = self.{{FIELD_NAME}}();";
code_ += " {{EXPR}}";
code_ += " };";
}
});
code_ += " {{OBJECT_NAME}} {";
code_ += " {{OBJECT_NAME}} {";
ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
code_ += " {{FIELD_NAME}},";
code_ += " {{FIELD_NAME}},";
});
code_ += " }";
code_ += " }";
code_ += " }";
}
// Generate field id constants.
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_ += "";
// Generate the accessors. Each has one of two forms:
@@ -1864,11 +1843,11 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("RETURN_TYPE",
GenTableAccessorFuncReturnType(field, "'a"));
this->GenComment(field.doc_comment, " ");
code_ += " #[inline]";
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
code_ += " " + GenTableAccessorFuncBody(field, "'a");
code_ += " }";
this->GenComment(field.doc_comment);
code_ += "#[inline]";
code_ += "pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
code_ += " " + GenTableAccessorFuncBody(field, "'a");
code_ += "}";
// Generate a comparison function for this field if it is a key.
if (field.key) { GenKeyFieldMethods(field); }
@@ -1886,24 +1865,24 @@ 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.IsRequired()) {
code_ += "{{NESTED}}<'a> {";
code_ += " let data = self.{{FIELD_NAME}}();";
code_ += " let data = self.{{FIELD_NAME}}();";
code_ += " use flatbuffers::Follow;";
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)";
} else {
code_ += "Option<{{NESTED}}<'a>> {";
code_ += " self.{{FIELD_NAME}}().map(|data| {";
code_ += " use flatbuffers::Follow;";
code_ +=
" <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
"::follow(data, 0)";
code_ += " })";
code_ += " })";
}
code_ += " }";
code_ += "}";
}
});
@@ -1913,10 +1892,10 @@ class RustGenerator : public BaseGenerator {
ForAllUnionVariantsBesidesNone(
*field.value.type.enum_def, [&](const EnumVal &unused) {
(void)unused;
code_ += " #[inline]";
code_ += " #[allow(non_snake_case)]";
code_ += "#[inline]";
code_ += "#[allow(non_snake_case)]";
code_ +=
" pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> "
"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
@@ -1930,23 +1909,22 @@ class RustGenerator : public BaseGenerator {
//
// To avoid this problem the type field name is used unescaped here:
code_ +=
" if self.{{DISCRIMINANT}}() == {{U_ELEMENT_ENUM_TYPE}} {";
" if self.{{DISCRIMINANT}}() == {{U_ELEMENT_ENUM_TYPE}} {";
// The following logic is not tested in the integration test,
// as of April 10, 2020
if (field.IsRequired()) {
code_ += " let u = self.{{FIELD_NAME}}();";
code_ +=
" Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
code_ += " let u = self.{{FIELD_NAME}}();";
code_ += " Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
} else {
code_ +=
" self.{{FIELD_NAME}}().map("
" self.{{FIELD_NAME}}().map("
"{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
}
code_ += " } else {";
code_ += " None";
code_ += " }";
code_ += " } else {";
code_ += " None";
code_ += " }";
code_ += "}";
code_ += "";
});
});
@@ -1988,17 +1966,17 @@ class RustGenerator : public BaseGenerator {
"\"{{FIELD_NAME}}_type\", Self::{{UNION_TYPE_OFFSET_NAME}}, "
"\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
"|key, v, pos| {";
code_ += " match key {";
code_ += " match key {";
ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
(void)unused;
code_ +=
" {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
" {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
"<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
"\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
});
code_ += " _ => Ok(()),";
code_ += " }";
code_ += " })?\\";
code_ += " _ => Ok(()),";
code_ += " }";
code_ += " })?\\";
});
code_ += "\n .finish();";
code_ += " Ok(())";
@@ -2011,21 +1989,21 @@ class RustGenerator : public BaseGenerator {
code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
code_ += " pub {{FIELD_NAME}}: {{PARAM_TYPE}},";
code_ += " pub {{FIELD_NAME}}: {{PARAM_TYPE}},";
});
code_ += "}";
// Generate an impl of Default for the *Args type:
code_ += "impl<'a> Default for {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
code_ += " #[inline]";
code_ += " fn default() -> Self {";
code_ += " {{STRUCT_NAME}}Args {";
code_ += " #[inline]";
code_ += " fn default() -> Self {";
code_ += " {{STRUCT_NAME}}Args {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
code_ += " {{FIELD_NAME}}: {{BLDR_DEF_VAL}},\\";
code_ += " {{FIELD_NAME}}: {{BLDR_DEF_VAL}},\\";
code_ += field.IsRequired() ? " // required field" : "";
});
code_ += " }";
code_ += " }";
code_ += " }";
code_ += "}";
// Generate a builder struct:
@@ -2055,18 +2033,18 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("FIELD_OFFSET", Name(struct_def) + "::" + offset);
code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
code_ += " #[inline]";
code_ += "#[inline]";
code_ +=
" pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
"pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
"{{FIELD_TYPE}}) {";
if (is_scalar && !field.IsOptional()) {
code_ +=
" {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
" {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
"{{BLDR_DEF_VAL}});";
} else {
code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
}
code_ += " }";
code_ += "}";
});
// Struct initializer (all fields required);
@@ -2092,7 +2070,7 @@ class RustGenerator : public BaseGenerator {
ForAllTableFields(struct_def, [&](const FieldDef &field) {
if (!field.IsRequired()) return;
code_ +=
" self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}},"
" self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}},"
"\"{{FIELD_NAME}}\");";
});
code_ += " flatbuffers::WIPOffset::new(o.value())";
@@ -2113,30 +2091,29 @@ class RustGenerator : public BaseGenerator {
"&\"InvalidFlatbuffer: Union discriminant"
" does not match value.\"");
code_ += " match self.{{DISCRIMINANT}}() {";
code_ += " match self.{{DISCRIMINANT}}() {";
ForAllUnionVariantsBesidesNone(
*field.value.type.enum_def, [&](const EnumVal &unused) {
(void)unused;
code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
code_ +=
" if let Some(x) = "
" if let Some(x) = "
"self.{{FIELD_NAME}}_as_"
"{{U_ELEMENT_NAME}}() {";
code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
code_ += " } else {";
code_ +=
" ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
code_ += " }";
code_ += " },";
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)";
code_ += " },";
code_ += " };";
code_ += " _ => {";
code_ += " let x: Option<()> = None;";
code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
code_ += " },";
code_ += " };";
} else {
// Most fields.
code_ += " ds.field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}());";
code_ += " ds.field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}());";
}
});
code_ += " ds.finish()";
@@ -2156,7 +2133,7 @@ class RustGenerator : public BaseGenerator {
// 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_ += "pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
});
code_ += "}";
@@ -2166,7 +2143,7 @@ class RustGenerator : public BaseGenerator {
ForAllObjectTableFields(table, [&](const FieldDef &field) {
if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
std::string default_value = GetDefaultValue(field, kObject);
code_ += " {{FIELD_NAME}}: " + default_value + ",";
code_ += " {{FIELD_NAME}}: " + default_value + ",";
});
code_ += " }";
code_ += " }";
@@ -2190,7 +2167,7 @@ class RustGenerator : public BaseGenerator {
case ftBool:
case ftFloat:
case ftEnumKey: {
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}};";
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}};";
return;
}
case ftUnionKey: return; // Generate union type with union value.
@@ -2198,9 +2175,9 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("SNAKE_CASE_ENUM_NAME",
MakeSnakeCase(Name(*field.value.type.enum_def)));
code_ +=
" let {{FIELD_NAME}}_type = "
" let {{FIELD_NAME}}_type = "
"self.{{FIELD_NAME}}.{{SNAKE_CASE_ENUM_NAME}}_type();";
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.pack(_fbb);";
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.pack(_fbb);";
return;
}
// The rest of the types require special casing around optionalness
@@ -2213,14 +2190,13 @@ class RustGenerator : public BaseGenerator {
// Hold the struct in a variable so we can reference it.
if (field.IsRequired()) {
code_ +=
" let {{FIELD_NAME}}_tmp = "
"Some(self.{{FIELD_NAME}}.pack());";
" let {{FIELD_NAME}}_tmp = Some(self.{{FIELD_NAME}}.pack());";
} else {
code_ +=
" let {{FIELD_NAME}}_tmp = self.{{FIELD_NAME}}"
" let {{FIELD_NAME}}_tmp = self.{{FIELD_NAME}}"
".as_ref().map(|x| x.pack());";
}
code_ += " let {{FIELD_NAME}} = {{FIELD_NAME}}_tmp.as_ref();";
code_ += " let {{FIELD_NAME}} = {{FIELD_NAME}}_tmp.as_ref();";
return;
}
@@ -2274,7 +2250,7 @@ class RustGenerator : public BaseGenerator {
code_ += " {{STRUCT_NAME}}::create(_fbb, &{{STRUCT_NAME}}Args{";
ForAllObjectTableFields(table, [&](const FieldDef &field) {
(void)field; // Unused.
code_ += " {{FIELD_NAME}},";
code_ += " {{FIELD_NAME}},";
});
code_ += " })";
code_ += " }";
@@ -2288,21 +2264,23 @@ class RustGenerator : public BaseGenerator {
if (field.deprecated) continue;
code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("FIELD_OBJECT_TYPE", ObjectFieldType(field, true));
code_.IncrementIdentLevel();
cb(field);
code_.DecrementIdentLevel();
}
}
void MapNativeTableField(const FieldDef &field, const std::string &expr) {
if (field.IsOptional()) {
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.as_ref().map(|x|{";
code_ += " " + expr;
code_ += " });";
code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.as_ref().map(|x|{";
code_ += " " + expr;
code_ += " });";
} else {
// 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_ += " });";
code_ += " let {{FIELD_NAME}} = Some({";
code_ += " let x = &self.{{FIELD_NAME}};";
code_ += " " + expr;
code_ += " });";
}
}
@@ -2314,20 +2292,20 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
code_.SetValue("REF", IsString(field.value.type) ? "" : "&");
code_ += " #[inline]";
code_ += "#[inline]";
code_ +=
" pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> "
" bool {";
code_ += " self.{{FIELD_NAME}}() < o.{{FIELD_NAME}}()";
code_ += " }";
"pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> "
"bool {";
code_ += " self.{{FIELD_NAME}}() < o.{{FIELD_NAME}}()";
code_ += "}";
code_ += "";
code_ += " #[inline]";
code_ += "#[inline]";
code_ +=
" pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
" ::std::cmp::Ordering {";
code_ += " let key = self.{{FIELD_NAME}}();";
code_ += " key.cmp({{REF}}val)";
code_ += " }";
"pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
"::std::cmp::Ordering {";
code_ += " let key = self.{{FIELD_NAME}}();";
code_ += " key.cmp({{REF}}val)";
code_ += "}";
}
// Generate functions for accessing the root table object. This function
@@ -2553,7 +2531,9 @@ class RustGenerator : public BaseGenerator {
code_.SetValue(
"REF",
IsStruct(field.value.type) || IsArray(field.value.type) ? "&" : "");
code_.IncrementIdentLevel();
cb(field);
code_.DecrementIdentLevel();
const size_t size = InlineSize(field.value.type);
offset_to_field += size + field.padding;
}
@@ -2592,7 +2572,7 @@ class RustGenerator : public BaseGenerator {
code_ += " f.debug_struct(\"{{STRUCT_NAME}}\")";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
code_ += " .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
code_ += " .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
});
code_ += " .finish()";
code_ += " }";
@@ -2663,13 +2643,13 @@ class RustGenerator : public BaseGenerator {
code_ += " pub fn new(";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
code_ += " {{FIELD_NAME}}: {{REF}}{{FIELD_TYPE}},";
code_ += " {{FIELD_NAME}}: {{REF}}{{FIELD_TYPE}},";
});
code_ += " ) -> Self {";
code_ += " let mut s = Self([0; {{STRUCT_SIZE}}]);";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
code_ += " s.set_{{FIELD_NAME}}({{FIELD_NAME}});";
code_ += " s.set_{{FIELD_NAME}}({{FIELD_NAME}});";
});
code_ += " s";
code_ += " }";
@@ -2681,12 +2661,12 @@ class RustGenerator : public BaseGenerator {
// Generate accessor methods for the struct.
ForAllStructFields(struct_def, [&](const FieldDef &field) {
this->GenComment(field.doc_comment, " ");
this->GenComment(field.doc_comment);
// Getter.
if (IsStruct(field.value.type)) {
code_ += " pub fn {{FIELD_NAME}}(&self) -> &{{FIELD_TYPE}} {";
code_ += "pub fn {{FIELD_NAME}}(&self) -> &{{FIELD_TYPE}} {";
code_ +=
" unsafe {"
" unsafe {"
" &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
" {{FIELD_TYPE}}) }";
} else if (IsArray(field.value.type)) {
@@ -2694,31 +2674,31 @@ class RustGenerator : public BaseGenerator {
NumToString(field.value.type.fixed_length));
code_.SetValue("ARRAY_ITEM", GetTypeGet(field.value.type.VectorType()));
code_ +=
" pub fn {{FIELD_NAME}}(&'a self) -> "
"pub fn {{FIELD_NAME}}(&'a self) -> "
"flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
} else {
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
code_ += "pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
code_ +=
" let mut mem = core::mem::MaybeUninit::"
" let mut mem = core::mem::MaybeUninit::"
"<{{FIELD_TYPE}}>::uninit();";
code_ += " unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
code_ += " mem.as_mut_ptr() as *mut u8,";
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
code_ += " );";
code_ += " mem.assume_init()";
code_ += " }.from_little_endian()";
code_ += " unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
code_ += " mem.as_mut_ptr() as *mut u8,";
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
code_ += " );";
code_ += " mem.assume_init()";
code_ += " }.from_little_endian()";
}
code_ += " }\n";
code_ += "}\n";
// Setter.
if (IsStruct(field.value.type)) {
code_.SetValue("FIELD_SIZE", NumToString(InlineSize(field.value.type)));
code_ += " #[allow(clippy::identity_op)]"; // If FIELD_OFFSET=0.
code_ += " pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ += "#[allow(clippy::identity_op)]"; // If FIELD_OFFSET=0.
code_ += "pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ +=
" self.0[{{FIELD_OFFSET}}..{{FIELD_OFFSET}} + {{FIELD_SIZE}}]"
" self.0[{{FIELD_OFFSET}}..{{FIELD_OFFSET}} + {{FIELD_SIZE}}]"
".copy_from_slice(&x.0)";
} else if (IsArray(field.value.type)) {
if (GetFullType(field.value.type) == ftArrayOfBuiltin) {
@@ -2728,36 +2708,35 @@ class RustGenerator : public BaseGenerator {
"ARRAY_ITEM_SIZE",
NumToString(InlineSize(field.value.type.VectorType())));
code_ +=
" pub fn set_{{FIELD_NAME}}(&mut self, items: &{{FIELD_TYPE}}) "
"pub fn set_{{FIELD_NAME}}(&mut self, items: &{{FIELD_TYPE}}) "
"{";
code_ +=
" flatbuffers::emplace_scalar_array(&mut self.0, "
" flatbuffers::emplace_scalar_array(&mut self.0, "
"{{FIELD_OFFSET}}, items);";
} else {
code_.SetValue("FIELD_SIZE",
NumToString(InlineSize(field.value.type)));
code_ +=
" pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ += " unsafe {";
code_ += " std::ptr::copy(";
code_ += " x.as_ptr() as *const u8,";
code_ += " self.0.as_mut_ptr().add({{FIELD_OFFSET}}),";
code_ += " {{FIELD_SIZE}},";
code_ += " );";
code_ += " }";
code_ += "pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ += " unsafe {";
code_ += " std::ptr::copy(";
code_ += " x.as_ptr() as *const u8,";
code_ += " self.0.as_mut_ptr().add({{FIELD_OFFSET}}),";
code_ += " {{FIELD_SIZE}},";
code_ += " );";
code_ += " }";
}
} else {
code_ += " pub fn set_{{FIELD_NAME}}(&mut self, x: {{FIELD_TYPE}}) {";
code_ += " let x_le = x.to_little_endian();";
code_ += " unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,";
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
code_ += " );";
code_ += " }";
code_ += "pub fn set_{{FIELD_NAME}}(&mut self, x: {{FIELD_TYPE}}) {";
code_ += " let x_le = x.to_little_endian();";
code_ += " unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,";
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
code_ += " );";
code_ += " }";
}
code_ += " }\n";
code_ += "}\n";
// Generate a comparison function for this field if it is a key.
if (field.key) { GenKeyFieldMethods(field); }
@@ -2772,15 +2751,15 @@ class RustGenerator : public BaseGenerator {
if (IsArray(field.value.type)) {
if (GetFullType(field.value.type) == ftArrayOfStruct) {
code_ +=
" {{FIELD_NAME}}: { let {{FIELD_NAME}} = "
" {{FIELD_NAME}}: { let {{FIELD_NAME}} = "
"self.{{FIELD_NAME}}(); flatbuffers::array_init(|i| "
"{{FIELD_NAME}}.get(i).unpack()) },";
} else {
code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}().into(),";
code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}().into(),";
}
} else {
std::string unpack = IsStruct(field.value.type) ? ".unpack()" : "";
code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}()" + unpack + ",";
code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}()" + unpack + ",";
}
});
code_ += " }";
@@ -2797,7 +2776,7 @@ class RustGenerator : public BaseGenerator {
code_ += "pub struct {{NATIVE_STRUCT_NAME}} {";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
(void)field; // unused.
code_ += " pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
code_ += "pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
});
code_ += "}";
// The `pack` method that turns the native struct into its Flatbuffers
@@ -2807,17 +2786,17 @@ class RustGenerator : public BaseGenerator {
code_ += " {{STRUCT_NAME}}::new(";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
if (IsStruct(field.value.type)) {
code_ += " &self.{{FIELD_NAME}}.pack(),";
code_ += " &self.{{FIELD_NAME}}.pack(),";
} else if (IsArray(field.value.type)) {
if (GetFullType(field.value.type) == ftArrayOfStruct) {
code_ +=
" &flatbuffers::array_init(|i| "
" &flatbuffers::array_init(|i| "
"self.{{FIELD_NAME}}[i].pack()),";
} else {
code_ += " &self.{{FIELD_NAME}},";
code_ += " &self.{{FIELD_NAME}},";
}
} else {
code_ += " self.{{FIELD_NAME}},";
code_ += " self.{{FIELD_NAME}},";
}
});
code_ += " )";