Merge pull request #257 from evanw/javascript
Add support for JavaScript code generation with Google Closure Compiler type annotations
This commit is contained in:
commit
525130765a
|
@ -44,6 +44,8 @@ snapshot.sh
|
|||
tests/go_gen
|
||||
tests/monsterdata_java_wire.mon
|
||||
tests/monsterdata_go_wire.mon
|
||||
tests/monsterdata_javascript_wire.mon
|
||||
tests/unicode_test.mon
|
||||
CMakeLists.txt.user
|
||||
CMakeScripts/**
|
||||
CTestTestfile.cmake
|
||||
|
@ -55,4 +57,4 @@ java/.idea
|
|||
java/*.iml
|
||||
java/target
|
||||
**/*.pyc
|
||||
.idea
|
||||
.idea
|
||||
|
|
|
@ -33,6 +33,7 @@ set(FlatBuffers_Compiler_SRCS
|
|||
src/idl_gen_cpp.cpp
|
||||
src/idl_gen_general.cpp
|
||||
src/idl_gen_go.cpp
|
||||
src/idl_gen_js.cpp
|
||||
src/idl_gen_python.cpp
|
||||
src/idl_gen_fbs.cpp
|
||||
src/flatc.cpp
|
||||
|
|
|
@ -449,6 +449,7 @@ extern void GenComment(const std::vector<std::string> &dc,
|
|||
// Container of options that may apply to any of the source/text generators.
|
||||
struct GeneratorOptions {
|
||||
bool strict_json;
|
||||
bool skip_js_exports;
|
||||
bool output_default_scalars_in_json;
|
||||
int indent_step;
|
||||
bool output_enum_identifiers;
|
||||
|
@ -464,6 +465,7 @@ struct GeneratorOptions {
|
|||
Language lang;
|
||||
|
||||
GeneratorOptions() : strict_json(false),
|
||||
skip_js_exports(false),
|
||||
output_default_scalars_in_json(false),
|
||||
indent_step(2),
|
||||
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
|
||||
|
@ -506,6 +508,15 @@ extern bool GenerateCPP(const Parser &parser,
|
|||
const std::string &file_name,
|
||||
const GeneratorOptions &opts);
|
||||
|
||||
// Generate JavaScript code from the definitions in the Parser object.
|
||||
// See idl_gen_js.
|
||||
extern std::string GenerateJS(const Parser &parser,
|
||||
const GeneratorOptions &opts);
|
||||
extern bool GenerateJS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name,
|
||||
const GeneratorOptions &opts);
|
||||
|
||||
// Generate Go files from the definitions in the Parser object.
|
||||
// See idl_gen_go.cpp.
|
||||
extern bool GenerateGo(const Parser &parser,
|
||||
|
@ -551,6 +562,13 @@ extern bool GenerateFBS(const Parser &parser,
|
|||
const std::string &file_name,
|
||||
const GeneratorOptions &opts);
|
||||
|
||||
// Generate a make rule for the generated JavaScript code.
|
||||
// See idl_gen_js.cpp.
|
||||
extern std::string JSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name,
|
||||
const GeneratorOptions &opts);
|
||||
|
||||
// Generate a make rule for the generated C++ header.
|
||||
// See idl_gen_cpp.cpp.
|
||||
extern std::string CPPMakeRule(const Parser &parser,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,6 +60,10 @@ const Generator generators[] = {
|
|||
flatbuffers::GeneratorOptions::kJava,
|
||||
"Generate Java classes for tables/structs",
|
||||
flatbuffers::GeneralMakeRule },
|
||||
{ flatbuffers::GenerateJS, "-s", "JavaScript",
|
||||
flatbuffers::GeneratorOptions::kMAX,
|
||||
"Generate JavaScript code for tables/structs",
|
||||
flatbuffers::JSMakeRule },
|
||||
{ flatbuffers::GenerateGeneral, "-n", "C#",
|
||||
flatbuffers::GeneratorOptions::kCSharp,
|
||||
"Generate C# classes for tables/structs",
|
||||
|
@ -140,6 +144,8 @@ int main(int argc, const char *argv[]) {
|
|||
include_directories.push_back(argv[argi]);
|
||||
} else if(arg == "--strict-json") {
|
||||
opts.strict_json = true;
|
||||
} else if(arg == "--no-js-exports") {
|
||||
opts.skip_js_exports = true;
|
||||
} else if(arg == "--defaults-json") {
|
||||
opts.output_default_scalars_in_json = true;
|
||||
} else if(arg == "--no-prefix") {
|
||||
|
|
|
@ -0,0 +1,732 @@
|
|||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// independent from idl_parser, since this code is not needed for most clients
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace js {
|
||||
|
||||
static void GenNamespaces(const Parser &parser, std::string *code_ptr,
|
||||
std::string *exports_ptr) {
|
||||
std::set<std::string> namespaces;
|
||||
|
||||
for (auto it = parser.namespaces_.begin();
|
||||
it != parser.namespaces_.end(); ++it) {
|
||||
std::string namespace_so_far;
|
||||
|
||||
// Gather all parent namespaces for this namespace
|
||||
for (auto component = (*it)->components.begin();
|
||||
component != (*it)->components.end(); ++component) {
|
||||
if (!namespace_so_far.empty()) {
|
||||
namespace_so_far += '.';
|
||||
}
|
||||
namespace_so_far += *component;
|
||||
namespaces.insert(namespace_so_far);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure parent namespaces come before child namespaces
|
||||
std::vector<std::string> sorted_namespaces(
|
||||
namespaces.begin(), namespaces.end());
|
||||
std::sort(sorted_namespaces.begin(), sorted_namespaces.end());
|
||||
|
||||
// Emit namespaces in a form that Closure Compiler can optimize
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
for (auto it = sorted_namespaces.begin();
|
||||
it != sorted_namespaces.end(); it++) {
|
||||
code += "/**\n * @const\n*/\n";
|
||||
if (it->find('.') == std::string::npos) {
|
||||
code += "var ";
|
||||
exports += "this." + *it + " = " + *it + ";\n";
|
||||
}
|
||||
code += *it + " = " + *it + " || {};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
static std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) {
|
||||
std::string qualified_name;
|
||||
for (auto it = ns->components.begin();
|
||||
it != ns->components.end(); ++it) {
|
||||
qualified_name += *it + ".";
|
||||
}
|
||||
return qualified_name + name;
|
||||
}
|
||||
|
||||
static std::string WrapInNameSpace(const Definition &def) {
|
||||
return WrapInNameSpace(def.defined_namespace, def.name);
|
||||
}
|
||||
|
||||
// Generate a documentation comment, if available.
|
||||
static void GenDocComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr,
|
||||
const std::string &extra_lines,
|
||||
const char *indent = nullptr) {
|
||||
if (dc.empty() && extra_lines.empty()) {
|
||||
// Don't output empty comment blocks with 0 lines of comment content.
|
||||
return;
|
||||
}
|
||||
|
||||
std::string &code = *code_ptr;
|
||||
if (indent) code += indent;
|
||||
code += "/**\n";
|
||||
for (auto it = dc.begin(); it != dc.end(); ++it) {
|
||||
if (indent) code += indent;
|
||||
code += " *" + *it + "\n";
|
||||
}
|
||||
if (!extra_lines.empty()) {
|
||||
if (!dc.empty()) {
|
||||
if (indent) code += indent;
|
||||
code += " *\n";
|
||||
}
|
||||
if (indent) code += indent;
|
||||
std::string::size_type start = 0;
|
||||
while (true) {
|
||||
auto end = extra_lines.find('\n', start);
|
||||
if (end != std::string::npos) {
|
||||
code += " * " + extra_lines.substr(start, end - start) + "\n";
|
||||
start = end + 1;
|
||||
} else {
|
||||
code += " * " + extra_lines.substr(start) + "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (indent) code += indent;
|
||||
code += " */\n";
|
||||
}
|
||||
|
||||
static void GenDocComment(std::string *code_ptr,
|
||||
const std::string &extra_lines) {
|
||||
GenDocComment(std::vector<std::string>(), code_ptr, extra_lines);
|
||||
}
|
||||
|
||||
// Generate an enum declaration and an enum string lookup table.
|
||||
static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
std::string *exports_ptr) {
|
||||
if (enum_def.generated) return;
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
|
||||
if (enum_def.defined_namespace->components.empty()) {
|
||||
code += "var ";
|
||||
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
|
||||
}
|
||||
code += WrapInNameSpace(enum_def) + " = {\n";
|
||||
for (auto it = enum_def.vals.vec.begin();
|
||||
it != enum_def.vals.vec.end(); ++it) {
|
||||
auto &ev = **it;
|
||||
if (!ev.doc_comment.empty()) {
|
||||
if (it != enum_def.vals.vec.begin()) {
|
||||
code += '\n';
|
||||
}
|
||||
GenDocComment(ev.doc_comment, code_ptr, "", " ");
|
||||
}
|
||||
code += " " + ev.name + ": " + NumToString(ev.value);
|
||||
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
static std::string GenType(const Type &type) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_BOOL:
|
||||
case BASE_TYPE_CHAR: return "Int8";
|
||||
case BASE_TYPE_UTYPE:
|
||||
case BASE_TYPE_UCHAR: return "Uint8";
|
||||
case BASE_TYPE_SHORT: return "Int16";
|
||||
case BASE_TYPE_USHORT: return "Uint16";
|
||||
case BASE_TYPE_INT: return "Int32";
|
||||
case BASE_TYPE_UINT: return "Uint32";
|
||||
case BASE_TYPE_LONG: return "Int64";
|
||||
case BASE_TYPE_ULONG: return "Uint64";
|
||||
case BASE_TYPE_FLOAT: return "Float32";
|
||||
case BASE_TYPE_DOUBLE: return "Float64";
|
||||
case BASE_TYPE_STRING: return "String";
|
||||
case BASE_TYPE_VECTOR: return GenType(type.VectorType());
|
||||
case BASE_TYPE_STRUCT: return type.struct_def->name;
|
||||
default: return "Table";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GenGetter(const Type &type, const std::string &arguments) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_STRING: return "this.bb.__string" + arguments;
|
||||
case BASE_TYPE_STRUCT: return "this.bb.__struct" + arguments;
|
||||
case BASE_TYPE_UNION: return "this.bb.__union" + arguments;
|
||||
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
|
||||
default: {
|
||||
auto getter = "this.bb.read" + MakeCamel(GenType(type)) + arguments;
|
||||
if (type.base_type == BASE_TYPE_BOOL) {
|
||||
getter = "!!" + getter;
|
||||
}
|
||||
if (type.enum_def) {
|
||||
getter = "/** @type {" + WrapInNameSpace(*type.enum_def) + "} */ (" +
|
||||
getter + ")";
|
||||
}
|
||||
return getter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GenDefaultValue(const Value &value) {
|
||||
if (value.type.enum_def) {
|
||||
if (auto val = value.type.enum_def->ReverseLookup(
|
||||
atoi(value.constant.c_str()), false)) {
|
||||
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
|
||||
}
|
||||
}
|
||||
|
||||
switch (value.type.base_type) {
|
||||
case BASE_TYPE_BOOL:
|
||||
return value.constant == "0" ? "false" : "true";
|
||||
|
||||
case BASE_TYPE_STRING:
|
||||
return "null";
|
||||
|
||||
case BASE_TYPE_LONG:
|
||||
case BASE_TYPE_ULONG:
|
||||
if (value.constant != "0") {
|
||||
int64_t constant = std::atoll(value.constant.c_str());
|
||||
return "new flatbuffers.Long(" + NumToString((int32_t)constant) +
|
||||
", " + NumToString((int32_t)(constant >> 32)) + ")";
|
||||
}
|
||||
return "flatbuffers.Long.ZERO";
|
||||
|
||||
default:
|
||||
return value.constant;
|
||||
}
|
||||
}
|
||||
|
||||
enum struct InOut {
|
||||
IN,
|
||||
OUT,
|
||||
};
|
||||
|
||||
static std::string GenTypeName(const Type &type, InOut inOut) {
|
||||
if (inOut == InOut::OUT) {
|
||||
if (type.base_type == BASE_TYPE_STRING) {
|
||||
return "string|Uint8Array";
|
||||
}
|
||||
if (type.base_type == BASE_TYPE_STRUCT) {
|
||||
return WrapInNameSpace(*type.struct_def);
|
||||
}
|
||||
}
|
||||
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_BOOL: return "boolean";
|
||||
case BASE_TYPE_LONG:
|
||||
case BASE_TYPE_ULONG: return "flatbuffers.Long";
|
||||
default:
|
||||
if (IsScalar(type.base_type)) {
|
||||
if (type.enum_def) {
|
||||
return WrapInNameSpace(*type.enum_def);
|
||||
}
|
||||
return "number";
|
||||
}
|
||||
return "flatbuffers.Offset";
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the method name for use with add/put calls.
|
||||
static std::string GenWriteMethod(const Type &type) {
|
||||
// Forward to signed versions since unsigned versions don't exist
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_UTYPE:
|
||||
case BASE_TYPE_UCHAR: return GenWriteMethod(Type(BASE_TYPE_CHAR));
|
||||
case BASE_TYPE_USHORT: return GenWriteMethod(Type(BASE_TYPE_SHORT));
|
||||
case BASE_TYPE_UINT: return GenWriteMethod(Type(BASE_TYPE_INT));
|
||||
case BASE_TYPE_ULONG: return GenWriteMethod(Type(BASE_TYPE_LONG));
|
||||
default: break;
|
||||
}
|
||||
|
||||
return IsScalar(type.base_type)
|
||||
? MakeCamel(GenType(type))
|
||||
: (IsStruct(type) ? "Struct" : "Offset");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::string MaybeAdd(T value) {
|
||||
return value != 0 ? " + " + NumToString(value) : "";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::string MaybeScale(T value) {
|
||||
return value != 1 ? " * " + NumToString(value) : "";
|
||||
}
|
||||
|
||||
static void GenStructArgs(const StructDef &struct_def,
|
||||
std::string *annotations,
|
||||
std::string *arguments,
|
||||
const std::string &nameprefix) {
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (IsStruct(field.value.type)) {
|
||||
// Generate arguments for a struct inside a struct. To ensure names
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
GenStructArgs(*field.value.type.struct_def, annotations, arguments,
|
||||
nameprefix + field.name + "_");
|
||||
} else {
|
||||
*annotations += "@param {" + GenTypeName(field.value.type, InOut::IN);
|
||||
*annotations += "} " + nameprefix + field.name + "\n";
|
||||
*arguments += ", " + nameprefix + field.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GenStructBody(const StructDef &struct_def,
|
||||
std::string *body,
|
||||
const std::string &nameprefix) {
|
||||
*body += " builder.prep(";
|
||||
*body += NumToString(struct_def.minalign) + ", ";
|
||||
*body += NumToString(struct_def.bytesize) + ");\n";
|
||||
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend(); ++it) {
|
||||
auto &field = **it;
|
||||
if (field.padding) {
|
||||
*body += " builder.pad(" + NumToString(field.padding) + ");\n";
|
||||
}
|
||||
if (IsStruct(field.value.type)) {
|
||||
// Generate arguments for a struct inside a struct. To ensure names
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
GenStructBody(*field.value.type.struct_def, body,
|
||||
nameprefix + field.name + "_");
|
||||
} else {
|
||||
*body += " builder.write" + GenWriteMethod(field.value.type) + "(";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL) {
|
||||
*body += "+";
|
||||
}
|
||||
*body += nameprefix + field.name + ");\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate an accessor struct with constructor for a flatbuffers struct.
|
||||
static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
std::string *code_ptr, std::string *exports_ptr) {
|
||||
if (struct_def.generated) return;
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
|
||||
// Emit constructor
|
||||
bool isStatement = struct_def.defined_namespace->components.empty();
|
||||
std::string object_name = WrapInNameSpace(struct_def);
|
||||
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
|
||||
if (isStatement) {
|
||||
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
|
||||
code += "function " + object_name;
|
||||
} else {
|
||||
code += object_name + " = function";
|
||||
}
|
||||
code += "() {\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {flatbuffers.ByteBuffer}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb = null;\n";
|
||||
code += "\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {number}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb_pos = 0;\n";
|
||||
code += isStatement ? "}\n\n" : "};\n\n";
|
||||
|
||||
// Generate the __init method that sets the field in a pre-existing
|
||||
// accessor object. This is to allow object reuse.
|
||||
code += "/**\n";
|
||||
code += " * @param {number} i\n";
|
||||
code += " * @param {flatbuffers.ByteBuffer} bb\n";
|
||||
code += " * @returns {" + object_name + "}\n";
|
||||
code += " */\n";
|
||||
code += object_name + ".prototype.__init = function(i, bb) {\n";
|
||||
code += " this.bb_pos = i;\n";
|
||||
code += " this.bb = bb;\n";
|
||||
code += " return this;\n";
|
||||
code += "};\n\n";
|
||||
|
||||
// Generate a special accessor for the table that when used as the root of a
|
||||
// FlatBuffer
|
||||
if (!struct_def.fixed) {
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.ByteBuffer} bb\n"
|
||||
"@param {" + object_name + "=} obj\n"
|
||||
"@returns {" + object_name + "}");
|
||||
code += object_name + ".getRootAs" + struct_def.name;
|
||||
code += " = function(bb, obj) {\n";
|
||||
code += " return (obj || new " + object_name;
|
||||
code += ").__init(bb.readInt32(bb.position()) + bb.position(), bb);\n";
|
||||
code += "};\n\n";
|
||||
|
||||
// Generate the identifier check method
|
||||
if (parser.root_struct_def_ == &struct_def &&
|
||||
!parser.file_identifier_.empty()) {
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.ByteBuffer} bb\n"
|
||||
"@returns {boolean}");
|
||||
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
|
||||
code += " return bb.__has_identifier('" + parser.file_identifier_;
|
||||
code += "');\n};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Emit field accessors
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (field.deprecated) continue;
|
||||
auto offset_prefix = " var offset = this.bb.__offset(this.bb_pos, " +
|
||||
NumToString(field.value.offset) + ");\n return offset ? ";
|
||||
|
||||
// Emit a scalar field
|
||||
if (IsScalar(field.value.type.base_type) ||
|
||||
field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
std::string(field.value.type.base_type == BASE_TYPE_STRING ?
|
||||
"@param {flatbuffers.Encoding=} optionalEncoding\n" : "") +
|
||||
"@returns {" + GenTypeName(field.value.type, InOut::OUT) + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += "optionalEncoding";
|
||||
}
|
||||
code += ") {\n";
|
||||
if (struct_def.fixed) {
|
||||
code += " return " + GenGetter(field.value.type, "(this.bb_pos" +
|
||||
MaybeAdd(field.value.offset) + ")") + ";\n";
|
||||
} else {
|
||||
std::string index = "this.bb_pos + offset";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
index += ", optionalEncoding";
|
||||
}
|
||||
code += offset_prefix + GenGetter(field.value.type,
|
||||
"(" + index + ")") + " : " + GenDefaultValue(field.value);
|
||||
code += ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Emit an object field
|
||||
else {
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
auto type = WrapInNameSpace(*field.value.type.struct_def);
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
"@param {" + type + "=} obj\n@returns {" + type + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
if (struct_def.fixed) {
|
||||
code += " return (obj || new " + type;
|
||||
code += ").__init(this.bb_pos";
|
||||
code += MaybeAdd(field.value.offset) + ", this.bb);\n";
|
||||
} else {
|
||||
code += offset_prefix + "(obj || new " + type + ").__init(";
|
||||
code += field.value.type.struct_def->fixed
|
||||
? "this.bb_pos + offset"
|
||||
: "this.bb.__indirect(this.bb_pos + offset)";
|
||||
code += ", this.bb) : null;\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BASE_TYPE_VECTOR: {
|
||||
auto vectortype = field.value.type.VectorType();
|
||||
auto vectortypename = GenTypeName(vectortype, InOut::OUT);
|
||||
auto inline_size = InlineSize(vectortype);
|
||||
auto index = "this.bb.__vector(this.bb_pos + offset) + index" +
|
||||
MaybeScale(inline_size);
|
||||
std::string args = "@param {number} index\n";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
args += "@param {" + vectortypename + "=} obj\n";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
args += "@param {flatbuffers.Encoding=} optionalEncoding\n";
|
||||
}
|
||||
GenDocComment(field.doc_comment, code_ptr, args +
|
||||
"@returns {" + vectortypename + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(index";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += ", obj";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += ", optionalEncoding";
|
||||
}
|
||||
code += ") {\n";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += offset_prefix + "(obj || new " + vectortypename;
|
||||
code += ").__init(";
|
||||
code += vectortype.struct_def->fixed
|
||||
? index
|
||||
: "this.bb.__indirect(" + index + ")";
|
||||
code += ", this.bb)";
|
||||
} else {
|
||||
if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
index += ", optionalEncoding";
|
||||
}
|
||||
code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
|
||||
}
|
||||
code += " : ";
|
||||
if (field.value.type.element == BASE_TYPE_BOOL) {
|
||||
code += "false";
|
||||
} else if (field.value.type.element == BASE_TYPE_LONG ||
|
||||
field.value.type.element == BASE_TYPE_ULONG) {
|
||||
code += "flatbuffers.Long.ZERO";
|
||||
} else if (IsScalar(field.value.type.element)) {
|
||||
code += "0";
|
||||
} else {
|
||||
code += "null";
|
||||
}
|
||||
code += ";\n";
|
||||
break;
|
||||
}
|
||||
|
||||
case BASE_TYPE_UNION:
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
"@param {flatbuffers.Table} obj\n"
|
||||
"@returns {?flatbuffers.Table}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
code += offset_prefix + GenGetter(field.value.type,
|
||||
"(obj, this.bb_pos + offset)") + " : null;\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
code += "};\n\n";
|
||||
|
||||
// Emit a length helper
|
||||
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
GenDocComment(code_ptr, "@returns {number}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Length = function() {\n" + offset_prefix;
|
||||
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Emit a factory constructor
|
||||
if (struct_def.fixed) {
|
||||
std::string annotations = "@param {flatbuffers.Builder} builder\n";
|
||||
std::string arguments;
|
||||
GenStructArgs(struct_def, &annotations, &arguments, "");
|
||||
GenDocComment(code_ptr, annotations +
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".create" + struct_def.name + " = function(builder";
|
||||
code += arguments + ") {\n";
|
||||
GenStructBody(struct_def, &code, "");
|
||||
code += " return builder.offset();\n};\n\n";
|
||||
} else {
|
||||
// Generate a method to start building a new object
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder");
|
||||
code += object_name + ".start" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
code += " builder.startObject(" + NumToString(
|
||||
struct_def.fields.vec.size()) + ");\n";
|
||||
code += "};\n\n";
|
||||
|
||||
// Generate a set of static methods that allow table construction
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (field.deprecated) continue;
|
||||
auto argname = MakeCamel(field.name, false);
|
||||
if (!IsScalar(field.value.type.base_type)) {
|
||||
argname += "Offset";
|
||||
}
|
||||
|
||||
// Generate the field insertion method
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {" + GenTypeName(field.value.type, InOut::IN) + "} " +
|
||||
argname);
|
||||
code += object_name + ".add" + MakeCamel(field.name);
|
||||
code += " = function(builder, " + argname + ") {\n";
|
||||
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
|
||||
code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL) {
|
||||
code += "+";
|
||||
}
|
||||
code += argname + ", ";
|
||||
if (!IsScalar(field.value.type.base_type)) {
|
||||
code += "0";
|
||||
} else {
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL) {
|
||||
code += "+";
|
||||
}
|
||||
code += GenDefaultValue(field.value);
|
||||
}
|
||||
code += ");\n};\n\n";
|
||||
|
||||
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
auto vector_type = field.value.type.VectorType();
|
||||
auto alignment = InlineAlignment(vector_type);
|
||||
auto elem_size = InlineSize(vector_type);
|
||||
|
||||
// Generate a method to create a vector from a JavaScript array
|
||||
if (!IsStruct(vector_type)) {
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {Array.<" + GenTypeName(vector_type, InOut::IN) +
|
||||
">} data\n"
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".create" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, data) {\n";
|
||||
code += " builder.startVector(" + NumToString(elem_size);
|
||||
code += ", data.length, " + NumToString(alignment) + ");\n";
|
||||
code += " for (var i = data.length - 1; i >= 0; i--) {\n";
|
||||
code += " builder.add" + GenWriteMethod(vector_type) + "(";
|
||||
if (vector_type.base_type == BASE_TYPE_BOOL) {
|
||||
code += "+";
|
||||
}
|
||||
code += "data[i]);\n";
|
||||
code += " }\n";
|
||||
code += " return builder.endVector();\n";
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
// Generate a method to start a vector, data to be added manually after
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {number} numElems");
|
||||
code += object_name + ".start" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, numElems) {\n";
|
||||
code += " builder.startVector(" + NumToString(elem_size);
|
||||
code += ", numElems, " + NumToString(alignment) + ");\n";
|
||||
code += "};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a method to stop building a new object
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".end" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
code += " var offset = builder.endObject();\n";
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (!field.deprecated && field.required) {
|
||||
code += " builder.requiredField(offset, ";
|
||||
code += NumToString(field.value.offset);
|
||||
code += "); // " + field.name + "\n";
|
||||
}
|
||||
}
|
||||
code += " return offset;\n";
|
||||
code += "};\n\n";
|
||||
|
||||
// Generate the method to complete buffer construction
|
||||
if (parser.root_struct_def_ == &struct_def) {
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {flatbuffers.Offset} offset");
|
||||
code += object_name + ".finish" + struct_def.name + "Buffer";
|
||||
code += " = function(builder, offset) {\n";
|
||||
code += " builder.finish(offset";
|
||||
if (!parser.file_identifier_.empty()) {
|
||||
code += ", '" + parser.file_identifier_ + "'";
|
||||
}
|
||||
code += ");\n";
|
||||
code += "};\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
// Iterate through all definitions we haven't generate code for (enums, structs,
|
||||
// and tables) and output them to a single file.
|
||||
std::string GenerateJS(const Parser &parser,
|
||||
const GeneratorOptions &opts) {
|
||||
using namespace js;
|
||||
|
||||
// Generate code for all the enum declarations.
|
||||
std::string enum_code, exports_code;
|
||||
for (auto it = parser.enums_.vec.begin();
|
||||
it != parser.enums_.vec.end(); ++it) {
|
||||
GenEnum(**it, &enum_code, &exports_code);
|
||||
}
|
||||
|
||||
// Generate code for all structs, then all tables.
|
||||
std::string decl_code;
|
||||
for (auto it = parser.structs_.vec.begin();
|
||||
it != parser.structs_.vec.end(); ++it) {
|
||||
GenStruct(parser, **it, &decl_code, &exports_code);
|
||||
}
|
||||
|
||||
// Only output file-level code if there were any declarations.
|
||||
if (enum_code.length() || decl_code.length()) {
|
||||
std::string code;
|
||||
code = "// automatically generated by the FlatBuffers compiler,"
|
||||
" do not modify\n\n";
|
||||
|
||||
// Generate code for all the namespace declarations.
|
||||
GenNamespaces(parser, &code, &exports_code);
|
||||
|
||||
// Output the main declaration code from above.
|
||||
code += enum_code;
|
||||
code += decl_code;
|
||||
|
||||
if (!exports_code.empty() && !opts.skip_js_exports) {
|
||||
code += "// Exports for Node.js and RequireJS\n";
|
||||
code += exports_code;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
static std::string GeneratedFileName(const std::string &path,
|
||||
const std::string &file_name) {
|
||||
return path + file_name + "_generated.js";
|
||||
}
|
||||
|
||||
bool GenerateJS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name,
|
||||
const GeneratorOptions &opts) {
|
||||
auto code = GenerateJS(parser, opts);
|
||||
return !code.length() ||
|
||||
SaveFile(GeneratedFileName(path, file_name).c_str(), code, false);
|
||||
}
|
||||
|
||||
std::string JSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name,
|
||||
const GeneratorOptions & /*opts*/) {
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(file_name));
|
||||
std::string make_rule = GeneratedFileName(path, filebase) + ": ";
|
||||
auto included_files = parser.GetIncludedFilesRecursive(file_name);
|
||||
for (auto it = included_files.begin();
|
||||
it != included_files.end(); ++it) {
|
||||
make_rule += " " + *it;
|
||||
}
|
||||
return make_rule;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
|
@ -0,0 +1,276 @@
|
|||
// Run this using JavaScriptTest.sh
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
var flatbuffers = require('../js/flatbuffers').flatbuffers;
|
||||
var MyGame = require('./monster_test_generated').MyGame;
|
||||
|
||||
function main() {
|
||||
|
||||
// First, let's test reading a FlatBuffer generated by C++ code:
|
||||
// This file was generated from monsterdata_test.json
|
||||
var data = new Uint8Array(fs.readFileSync('monsterdata_test.mon'));
|
||||
|
||||
// Now test it:
|
||||
|
||||
var bb = new flatbuffers.ByteBuffer(data);
|
||||
testBuffer(bb);
|
||||
|
||||
// Second, let's create a FlatBuffer from scratch in JavaScript, and test it also.
|
||||
// We use an initial size of 1 to exercise the reallocation algorithm,
|
||||
// normally a size larger than the typical FlatBuffer you generate would be
|
||||
// better for performance.
|
||||
var fbb = new flatbuffers.Builder(1);
|
||||
|
||||
// We set up the same values as monsterdata.json:
|
||||
|
||||
var str = fbb.createString('MyMonster');
|
||||
|
||||
var inv = MyGame.Example.Monster.createInventoryVector(fbb, [0, 1, 2, 3, 4]);
|
||||
|
||||
var fred = fbb.createString('Fred');
|
||||
MyGame.Example.Monster.startMonster(fbb);
|
||||
MyGame.Example.Monster.addName(fbb, fred);
|
||||
var mon2 = MyGame.Example.Monster.endMonster(fbb);
|
||||
|
||||
MyGame.Example.Monster.startTest4Vector(fbb, 2);
|
||||
MyGame.Example.Test.createTest(fbb, 10, 20);
|
||||
MyGame.Example.Test.createTest(fbb, 30, 40);
|
||||
var test4 = fbb.endVector();
|
||||
|
||||
var testArrayOfString = MyGame.Example.Monster.createTestarrayofstringVector(fbb, [
|
||||
fbb.createString('test1'),
|
||||
fbb.createString('test2')
|
||||
]);
|
||||
|
||||
MyGame.Example.Monster.startMonster(fbb);
|
||||
MyGame.Example.Monster.addPos(fbb, MyGame.Example.Vec3.createVec3(fbb, 1, 2, 3, 3, MyGame.Example.Color.Green, 5, 6));
|
||||
MyGame.Example.Monster.addHp(fbb, 80);
|
||||
MyGame.Example.Monster.addName(fbb, str);
|
||||
MyGame.Example.Monster.addInventory(fbb, inv);
|
||||
MyGame.Example.Monster.addTestType(fbb, MyGame.Example.Any.Monster);
|
||||
MyGame.Example.Monster.addTest(fbb, mon2);
|
||||
MyGame.Example.Monster.addTest4(fbb, test4);
|
||||
MyGame.Example.Monster.addTestarrayofstring(fbb, testArrayOfString);
|
||||
MyGame.Example.Monster.addTestbool(fbb, false);
|
||||
var mon = MyGame.Example.Monster.endMonster(fbb);
|
||||
|
||||
MyGame.Example.Monster.finishMonsterBuffer(fbb, mon);
|
||||
|
||||
// Write the result to a file for debugging purposes:
|
||||
// Note that the binaries are not necessarily identical, since the JSON
|
||||
// parser may serialize in a slightly different order than the above
|
||||
// JavaScript code. They are functionally equivalent though.
|
||||
|
||||
fs.writeFileSync('monsterdata_javascript_wire.mon', new Buffer(fbb.asUint8Array()));
|
||||
|
||||
// Test it:
|
||||
testBuffer(fbb.dataBuffer());
|
||||
|
||||
testUnicode();
|
||||
fuzzTest1();
|
||||
|
||||
console.log('FlatBuffers test: completed successfully');
|
||||
}
|
||||
|
||||
function testBuffer(bb) {
|
||||
assert.ok(MyGame.Example.Monster.bufferHasIdentifier(bb));
|
||||
|
||||
var monster = MyGame.Example.Monster.getRootAsMonster(bb);
|
||||
|
||||
assert.strictEqual(monster.hp(), 80);
|
||||
assert.strictEqual(monster.mana(), 150); // default
|
||||
|
||||
assert.strictEqual(monster.name(), 'MyMonster');
|
||||
|
||||
var pos = monster.pos();
|
||||
assert.strictEqual(pos.x(), 1);
|
||||
assert.strictEqual(pos.y(), 2);
|
||||
assert.strictEqual(pos.z(), 3);
|
||||
assert.strictEqual(pos.test1(), 3);
|
||||
assert.strictEqual(pos.test2(), MyGame.Example.Color.Green);
|
||||
var t = pos.test3();
|
||||
assert.strictEqual(t.a(), 5);
|
||||
assert.strictEqual(t.b(), 6);
|
||||
|
||||
assert.strictEqual(monster.testType(), MyGame.Example.Any.Monster);
|
||||
var monster2 = new MyGame.Example.Monster();
|
||||
assert.strictEqual(monster.test(monster2) != null, true);
|
||||
assert.strictEqual(monster2.name(), 'Fred');
|
||||
|
||||
assert.strictEqual(monster.inventoryLength(), 5);
|
||||
var invsum = 0;
|
||||
for (var i = 0; i < monster.inventoryLength(); i++) {
|
||||
invsum += monster.inventory(i);
|
||||
}
|
||||
assert.strictEqual(invsum, 10);
|
||||
|
||||
var test_0 = monster.test4(0);
|
||||
var test_1 = monster.test4(1);
|
||||
assert.strictEqual(monster.test4Length(), 2);
|
||||
assert.strictEqual(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
|
||||
|
||||
assert.strictEqual(monster.testarrayofstringLength(), 2);
|
||||
assert.strictEqual(monster.testarrayofstring(0), 'test1');
|
||||
assert.strictEqual(monster.testarrayofstring(1), 'test2');
|
||||
|
||||
assert.strictEqual(monster.testbool(), false);
|
||||
}
|
||||
|
||||
function testUnicode() {
|
||||
var correct = fs.readFileSync('unicode_test.mon');
|
||||
var json = JSON.parse(fs.readFileSync('unicode_test.json', 'utf8'));
|
||||
|
||||
// Test reading
|
||||
var bb = new flatbuffers.ByteBuffer(new Uint8Array(correct));
|
||||
var monster = MyGame.Example.Monster.getRootAsMonster(bb);
|
||||
assert.strictEqual(monster.name(), json.name);
|
||||
assert.deepEqual(new Buffer(monster.name(flatbuffers.Encoding.UTF8_BYTES)), new Buffer(json.name));
|
||||
assert.strictEqual(monster.testarrayoftablesLength(), json.testarrayoftables.length);
|
||||
json.testarrayoftables.forEach(function(table, i) {
|
||||
var value = monster.testarrayoftables(i);
|
||||
assert.strictEqual(value.name(), table.name);
|
||||
assert.deepEqual(new Buffer(value.name(flatbuffers.Encoding.UTF8_BYTES)), new Buffer(table.name));
|
||||
});
|
||||
assert.strictEqual(monster.testarrayofstringLength(), json.testarrayofstring.length);
|
||||
json.testarrayofstring.forEach(function(string, i) {
|
||||
assert.strictEqual(monster.testarrayofstring(i), string);
|
||||
assert.deepEqual(new Buffer(monster.testarrayofstring(i, flatbuffers.Encoding.UTF8_BYTES)), new Buffer(string));
|
||||
});
|
||||
|
||||
// Test writing
|
||||
var fbb = new flatbuffers.Builder();
|
||||
var name = fbb.createString(json.name);
|
||||
var testarrayoftablesOffsets = json.testarrayoftables.map(function(table) {
|
||||
var name = fbb.createString(new Uint8Array(new Buffer(table.name)));
|
||||
MyGame.Example.Monster.startMonster(fbb);
|
||||
MyGame.Example.Monster.addName(fbb, name);
|
||||
return MyGame.Example.Monster.endMonster(fbb);
|
||||
});
|
||||
var testarrayoftablesOffset = MyGame.Example.Monster.createTestarrayoftablesVector(fbb,
|
||||
testarrayoftablesOffsets);
|
||||
var testarrayofstringOffset = MyGame.Example.Monster.createTestarrayofstringVector(fbb,
|
||||
json.testarrayofstring.map(function(string) { return fbb.createString(string); }));
|
||||
MyGame.Example.Monster.startMonster(fbb);
|
||||
MyGame.Example.Monster.addTestarrayofstring(fbb, testarrayofstringOffset);
|
||||
MyGame.Example.Monster.addTestarrayoftables(fbb, testarrayoftablesOffset);
|
||||
MyGame.Example.Monster.addName(fbb, name);
|
||||
MyGame.Example.Monster.finishMonsterBuffer(fbb, MyGame.Example.Monster.endMonster(fbb));
|
||||
assert.deepEqual(new Buffer(fbb.asUint8Array()), correct);
|
||||
}
|
||||
|
||||
var __imul = Math.imul ? Math.imul : function(a, b) {
|
||||
var ah = a >> 16 & 65535;
|
||||
var bh = b >> 16 & 65535;
|
||||
var al = a & 65535;
|
||||
var bl = b & 65535;
|
||||
return al * bl + (ah * bl + al * bh << 16) | 0;
|
||||
};
|
||||
|
||||
// Include simple random number generator to ensure results will be the
|
||||
// same cross platform.
|
||||
// http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
|
||||
var lcg_seed = 48271;
|
||||
|
||||
function lcg_rand() {
|
||||
return lcg_seed = (__imul(lcg_seed, 279470273) >>> 0) % 4294967291;
|
||||
}
|
||||
|
||||
function lcg_reset() {
|
||||
lcg_seed = 48271;
|
||||
}
|
||||
|
||||
// Converts a Field ID to a virtual table offset.
|
||||
function fieldIndexToOffset(field_id) {
|
||||
// Should correspond to what EndTable() below builds up.
|
||||
var fixed_fields = 2; // Vtable size and Object Size.
|
||||
return (field_id + fixed_fields) * 2;
|
||||
}
|
||||
|
||||
// Low level stress/fuzz test: serialize/deserialize a variety of
|
||||
// different kinds of data in different combinations
|
||||
function fuzzTest1() {
|
||||
|
||||
// Values we're testing against: chosen to ensure no bits get chopped
|
||||
// off anywhere, and also be different from eachother.
|
||||
var bool_val = true;
|
||||
var char_val = -127; // 0x81
|
||||
var uchar_val = 0xFF;
|
||||
var short_val = -32222; // 0x8222;
|
||||
var ushort_val = 0xFEEE;
|
||||
var int_val = 0x83333333 | 0;
|
||||
var uint_val = 0xFDDDDDDD;
|
||||
var long_val = new flatbuffers.Long(0x44444444, 0x84444444);
|
||||
var ulong_val = new flatbuffers.Long(0xCCCCCCCC, 0xFCCCCCCC);
|
||||
var float_val = new Float32Array([3.14159])[0];
|
||||
var double_val = 3.14159265359;
|
||||
|
||||
var test_values_max = 11;
|
||||
var fields_per_object = 4;
|
||||
var num_fuzz_objects = 10000; // The higher, the more thorough :)
|
||||
|
||||
var builder = new flatbuffers.Builder();
|
||||
|
||||
lcg_reset(); // Keep it deterministic.
|
||||
|
||||
var objects = [];
|
||||
|
||||
// Generate num_fuzz_objects random objects each consisting of
|
||||
// fields_per_object fields, each of a random type.
|
||||
for (var i = 0; i < num_fuzz_objects; i++) {
|
||||
builder.startObject(fields_per_object);
|
||||
for (var f = 0; f < fields_per_object; f++) {
|
||||
var choice = lcg_rand() % test_values_max;
|
||||
switch (choice) {
|
||||
case 0: builder.addFieldInt8(f, bool_val, 0); break;
|
||||
case 1: builder.addFieldInt8(f, char_val, 0); break;
|
||||
case 2: builder.addFieldInt8(f, uchar_val, 0); break;
|
||||
case 3: builder.addFieldInt16(f, short_val, 0); break;
|
||||
case 4: builder.addFieldInt16(f, ushort_val, 0); break;
|
||||
case 5: builder.addFieldInt32(f, int_val, 0); break;
|
||||
case 6: builder.addFieldInt32(f, uint_val, 0); break;
|
||||
case 7: builder.addFieldInt64(f, long_val, flatbuffers.Long.ZERO); break;
|
||||
case 8: builder.addFieldInt64(f, ulong_val, flatbuffers.Long.ZERO); break;
|
||||
case 9: builder.addFieldFloat32(f, float_val, 0); break;
|
||||
case 10: builder.addFieldFloat64(f, double_val, 0); break;
|
||||
}
|
||||
}
|
||||
objects.push(builder.endObject());
|
||||
}
|
||||
builder.prep(8, 0); // Align whole buffer.
|
||||
|
||||
lcg_reset(); // Reset.
|
||||
|
||||
builder.finish(objects[objects.length - 1]);
|
||||
var bytes = new Uint8Array(builder.asUint8Array());
|
||||
var view = new DataView(bytes.buffer);
|
||||
|
||||
// Test that all objects we generated are readable and return the
|
||||
// expected values. We generate random objects in the same order
|
||||
// so this is deterministic.
|
||||
for (var i = 0; i < num_fuzz_objects; i++) {
|
||||
var offset = bytes.length - objects[i];
|
||||
for (var f = 0; f < fields_per_object; f++) {
|
||||
var choice = lcg_rand() % test_values_max;
|
||||
var vtable_offset = fieldIndexToOffset(f);
|
||||
var vtable = offset - view.getInt32(offset, true);
|
||||
assert.ok(vtable_offset < view.getInt16(vtable, true));
|
||||
var field_offset = offset + view.getInt16(vtable + vtable_offset, true);
|
||||
switch (choice) {
|
||||
case 0: assert.strictEqual(!!view.getInt8(field_offset), bool_val); break;
|
||||
case 1: assert.strictEqual(view.getInt8(field_offset), char_val); break;
|
||||
case 2: assert.strictEqual(view.getUint8(field_offset), uchar_val); break;
|
||||
case 3: assert.strictEqual(view.getInt16(field_offset, true), short_val); break;
|
||||
case 4: assert.strictEqual(view.getUint16(field_offset, true), ushort_val); break;
|
||||
case 5: assert.strictEqual(view.getInt32(field_offset, true), int_val); break;
|
||||
case 6: assert.strictEqual(view.getUint32(field_offset, true), uint_val); break;
|
||||
case 7: assert.strictEqual(view.getInt32(field_offset, true), long_val.low); assert.strictEqual(view.getInt32(field_offset + 4, true), long_val.high); break;
|
||||
case 8: assert.strictEqual(view.getInt32(field_offset, true), ulong_val.low); assert.strictEqual(view.getInt32(field_offset + 4, true), ulong_val.high); break;
|
||||
case 9: assert.strictEqual(view.getFloat32(field_offset, true), float_val); break;
|
||||
case 10: assert.strictEqual(view.getFloat64(field_offset, true), double_val); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
pushd "$(dirname $0)" >/dev/null
|
||||
../flatc -b monster_test.fbs unicode_test.json
|
||||
node JavaScriptTest
|
|
@ -1,2 +1,2 @@
|
|||
../flatc -c -j -n -g -b -p --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
|
||||
../flatc -c -j -n -g -b -p -s --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
|
||||
../flatc -b --schema monster_test.fbs
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,985 @@
|
|||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
var MyGame = MyGame || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
MyGame.Example = MyGame.Example || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
MyGame.OtherNameSpace = MyGame.OtherNameSpace || {};
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*/
|
||||
MyGame.Example.Color = {
|
||||
Red: 1,
|
||||
Green: 2,
|
||||
Blue: 8
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*/
|
||||
MyGame.Example.Any = {
|
||||
NONE: 0,
|
||||
Monster: 1,
|
||||
TestSimpleTableWithEnum: 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.Test = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.Test}
|
||||
*/
|
||||
MyGame.Example.Test.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Test.prototype.a = function() {
|
||||
return this.bb.readInt16(this.bb_pos);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Test.prototype.b = function() {
|
||||
return this.bb.readInt8(this.bb_pos + 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Test.createTest = function(builder, a, b) {
|
||||
builder.prep(2, 4);
|
||||
builder.pad(1);
|
||||
builder.writeInt8(b);
|
||||
builder.writeInt16(a);
|
||||
return builder.offset();
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.TestSimpleTableWithEnum}
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @param {MyGame.Example.TestSimpleTableWithEnum=} obj
|
||||
* @returns {MyGame.Example.TestSimpleTableWithEnum}
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.getRootAsTestSimpleTableWithEnum = function(bb, obj) {
|
||||
return (obj || new MyGame.Example.TestSimpleTableWithEnum).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {MyGame.Example.Color}
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.prototype.color = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Green;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.startTestSimpleTableWithEnum = function(builder) {
|
||||
builder.startObject(1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {MyGame.Example.Color} color
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.addColor = function(builder, color) {
|
||||
builder.addFieldInt8(0, color, MyGame.Example.Color.Green);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.TestSimpleTableWithEnum.endTestSimpleTableWithEnum = function(builder) {
|
||||
var offset = builder.endObject();
|
||||
return offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.Vec3 = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.Vec3}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.x = function() {
|
||||
return this.bb.readFloat32(this.bb_pos);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.y = function() {
|
||||
return this.bb.readFloat32(this.bb_pos + 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.z = function() {
|
||||
return this.bb.readFloat32(this.bb_pos + 8);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.test1 = function() {
|
||||
return this.bb.readFloat64(this.bb_pos + 16);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {MyGame.Example.Color}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.test2 = function() {
|
||||
return /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + 24));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Test=} obj
|
||||
* @returns {MyGame.Example.Test}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.test3 = function(obj) {
|
||||
return (obj || new MyGame.Example.Test).__init(this.bb_pos + 26, this.bb);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @param {number} z
|
||||
* @param {number} test1
|
||||
* @param {MyGame.Example.Color} test2
|
||||
* @param {number} test3_a
|
||||
* @param {number} test3_b
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Vec3.createVec3 = function(builder, x, y, z, test1, test2, test3_a, test3_b) {
|
||||
builder.prep(16, 32);
|
||||
builder.pad(2);
|
||||
builder.prep(2, 4);
|
||||
builder.pad(1);
|
||||
builder.writeInt8(test3_b);
|
||||
builder.writeInt16(test3_a);
|
||||
builder.pad(1);
|
||||
builder.writeInt8(test2);
|
||||
builder.writeFloat64(test1);
|
||||
builder.pad(4);
|
||||
builder.writeFloat32(z);
|
||||
builder.writeFloat32(y);
|
||||
builder.writeFloat32(x);
|
||||
return builder.offset();
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.Stat = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.Stat}
|
||||
*/
|
||||
MyGame.Example.Stat.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @param {MyGame.Example.Stat=} obj
|
||||
* @returns {MyGame.Example.Stat}
|
||||
*/
|
||||
MyGame.Example.Stat.getRootAsStat = function(bb, obj) {
|
||||
return (obj || new MyGame.Example.Stat).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Encoding=} optionalEncoding
|
||||
* @returns {string|Uint8Array}
|
||||
*/
|
||||
MyGame.Example.Stat.prototype.id = function(optionalEncoding) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {flatbuffers.Long}
|
||||
*/
|
||||
MyGame.Example.Stat.prototype.val = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Stat.prototype.count = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb.readUint16(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
*/
|
||||
MyGame.Example.Stat.startStat = function(builder) {
|
||||
builder.startObject(3);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} idOffset
|
||||
*/
|
||||
MyGame.Example.Stat.addId = function(builder, idOffset) {
|
||||
builder.addFieldOffset(0, idOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Long} val
|
||||
*/
|
||||
MyGame.Example.Stat.addVal = function(builder, val) {
|
||||
builder.addFieldInt64(1, val, flatbuffers.Long.ZERO);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} count
|
||||
*/
|
||||
MyGame.Example.Stat.addCount = function(builder, count) {
|
||||
builder.addFieldInt16(2, count, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Stat.endStat = function(builder) {
|
||||
var offset = builder.endObject();
|
||||
return offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.Monster = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.Monster}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @param {MyGame.Example.Monster=} obj
|
||||
* @returns {MyGame.Example.Monster}
|
||||
*/
|
||||
MyGame.Example.Monster.getRootAsMonster = function(bb, obj) {
|
||||
return (obj || new MyGame.Example.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {boolean}
|
||||
*/
|
||||
MyGame.Example.Monster.bufferHasIdentifier = function(bb) {
|
||||
return bb.__has_identifier('MONS');
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Vec3=} obj
|
||||
* @returns {MyGame.Example.Vec3}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.pos = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new MyGame.Example.Vec3).__init(this.bb_pos + offset, this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.mana = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb.readInt16(this.bb_pos + offset) : 150;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.hp = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb.readInt16(this.bb_pos + offset) : 100;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Encoding=} optionalEncoding
|
||||
* @returns {string|Uint8Array}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.name = function(optionalEncoding) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.inventory = function(index) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.inventoryLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {MyGame.Example.Color}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.color = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 16);
|
||||
return offset ? /** @type {MyGame.Example.Color} */ (this.bb.readInt8(this.bb_pos + offset)) : MyGame.Example.Color.Blue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {MyGame.Example.Any}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testType = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 18);
|
||||
return offset ? /** @type {MyGame.Example.Any} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.Any.NONE;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Table} obj
|
||||
* @returns {?flatbuffers.Table}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.test = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 20);
|
||||
return offset ? this.bb.__union(obj, this.bb_pos + offset) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @param {MyGame.Example.Test=} obj
|
||||
* @returns {MyGame.Example.Test}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.test4 = function(index, obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 22);
|
||||
return offset ? (obj || new MyGame.Example.Test).__init(this.bb.__vector(this.bb_pos + offset) + index * 4, this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.test4Length = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 22);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @param {flatbuffers.Encoding=} optionalEncoding
|
||||
* @returns {string|Uint8Array}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofstring = function(index, optionalEncoding) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 24);
|
||||
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofstringLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 24);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* an example documentation comment: this will end up in the generated code
|
||||
* multiline too
|
||||
*
|
||||
* @param {number} index
|
||||
* @param {MyGame.Example.Monster=} obj
|
||||
* @returns {MyGame.Example.Monster}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayoftables = function(index, obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 26);
|
||||
return offset ? (obj || new MyGame.Example.Monster).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayoftablesLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 26);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Monster=} obj
|
||||
* @returns {MyGame.Example.Monster}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.enemy = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 28);
|
||||
return offset ? (obj || new MyGame.Example.Monster).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testnestedflatbuffer = function(index) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 30);
|
||||
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testnestedflatbufferLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 30);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Stat=} obj
|
||||
* @returns {MyGame.Example.Stat}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testempty = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 32);
|
||||
return offset ? (obj || new MyGame.Example.Stat).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testbool = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 34);
|
||||
return offset ? !!this.bb.readInt8(this.bb_pos + offset) : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashs32Fnv1 = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 36);
|
||||
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashu32Fnv1 = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 38);
|
||||
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {flatbuffers.Long}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashs64Fnv1 = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 40);
|
||||
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {flatbuffers.Long}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashu64Fnv1 = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 42);
|
||||
return offset ? this.bb.readUint64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashs32Fnv1a = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 44);
|
||||
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashu32Fnv1a = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 46);
|
||||
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {flatbuffers.Long}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashs64Fnv1a = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 48);
|
||||
return offset ? this.bb.readInt64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {flatbuffers.Long}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testhashu64Fnv1a = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 50);
|
||||
return offset ? this.bb.readUint64(this.bb_pos + offset) : flatbuffers.Long.ZERO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofbools = function(index) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 52);
|
||||
return offset ? !!this.bb.readInt8(this.bb.__vector(this.bb_pos + offset) + index) : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofboolsLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 52);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
*/
|
||||
MyGame.Example.Monster.startMonster = function(builder) {
|
||||
builder.startObject(25);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} posOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addPos = function(builder, posOffset) {
|
||||
builder.addFieldStruct(0, posOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} mana
|
||||
*/
|
||||
MyGame.Example.Monster.addMana = function(builder, mana) {
|
||||
builder.addFieldInt16(1, mana, 150);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} hp
|
||||
*/
|
||||
MyGame.Example.Monster.addHp = function(builder, hp) {
|
||||
builder.addFieldInt16(2, hp, 100);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} nameOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addName = function(builder, nameOffset) {
|
||||
builder.addFieldOffset(3, nameOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} inventoryOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addInventory = function(builder, inventoryOffset) {
|
||||
builder.addFieldOffset(5, inventoryOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<number>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createInventoryVector = function(builder, data) {
|
||||
builder.startVector(1, data.length, 1);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addInt8(data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startInventoryVector = function(builder, numElems) {
|
||||
builder.startVector(1, numElems, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {MyGame.Example.Color} color
|
||||
*/
|
||||
MyGame.Example.Monster.addColor = function(builder, color) {
|
||||
builder.addFieldInt8(6, color, MyGame.Example.Color.Blue);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {MyGame.Example.Any} testType
|
||||
*/
|
||||
MyGame.Example.Monster.addTestType = function(builder, testType) {
|
||||
builder.addFieldInt8(7, testType, MyGame.Example.Any.NONE);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTest = function(builder, testOffset) {
|
||||
builder.addFieldOffset(8, testOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} test4Offset
|
||||
*/
|
||||
MyGame.Example.Monster.addTest4 = function(builder, test4Offset) {
|
||||
builder.addFieldOffset(9, test4Offset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTest4Vector = function(builder, numElems) {
|
||||
builder.startVector(4, numElems, 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testarrayofstringOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestarrayofstring = function(builder, testarrayofstringOffset) {
|
||||
builder.addFieldOffset(10, testarrayofstringOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<flatbuffers.Offset>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createTestarrayofstringVector = function(builder, data) {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTestarrayofstringVector = function(builder, numElems) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testarrayoftablesOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestarrayoftables = function(builder, testarrayoftablesOffset) {
|
||||
builder.addFieldOffset(11, testarrayoftablesOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<flatbuffers.Offset>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createTestarrayoftablesVector = function(builder, data) {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTestarrayoftablesVector = function(builder, numElems) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} enemyOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addEnemy = function(builder, enemyOffset) {
|
||||
builder.addFieldOffset(12, enemyOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testnestedflatbufferOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestnestedflatbuffer = function(builder, testnestedflatbufferOffset) {
|
||||
builder.addFieldOffset(13, testnestedflatbufferOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<number>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createTestnestedflatbufferVector = function(builder, data) {
|
||||
builder.startVector(1, data.length, 1);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addInt8(data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTestnestedflatbufferVector = function(builder, numElems) {
|
||||
builder.startVector(1, numElems, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testemptyOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestempty = function(builder, testemptyOffset) {
|
||||
builder.addFieldOffset(14, testemptyOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {boolean} testbool
|
||||
*/
|
||||
MyGame.Example.Monster.addTestbool = function(builder, testbool) {
|
||||
builder.addFieldInt8(15, +testbool, +false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} testhashs32Fnv1
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashs32Fnv1 = function(builder, testhashs32Fnv1) {
|
||||
builder.addFieldInt32(16, testhashs32Fnv1, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} testhashu32Fnv1
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashu32Fnv1 = function(builder, testhashu32Fnv1) {
|
||||
builder.addFieldInt32(17, testhashu32Fnv1, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Long} testhashs64Fnv1
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashs64Fnv1 = function(builder, testhashs64Fnv1) {
|
||||
builder.addFieldInt64(18, testhashs64Fnv1, flatbuffers.Long.ZERO);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Long} testhashu64Fnv1
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashu64Fnv1 = function(builder, testhashu64Fnv1) {
|
||||
builder.addFieldInt64(19, testhashu64Fnv1, flatbuffers.Long.ZERO);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} testhashs32Fnv1a
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashs32Fnv1a = function(builder, testhashs32Fnv1a) {
|
||||
builder.addFieldInt32(20, testhashs32Fnv1a, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} testhashu32Fnv1a
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashu32Fnv1a = function(builder, testhashu32Fnv1a) {
|
||||
builder.addFieldInt32(21, testhashu32Fnv1a, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Long} testhashs64Fnv1a
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashs64Fnv1a = function(builder, testhashs64Fnv1a) {
|
||||
builder.addFieldInt64(22, testhashs64Fnv1a, flatbuffers.Long.ZERO);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Long} testhashu64Fnv1a
|
||||
*/
|
||||
MyGame.Example.Monster.addTesthashu64Fnv1a = function(builder, testhashu64Fnv1a) {
|
||||
builder.addFieldInt64(23, testhashu64Fnv1a, flatbuffers.Long.ZERO);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testarrayofboolsOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestarrayofbools = function(builder, testarrayofboolsOffset) {
|
||||
builder.addFieldOffset(24, testarrayofboolsOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<boolean>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createTestarrayofboolsVector = function(builder, data) {
|
||||
builder.startVector(1, data.length, 1);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addInt8(+data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTestarrayofboolsVector = function(builder, numElems) {
|
||||
builder.startVector(1, numElems, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.endMonster = function(builder) {
|
||||
var offset = builder.endObject();
|
||||
builder.requiredField(offset, 10); // name
|
||||
return offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} offset
|
||||
*/
|
||||
MyGame.Example.Monster.finishMonsterBuffer = function(builder, offset) {
|
||||
builder.finish(offset, 'MONS');
|
||||
};
|
||||
|
||||
// Exports for Node.js and RequireJS
|
||||
this.MyGame = MyGame;
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "unicode_test",
|
||||
"testarrayoftables": [
|
||||
{ "name": "Цлїςσδε" },
|
||||
{ "name": "フムアムカモケモ" },
|
||||
{ "name": "フムヤムカモケモ" },
|
||||
{ "name": "㊀㊁㊂㊃㊄" },
|
||||
{ "name": "☳☶☲" },
|
||||
{ "name": "𡇙𝌆" }
|
||||
],
|
||||
"testarrayofstring": [
|
||||
"Цлїςσδε",
|
||||
"フムアムカモケモ",
|
||||
"フムヤムカモケモ",
|
||||
"㊀㊁㊂㊃㊄",
|
||||
"☳☶☲",
|
||||
"𡇙𝌆"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue