From 689bfafa7e8061dc25f0f4b5e7017a1fecb3ceac Mon Sep 17 00:00:00 2001 From: Anass Al Date: Mon, 28 Sep 2020 08:54:50 -0700 Subject: [PATCH] [Python/JS/TS] Codegen SizeOf method for structs (#6136) * [Python] Codegen SizeOf classmethod for structs This codegens a `SizeOf()` classmethod for all structs since we can't determine the size of a FlatBuffer generated struct from Python otherwise. * [JS/TS] Codegen sizeOf static method for structs This codegens a `sizeOf()` static method for all structs since we can't determine the size of a FlatBuffer generated struct from JavaScript or TypeScript otherwise. --- src/idl_gen_js_ts.cpp | 12 +++++++++++ src/idl_gen_python.cpp | 13 ++++++++++++ tests/MyGame/Example/Ability.py | 4 ++++ tests/MyGame/Example/ArrayStruct.py | 4 ++++ tests/MyGame/Example/NestedStruct.py | 4 ++++ tests/MyGame/Example/Test.py | 4 ++++ tests/MyGame/Example/Vec3.py | 4 ++++ tests/monster_test_generated.js | 21 +++++++++++++++++++ tests/monster_test_generated.ts | 21 +++++++++++++++++++ .../NamespaceA/NamespaceB/StructInNestedNS.py | 4 ++++ .../namespace_test1_generated.js | 7 +++++++ .../namespace_test1_generated.ts | 7 +++++++ tests/union_vector/union_vector_generated.js | 14 +++++++++++++ tests/union_vector/union_vector_generated.ts | 14 +++++++++++++ 14 files changed, 133 insertions(+) diff --git a/src/idl_gen_js_ts.cpp b/src/idl_gen_js_ts.cpp index 8be06dff0..02b85bd2f 100644 --- a/src/idl_gen_js_ts.cpp +++ b/src/idl_gen_js_ts.cpp @@ -1795,6 +1795,18 @@ class JsTsGenerator : public BaseGenerator { code += "}\n\n"; } + // Emit the size of the struct. + if (struct_def.fixed) { + GenDocComment(code_ptr, GenTypeAnnotation(kReturns, "number", "", false)); + if (lang_.language == IDLOptions::kTs) { + code += "static sizeOf():number {\n"; + } else { + code += object_name + ".sizeOf = function() {\n"; + } + code += " return " + NumToString(struct_def.bytesize) + ";\n"; + code += "}\n\n"; + } + // Emit a factory constructor if (struct_def.fixed) { std::string annotations = diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index c64357e03..95b4490af 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -621,6 +621,16 @@ class PythonGenerator : public BaseGenerator { } } + // Generate struct sizeof. + void GenStructSizeOf(const StructDef &struct_def, std::string *code_ptr) { + auto &code = *code_ptr; + code += Indent + "@classmethod\n"; + code += Indent + "def SizeOf(cls):\n"; + code += + Indent + Indent + "return " + NumToString(struct_def.bytesize) + "\n"; + code += "\n"; + } + // Generate table constructors, conditioned on its members' types. void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { GetStartOfTable(struct_def, code_ptr); @@ -678,6 +688,9 @@ class PythonGenerator : public BaseGenerator { // Generate a special function to test file_identifier GenHasFileIdentifier(struct_def, code_ptr); } + } else { + // Generates the SizeOf method for all structs. + GenStructSizeOf(struct_def, code_ptr); } // Generates the Init method that sets the field in a pre-existing // accessor object. This is to allow object reuse. diff --git a/tests/MyGame/Example/Ability.py b/tests/MyGame/Example/Ability.py index 2cc916bdd..e57dfd74f 100644 --- a/tests/MyGame/Example/Ability.py +++ b/tests/MyGame/Example/Ability.py @@ -9,6 +9,10 @@ np = import_numpy() class Ability(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 8 + # Ability def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/MyGame/Example/ArrayStruct.py b/tests/MyGame/Example/ArrayStruct.py index 50f136df7..c80bf6882 100644 --- a/tests/MyGame/Example/ArrayStruct.py +++ b/tests/MyGame/Example/ArrayStruct.py @@ -9,6 +9,10 @@ np = import_numpy() class ArrayStruct(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 160 + # ArrayStruct def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/MyGame/Example/NestedStruct.py b/tests/MyGame/Example/NestedStruct.py index a66cee01f..a9db014f9 100644 --- a/tests/MyGame/Example/NestedStruct.py +++ b/tests/MyGame/Example/NestedStruct.py @@ -9,6 +9,10 @@ np = import_numpy() class NestedStruct(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 32 + # NestedStruct def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/MyGame/Example/Test.py b/tests/MyGame/Example/Test.py index 576a656e8..8357ec209 100644 --- a/tests/MyGame/Example/Test.py +++ b/tests/MyGame/Example/Test.py @@ -9,6 +9,10 @@ np = import_numpy() class Test(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 4 + # Test def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/MyGame/Example/Vec3.py b/tests/MyGame/Example/Vec3.py index 5c91a7d39..69cd511f4 100644 --- a/tests/MyGame/Example/Vec3.py +++ b/tests/MyGame/Example/Vec3.py @@ -9,6 +9,10 @@ np = import_numpy() class Vec3(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 32 + # Vec3 def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index fedc2c0e1..bab85474d 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -342,6 +342,13 @@ MyGame.Example.Test.prototype.mutate_b = function(value) { return true; }; +/** + * @returns {number} + */ +MyGame.Example.Test.sizeOf = function() { + return 4; +} + /** * @param {flatbuffers.Builder} builder * @param {number} a @@ -573,6 +580,13 @@ MyGame.Example.Vec3.prototype.test3 = function(obj) { return (obj || new MyGame.Example.Test).__init(this.bb_pos + 26, this.bb); }; +/** + * @returns {number} + */ +MyGame.Example.Vec3.sizeOf = function() { + return 32; +} + /** * @param {flatbuffers.Builder} builder * @param {number} x @@ -659,6 +673,13 @@ MyGame.Example.Ability.prototype.mutate_distance = function(value) { return true; }; +/** + * @returns {number} + */ +MyGame.Example.Ability.sizeOf = function() { + return 8; +} + /** * @param {flatbuffers.Builder} builder * @param {number} id diff --git a/tests/monster_test_generated.ts b/tests/monster_test_generated.ts index afdaeabdb..9ba725415 100644 --- a/tests/monster_test_generated.ts +++ b/tests/monster_test_generated.ts @@ -376,6 +376,13 @@ mutate_b(value:number):boolean { return true; }; +/** + * @returns number + */ +static sizeOf():number { + return 4; +} + /** * @param flatbuffers.Builder builder * @param number a @@ -668,6 +675,13 @@ test3(obj?:MyGame.Example.Test):MyGame.Example.Test|null { return (obj || new MyGame.Example.Test()).__init(this.bb_pos + 26, this.bb!); }; +/** + * @returns number + */ +static sizeOf():number { + return 32; +} + /** * @param flatbuffers.Builder builder * @param number x @@ -811,6 +825,13 @@ mutate_distance(value:number):boolean { return true; }; +/** + * @returns number + */ +static sizeOf():number { + return 8; +} + /** * @param flatbuffers.Builder builder * @param number id diff --git a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.py b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.py index 9df52bde4..f49495b62 100644 --- a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.py +++ b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.py @@ -9,6 +9,10 @@ np = import_numpy() class StructInNestedNS(object): __slots__ = ['_tab'] + @classmethod + def SizeOf(cls): + return 8 + # StructInNestedNS def Init(self, buf, pos): self._tab = flatbuffers.table.Table(buf, pos) diff --git a/tests/namespace_test/namespace_test1_generated.js b/tests/namespace_test/namespace_test1_generated.js index fe1c0a754..7331f64e4 100644 --- a/tests/namespace_test/namespace_test1_generated.js +++ b/tests/namespace_test/namespace_test1_generated.js @@ -205,6 +205,13 @@ NamespaceA.NamespaceB.StructInNestedNS.getFullyQualifiedName = function() { return 'NamespaceA.NamespaceB.StructInNestedNS'; } +/** + * @returns {number} + */ +NamespaceA.NamespaceB.StructInNestedNS.sizeOf = function() { + return 8; +} + /** * @param {flatbuffers.Builder} builder * @param {number} a diff --git a/tests/namespace_test/namespace_test1_generated.ts b/tests/namespace_test/namespace_test1_generated.ts index 47f894242..933a43d23 100644 --- a/tests/namespace_test/namespace_test1_generated.ts +++ b/tests/namespace_test/namespace_test1_generated.ts @@ -204,6 +204,13 @@ static getFullyQualifiedName():string { return 'NamespaceA.NamespaceB.StructInNestedNS'; } +/** + * @returns number + */ +static sizeOf():number { + return 8; +} + /** * @param flatbuffers.Builder builder * @param number a diff --git a/tests/union_vector/union_vector_generated.js b/tests/union_vector/union_vector_generated.js index 01f883c1d..9e8b76e64 100644 --- a/tests/union_vector/union_vector_generated.js +++ b/tests/union_vector/union_vector_generated.js @@ -185,6 +185,13 @@ Rapunzel.getFullyQualifiedName = function() { return 'Rapunzel'; } +/** + * @returns {number} + */ +Rapunzel.sizeOf = function() { + return 4; +} + /** * @param {flatbuffers.Builder} builder * @param {number} hair_length @@ -245,6 +252,13 @@ BookReader.getFullyQualifiedName = function() { return 'BookReader'; } +/** + * @returns {number} + */ +BookReader.sizeOf = function() { + return 4; +} + /** * @param {flatbuffers.Builder} builder * @param {number} books_read diff --git a/tests/union_vector/union_vector_generated.ts b/tests/union_vector/union_vector_generated.ts index eb74fcbc8..806c07f23 100644 --- a/tests/union_vector/union_vector_generated.ts +++ b/tests/union_vector/union_vector_generated.ts @@ -221,6 +221,13 @@ static getFullyQualifiedName():string { return 'Rapunzel'; } +/** + * @returns number + */ +static sizeOf():number { + return 4; +} + /** * @param flatbuffers.Builder builder * @param number hair_length @@ -310,6 +317,13 @@ static getFullyQualifiedName():string { return 'BookReader'; } +/** + * @returns number + */ +static sizeOf():number { + return 4; +} + /** * @param flatbuffers.Builder builder * @param number books_read