LIBS: updated flatbuffers

master
Martin Gerhardy 2022-02-06 15:06:39 +01:00
parent b1eaaffb7d
commit 42d0b14d96
28 changed files with 1168 additions and 1020 deletions

View File

@ -19,7 +19,6 @@
#include <list>
#include <sstream>
#include "bfbs_gen_lua.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
@ -65,7 +64,7 @@ const static FlatCOption options[] = {
{ "I", "", "PATH", "Search for includes in the specified path." },
{ "M", "", "", "Print make rules for generated files." },
{ "", "version", "", "Print the version number of flatc and exit." },
{ "", "help", "", "Prints this help text and exit." },
{ "h", "help", "", "Prints this help text and exit." },
{ "", "string-json", "",
"Strict JSON: field names must be / will be quoted, no trailing commas in "
"tables/vectors." },
@ -184,6 +183,8 @@ const static FlatCOption options[] = {
{ "", "reflect-types", "",
"Add minimal type reflection to code generation." },
{ "", "reflect-names", "", "Add minimal type/name reflection." },
{ "", "rust-serialize", "",
"Implement serde::Serialize on generated Rust types." },
{ "", "root-type", "T", "Select or override the default root_type." },
{ "", "require-explicit-ids", "",
"When parsing schemas, require explicit ids (id: x)." },
@ -199,6 +200,7 @@ const static FlatCOption options[] = {
"Used with \"binary\" and \"json\" options, it generates data using "
"schema-less FlexBuffers." },
{ "", "no-warnings", "", "Inhibit all warnings messages." },
{ "", "warning-as-errors", "", "Treat all warnings as errors." },
{ "", "cs-global-alias", "",
"Prepend \"global::\" to all user generated csharp classes and "
"structs." },
@ -268,6 +270,35 @@ static void AppendOption(std::stringstream &ss, const FlatCOption &option,
ss << "\n";
}
static void AppendShortOption(std::stringstream &ss,
const FlatCOption &option) {
if (!option.short_opt.empty()) {
ss << "-" << option.short_opt;
if (!option.long_opt.empty()) { ss << "|"; }
}
if (!option.long_opt.empty()) { ss << "--" << option.long_opt; }
}
std::string FlatCompiler::GetShortUsageString(const char *program_name) const {
std::stringstream ss;
ss << "Usage: " << program_name << " [";
for (size_t i = 0; i < params_.num_generators; ++i) {
const Generator &g = params_.generators[i];
AppendShortOption(ss, g.option);
ss << ", ";
}
for (const FlatCOption &option : options) {
AppendShortOption(ss, option);
ss << ", ";
}
ss.seekp(-2, ss.cur);
ss << "]... FILE... [-- FILE...]";
std::string help = ss.str();
std::stringstream ss_textwrap;
AppendTextWrappedString(ss_textwrap, help, 80, 0);
return ss_textwrap.str();
}
std::string FlatCompiler::GetUsageString(const char *program_name) const {
std::stringstream ss;
ss << "Usage: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
@ -299,6 +330,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
return 0;
}
if (argc <= 1) { Error("Need to provide at least one argument."); }
flatbuffers::IDLOptions opts;
std::string output_path;
@ -453,7 +486,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--version") {
printf("flatc version %s\n", FLATC_VERSION());
exit(0);
} else if (arg == "--help") {
} else if (arg == "--help" || arg == "-h") {
printf("%s\n", GetUsageString(program_name).c_str());
exit(0);
} else if (arg == "--grpc") {
@ -468,6 +501,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.mini_reflect = IDLOptions::kTypes;
} else if (arg == "--reflect-names") {
opts.mini_reflect = IDLOptions::kTypesAndNames;
} else if (arg == "--rust-serialize") {
opts.rust_serialize = true;
} else if (arg == "--require-explicit-ids") {
opts.require_explicit_ids = true;
} else if (arg == "--root-type") {
@ -496,6 +531,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.gen_jvmstatic = true;
} else if (arg == "--no-warnings") {
opts.no_warnings = true;
} else if (arg == "--warnings-as-errors") {
opts.warnings_as_errors = true;
} else if (arg == "--cpp-std") {
if (++argi >= argc)
Error("missing C++ standard specification" + arg, true);
@ -729,9 +766,19 @@ int FlatCompiler::Compile(int argc, const char **argv) {
// in any files coming up next.
parser->MarkGenerated();
}
if (opts.lang_to_generate & IDLOptions::kRust && !parser->opts.one_file) {
GenerateRustModuleRootFile(*parser, output_path);
// Once all the files have been parsed, run any generators Parsing Completed
// function for final generation.
for (size_t i = 0; i < params_.num_generators; ++i) {
if (generator_enabled[i] &&
params_.generators[i].parsing_completed != nullptr) {
if (!params_.generators[i].parsing_completed(*parser, output_path)) {
Error("failed running parsing completed for " +
std::string(params_.generators[i].lang_name));
}
}
}
return 0;
}

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <cstdio>
#include <memory>
#include "bfbs_gen_lua.h"
@ -27,16 +28,16 @@ static void Warn(const flatbuffers::FlatCompiler *flatc,
const std::string &warn, bool show_exe_name) {
(void)flatc;
if (show_exe_name) { printf("%s: ", g_program_name); }
fprintf(stderr, "warning:\n %s\n\n", warn.c_str());
fprintf(stderr, "\nwarning:\n %s\n\n", warn.c_str());
}
static void Error(const flatbuffers::FlatCompiler *flatc,
const std::string &err, bool usage, bool show_exe_name) {
if (show_exe_name) { printf("%s: ", g_program_name); }
if (usage && flatc) {
fprintf(stderr, "%s\n", flatc->GetUsageString(g_program_name).c_str());
fprintf(stderr, "%s\n", flatc->GetShortUsageString(g_program_name).c_str());
}
fprintf(stderr, "error:\n %s\n\n", err.c_str());
fprintf(stderr, "\nerror:\n %s\n\n", err.c_str());
exit(1);
}
@ -67,82 +68,83 @@ int main(int argc, const char *argv[]) {
flatbuffers::FlatCOption{
"b", "binary", "",
"Generate wire format binaries for any data definitions" },
flatbuffers::BinaryMakeRule, nullptr },
flatbuffers::BinaryMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateTextFile, "text", false, nullptr,
flatbuffers::IDLOptions::kJson,
flatbuffers::FlatCOption{
"t", "json", "", "Generate text output for any data definitions" },
flatbuffers::TextMakeRule, nullptr },
flatbuffers::TextMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateCPP, "C++", true, flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kCpp,
flatbuffers::FlatCOption{ "c", "cpp", "",
"Generate C++ headers for tables/structs" },
flatbuffers::CPPMakeRule, nullptr },
flatbuffers::CPPMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateGo, "Go", true, flatbuffers::GenerateGoGRPC,
flatbuffers::IDLOptions::kGo,
flatbuffers::FlatCOption{ "g", "go", "",
"Generate Go files for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateJava, "Java", true, flatbuffers::GenerateJavaGRPC,
flatbuffers::IDLOptions::kJava,
flatbuffers::FlatCOption{ "j", "java", "",
"Generate Java classes for tables/structs" },
flatbuffers::JavaMakeRule, nullptr },
flatbuffers::JavaMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateDart, "Dart", true, nullptr,
flatbuffers::IDLOptions::kDart,
flatbuffers::FlatCOption{ "d", "dart", "",
"Generate Dart classes for tables/structs" },
flatbuffers::DartMakeRule, nullptr },
flatbuffers::DartMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateTS, "TypeScript", true, flatbuffers::GenerateTSGRPC,
flatbuffers::IDLOptions::kTs,
flatbuffers::FlatCOption{ "T", "ts", "",
"Generate TypeScript code for tables/structs" },
flatbuffers::TSMakeRule, nullptr },
flatbuffers::TSMakeRule, nullptr, nullptr },
{ flatbuffers::GenerateCSharp, "C#", true, nullptr,
flatbuffers::IDLOptions::kCSharp,
flatbuffers::FlatCOption{ "n", "csharp", "",
"Generate C# classes for tables/structs" },
flatbuffers::CSharpMakeRule, nullptr },
flatbuffers::CSharpMakeRule, nullptr, nullptr },
{ flatbuffers::GeneratePython, "Python", true,
flatbuffers::GeneratePythonGRPC, flatbuffers::IDLOptions::kPython,
flatbuffers::FlatCOption{ "p", "python", "",
"Generate Python files for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateLobster, "Lobster", true, nullptr,
flatbuffers::IDLOptions::kLobster,
flatbuffers::FlatCOption{ "", "lobster", "",
"Generate Lobster files for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateLua, "Lua", true, nullptr,
flatbuffers::IDLOptions::kLua,
flatbuffers::FlatCOption{ "l", "lua", "",
"Generate Lua files for tables/structs" },
nullptr, bfbs_gen_lua.get() },
nullptr, bfbs_gen_lua.get(), nullptr },
{ flatbuffers::GenerateRust, "Rust", true, nullptr,
flatbuffers::IDLOptions::kRust,
flatbuffers::FlatCOption{ "r", "rust", "",
"Generate Rust files for tables/structs" },
flatbuffers::RustMakeRule, nullptr },
flatbuffers::RustMakeRule, nullptr,
flatbuffers::GenerateRustModuleRootFile },
{ flatbuffers::GeneratePhp, "PHP", true, nullptr,
flatbuffers::IDLOptions::kPhp,
flatbuffers::FlatCOption{ "", "php", "",
"Generate PHP files for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateKotlin, "Kotlin", true, nullptr,
flatbuffers::IDLOptions::kKotlin,
flatbuffers::FlatCOption{ "", "kotlin", "",
"Generate Kotlin classes for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateJsonSchema, "JsonSchema", true, nullptr,
flatbuffers::IDLOptions::kJsonSchema,
flatbuffers::FlatCOption{ "", "jsonschema", "", "Generate Json schema" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
{ flatbuffers::GenerateSwift, "swift", true, flatbuffers::GenerateSwiftGRPC,
flatbuffers::IDLOptions::kSwift,
flatbuffers::FlatCOption{ "", "swift", "",
"Generate Swift files for tables/structs" },
nullptr, nullptr },
nullptr, nullptr, nullptr },
};
flatbuffers::FlatCompiler::InitParams params;

View File

@ -283,6 +283,9 @@ class CppGenerator : public BaseGenerator {
code_ += "#pragma clang system_header\n\n";
}
code_ += "#include \"flatbuffers/flatbuffers.h\"";
code_ += "";
SetNameSpace(struct_def.defined_namespace);
auto name = Name(struct_def);
code_.SetValue("STRUCT_NAME", name);
@ -532,6 +535,16 @@ class CppGenerator : public BaseGenerator {
code_ += " buf, {{STRUCT_NAME}}Identifier());";
code_ += "}";
code_ += "";
// Check if a size-prefixed buffer has the identifier.
code_ += "inline \\";
code_ +=
"bool SizePrefixed{{STRUCT_NAME}}BufferHasIdentifier(const void "
"*buf) {";
code_ += " return flatbuffers::BufferHasIdentifier(";
code_ += " buf, {{STRUCT_NAME}}Identifier(), true);";
code_ += "}";
code_ += "";
}
// The root verifier.
@ -658,8 +671,9 @@ class CppGenerator : public BaseGenerator {
}
bool VectorElementUserFacing(const Type &type) const {
return opts_.g_cpp_std >= cpp::CPP_STD_17 && opts_.g_only_fixed_enums &&
IsEnum(type);
return (opts_.scoped_enums && IsEnum(type)) ||
(opts_.g_cpp_std >= cpp::CPP_STD_17 && opts_.g_only_fixed_enums &&
IsEnum(type));
}
void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
@ -799,7 +813,7 @@ class CppGenerator : public BaseGenerator {
}
std::string GenTypeNative(const Type &type, bool invector,
const FieldDef &field) {
const FieldDef &field, bool forcopy = false) {
switch (type.base_type) {
case BASE_TYPE_STRING: {
return NativeString(&field);
@ -820,15 +834,14 @@ class CppGenerator : public BaseGenerator {
if (IsStruct(type)) {
auto native_type = type.struct_def->attributes.Lookup("native_type");
if (native_type) { type_name = native_type->constant; }
if (invector || field.native_inline) {
if (invector || field.native_inline || forcopy) {
return type_name;
} else {
return GenTypeNativePtr(type_name, &field, false);
}
} else {
return GenTypeNativePtr(
WrapNativeNameInNameSpace(*type.struct_def, opts_), &field,
false);
const auto nn = WrapNativeNameInNameSpace(*type.struct_def, opts_);
return forcopy ? nn : GenTypeNativePtr(nn, &field, false);
}
}
case BASE_TYPE_UNION: {
@ -1472,7 +1485,7 @@ class CppGenerator : public BaseGenerator {
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (ev.union_type.struct_def->fixed) {
code_.SetValue("ALIGN",
NumToString(ev.union_type.struct_def->minalign));
NumToString(ev.union_type.struct_def->minalign));
code_ +=
" return verifier.VerifyField<{{TYPE}}>("
"static_cast<const uint8_t *>(obj), 0, {{ALIGN}});";
@ -1590,7 +1603,8 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
code_ += " case {{LABEL}}: {";
bool copyable = true;
if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
if (opts_.g_cpp_std < cpp::CPP_STD_11 &&
ev.union_type.base_type == BASE_TYPE_STRUCT &&
!ev.union_type.struct_def->fixed) {
// Don't generate code to copy if table is not copyable.
// TODO(wvo): make tables copyable instead.
@ -1793,13 +1807,50 @@ class CppGenerator : public BaseGenerator {
}
}
// Returns true if `struct_def` needs a copy constructor and assignment
// operator because it has one or more table members, struct members with a
// custom cpp_type and non-naked pointer type, or vector members of those.
bool NeedsCopyCtorAssignOp(const StructDef &struct_def) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
const auto &type = field.value.type;
if (field.deprecated) continue;
if (type.base_type == BASE_TYPE_STRUCT) {
const auto cpp_type = field.attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
const bool is_ptr = !(IsStruct(type) && field.native_inline) ||
(cpp_type && cpp_ptr_type->constant != "naked");
if (is_ptr) { return true; }
} else if (IsVector(type)) {
const auto vec_type = type.VectorType();
if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
const auto cpp_type = field.attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
const bool is_ptr =
(vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
(cpp_type && cpp_ptr_type->constant != "naked");
if (is_ptr) { return true; }
}
}
return false;
}
// Generate the default constructor for this struct. Properly initialize all
// scalar members with default values.
void GenDefaultConstructor(const StructDef &struct_def) {
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
// In >= C++11, default member initializers are generated.
if (opts_.g_cpp_std >= cpp::CPP_STD_11) { return; }
// In >= C++11, default member initializers are generated. To allow for
// aggregate initialization, do not emit a default constructor at all, with
// the exception of types that need a copy/move ctors and assignment
// operators.
if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
if (NeedsCopyCtorAssignOp(struct_def)) {
code_ += " {{NATIVE_NAME}}() = default;";
}
return;
}
std::string initializer_list;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@ -1843,6 +1894,125 @@ class CppGenerator : public BaseGenerator {
code_ += " }";
}
// Generate the >= C++11 copy/move constructor and assignment operator
// declarations if required. Tables that are default-copyable do not get
// user-provided copy/move constructors and assignment operators so they
// remain aggregates.
void GenCopyMoveCtorAndAssigOpDecls(const StructDef &struct_def) {
if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
if (!NeedsCopyCtorAssignOp(struct_def)) return;
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
code_ += " {{NATIVE_NAME}}(const {{NATIVE_NAME}} &o);";
code_ +=
" {{NATIVE_NAME}}({{NATIVE_NAME}}&&) FLATBUFFERS_NOEXCEPT = "
"default;";
code_ +=
" {{NATIVE_NAME}} &operator=({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT;";
}
// Generate the >= C++11 copy constructor and assignment operator definitions.
void GenCopyCtorAssignOpDefs(const StructDef &struct_def) {
if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
if (!NeedsCopyCtorAssignOp(struct_def)) return;
std::string initializer_list;
std::string vector_copies;
std::string swaps;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
const auto &type = field.value.type;
if (field.deprecated || type.base_type == BASE_TYPE_UTYPE) continue;
if (type.base_type == BASE_TYPE_STRUCT) {
if (!initializer_list.empty()) { initializer_list += ",\n "; }
const auto cpp_type = field.attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
auto type_name = (cpp_type) ? cpp_type->constant
: GenTypeNative(type, /*invector*/ false,
field, /*forcopy*/ true);
const bool is_ptr = !(IsStruct(type) && field.native_inline) ||
(cpp_type && cpp_ptr_type->constant != "naked");
CodeWriter cw;
cw.SetValue("FIELD", Name(field));
cw.SetValue("TYPE", type_name);
if (is_ptr) {
cw +=
"{{FIELD}}((o.{{FIELD}}) ? new {{TYPE}}(*o.{{FIELD}}) : "
"nullptr)\\";
initializer_list += cw.ToString();
} else {
cw += "{{FIELD}}(o.{{FIELD}})\\";
initializer_list += cw.ToString();
}
} else if (IsVector(type)) {
const auto vec_type = type.VectorType();
if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
const auto cpp_type = field.attributes.Lookup("cpp_type");
const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
const auto type_name = (cpp_type)
? cpp_type->constant
: GenTypeNative(vec_type, /*invector*/ true,
field, /*forcopy*/ true);
const bool is_ptr =
(vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
(cpp_type && cpp_ptr_type->constant != "naked");
CodeWriter cw(" ");
cw.SetValue("FIELD", Name(field));
cw.SetValue("TYPE", type_name);
if (is_ptr) {
// Use emplace_back to construct the potentially-smart pointer element
// from a raw pointer to a new-allocated copy.
cw.IncrementIdentLevel();
cw += "{{FIELD}}.reserve(o.{{FIELD}}.size());";
cw +=
"for (const auto &v : o.{{FIELD}}) { "
"{{FIELD}}.emplace_back((v) ? new {{TYPE}}(*v) : nullptr); }";
vector_copies += cw.ToString();
} else {
// For non-pointer elements, use std::vector's copy constructor in the
// initializer list. This will yield better performance than an insert
// range loop for trivially-copyable element types.
if (!initializer_list.empty()) { initializer_list += ",\n "; }
cw += "{{FIELD}}(o.{{FIELD}})\\";
initializer_list += cw.ToString();
}
} else {
if (!initializer_list.empty()) { initializer_list += ",\n "; }
CodeWriter cw;
cw.SetValue("FIELD", Name(field));
cw += "{{FIELD}}(o.{{FIELD}})\\";
initializer_list += cw.ToString();
}
{
if (!swaps.empty()) { swaps += "\n "; }
CodeWriter cw;
cw.SetValue("FIELD", Name(field));
cw += "std::swap({{FIELD}}, o.{{FIELD}});\\";
swaps += cw.ToString();
}
}
if (!initializer_list.empty()) {
initializer_list = "\n : " + initializer_list;
}
if (!swaps.empty()) { swaps = " " + swaps; }
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
code_.SetValue("INIT_LIST", initializer_list);
code_.SetValue("VEC_COPY", vector_copies);
code_.SetValue("SWAPS", swaps);
code_ +=
"inline {{NATIVE_NAME}}::{{NATIVE_NAME}}(const {{NATIVE_NAME}} &o)"
"{{INIT_LIST}} {";
code_ += "{{VEC_COPY}}}\n";
code_ +=
"inline {{NATIVE_NAME}} &{{NATIVE_NAME}}::operator="
"({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT {";
code_ += "{{SWAPS}}";
code_ += " return *this;\n}\n";
}
void GenCompareOperator(const StructDef &struct_def,
std::string accessSuffix = "") {
std::string compare_op;
@ -1855,7 +2025,7 @@ class CppGenerator : public BaseGenerator {
field.value.type.element != BASE_TYPE_UTYPE)) {
if (!compare_op.empty()) { compare_op += " &&\n "; }
auto accessor = Name(field) + accessSuffix;
if (struct_def.fixed ||
if (struct_def.fixed || field.native_inline ||
field.value.type.base_type != BASE_TYPE_STRUCT) {
compare_op += "(lhs." + accessor + " == rhs." + accessor + ")";
} else {
@ -1931,6 +2101,7 @@ class CppGenerator : public BaseGenerator {
}
GenOperatorNewDelete(struct_def);
GenDefaultConstructor(struct_def);
GenCopyMoveCtorAndAssigOpDecls(struct_def);
code_ += "};";
code_ += "";
}
@ -1954,8 +2125,9 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("OFFSET", GenFieldOffsetName(field));
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
code_ += "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
"{{OFFSET}}, {{ALIGN}})\\";
code_ +=
"{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
"{{OFFSET}}, {{ALIGN}})\\";
} else {
code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
}
@ -2007,11 +2179,13 @@ class CppGenerator : public BaseGenerator {
if (!nfn.empty()) {
code_.SetValue("CPP_NAME", nfn);
// FIXME: file_identifier.
code_ += "{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>"
"({{NAME}}(), nullptr)\\";
code_ +=
"{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>"
"({{NAME}}(), nullptr)\\";
} else if (field.flexbuffer) {
code_ += "{{PRE}}flexbuffers::VerifyNestedFlexBuffer"
"({{NAME}}(), verifier)\\";
code_ +=
"{{PRE}}flexbuffers::VerifyNestedFlexBuffer"
"({{NAME}}(), verifier)\\";
}
break;
}
@ -2048,7 +2222,8 @@ class CppGenerator : public BaseGenerator {
}
// Returns {field<val: -1, field==val: 0, field>val: +1}.
code_.SetValue("KEY_TYPE", type);
code_ += " int KeyCompareWithValue({{KEY_TYPE}} _{{FIELD_NAME}}) const {";
code_ +=
" int KeyCompareWithValue({{KEY_TYPE}} _{{FIELD_NAME}}) const {";
code_ +=
" return static_cast<int>({{FIELD_NAME}}() > _{{FIELD_NAME}}) - "
"static_cast<int>({{FIELD_NAME}}() < _{{FIELD_NAME}});";
@ -3109,6 +3284,9 @@ class CppGenerator : public BaseGenerator {
NativeName(Name(struct_def), &struct_def, opts_));
if (opts_.generate_object_based_api) {
// Generate the >= C++11 copy ctor and assignment operator definitions.
GenCopyCtorAssignOpDefs(struct_def);
// Generate the X::UnPack() method.
code_ +=
"inline " + TableUnPackSignature(struct_def, false, opts_) + " {";

View File

@ -738,11 +738,8 @@ class PythonGenerator : public BaseGenerator {
}
break;
}
case BASE_TYPE_UNION:
GetUnionField(struct_def, field, code_ptr);
break;
default:
FLATBUFFERS_ASSERT(0);
case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
default: FLATBUFFERS_ASSERT(0);
}
}
if (IsVector(field.value.type) || IsArray(field.value.type)) {
@ -913,14 +910,9 @@ class PythonGenerator : public BaseGenerator {
import_list->insert("import " + package_reference);
}
break;
case BASE_TYPE_STRING:
field_type += "str";
break;
case BASE_TYPE_NONE:
field_type += "None";
break;
default:
break;
case BASE_TYPE_STRING: field_type += "str"; break;
case BASE_TYPE_NONE: field_type += "None"; break;
default: break;
}
field_types += field_type + separator_string;
}
@ -1253,8 +1245,7 @@ class PythonGenerator : public BaseGenerator {
GenUnPackForScalarVector(struct_def, field, &code);
break;
}
default:
GenUnPackForScalar(struct_def, field, &code);
default: GenUnPackForScalar(struct_def, field, &code);
}
}

View File

@ -194,6 +194,11 @@ bool IsOptionalToBuilder(const FieldDef &field) {
bool GenerateRustModuleRootFile(const Parser &parser,
const std::string &output_dir) {
if (parser.opts.one_file) {
// Don't generate a root file when generating one file. This isn't an error
// so return true.
return true;
}
// We gather the symbols into a tree of namespaces (which are rust mods) and
// generate a file that gathers them all.
struct Module {
@ -384,6 +389,11 @@ class RustGenerator : public BaseGenerator {
code_ += "extern crate flatbuffers;";
code_ += "use std::mem;";
code_ += "use std::cmp::Ordering;";
if (parser_.opts.rust_serialize) {
code_ += "extern crate serde;";
code_ +=
"use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
}
code_ += "use self::flatbuffers::{EndianScalar, Follow};";
code_ += "use super::*;";
cur_name_space_ = symbol.defined_namespace;
@ -842,6 +852,27 @@ class RustGenerator : public BaseGenerator {
code_.SetValue("INTO_BASE", "self.0");
}
// Implement serde::Serialize
if (parser_.opts.rust_serialize) {
code_ += "impl Serialize for {{ENUM_NAME}} {";
code_ +=
" fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
code_ += " where";
code_ += " S: Serializer,";
code_ += " {";
if (IsBitFlagsEnum(enum_def)) {
code_ += " serializer.serialize_u32(self.bits() as u32)";
} else {
code_ +=
" serializer.serialize_unit_variant(\"{{ENUM_NAME}}\", self.0 "
"as "
"u32, self.variant_name().unwrap())";
}
code_ += " }";
code_ += "}";
code_ += "";
}
// Generate Follow and Push so we can serialize and stuff.
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_NAME}} {";
code_ += " type Inner = Self;";
@ -2005,6 +2036,74 @@ class RustGenerator : public BaseGenerator {
code_ += " }";
code_ += " }";
code_ += "}";
code_ += "";
// Implement serde::Serialize
if (parser_.opts.rust_serialize) {
const auto numFields = struct_def.fields.vec.size();
code_.SetValue("NUM_FIELDS", NumToString(numFields));
code_ += "impl Serialize for {{STRUCT_NAME}}<'_> {";
code_ +=
" fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
code_ += " where";
code_ += " S: Serializer,";
code_ += " {";
if (numFields == 0) {
code_ +=
" let s = serializer.serialize_struct(\"{{STRUCT_NAME}}\", 0)?;";
} else {
code_ +=
" let mut s = serializer.serialize_struct(\"{{STRUCT_NAME}}\", "
"{{NUM_FIELDS}})?;";
}
ForAllTableFields(struct_def, [&](const FieldDef &field) {
const Type &type = field.value.type;
if (IsUnion(type)) {
if (type.base_type == BASE_TYPE_UNION) {
const auto &enum_def = *type.enum_def;
code_.SetValue("ENUM_NAME", WrapInNameSpace(enum_def));
code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
code_ += " match self.{{FIELD_TYPE_FIELD_NAME}}_type() {";
code_ += " {{ENUM_NAME}}::NONE => (),";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
code_ += " {{ENUM_NAME}}::{{VARIANT_NAME}} => {";
code_ +=
" let f = "
"self.{{FIELD_TYPE_FIELD_NAME}}_as_{{U_ELEMENT_NAME}}()";
code_ +=
" .expect(\"Invalid union table, expected "
"`{{ENUM_NAME}}::{{VARIANT_NAME}}`.\");";
code_ += " s.serialize_field(\"{{FIELD_NAME}}\", &f)?;";
code_ += " }";
});
code_ += " _ => unimplemented!(),";
code_ += " }";
} else {
code_ +=
" s.serialize_field(\"{{FIELD_NAME}}\", "
"&self.{{FIELD_NAME}}())?;";
}
} else {
if (field.IsOptional()) {
code_ += " if let Some(f) = self.{{FIELD_NAME}}() {";
code_ += " s.serialize_field(\"{{FIELD_NAME}}\", &f)?;";
code_ += " } else {";
code_ += " s.skip_field(\"{{FIELD_NAME}}\")?;";
code_ += " }";
} else {
code_ +=
" s.serialize_field(\"{{FIELD_NAME}}\", "
"&self.{{FIELD_NAME}}())?;";
}
}
});
code_ += " s.end()";
code_ += " }";
code_ += "}";
code_ += "";
}
// Generate a builder struct:
code_ += "pub struct {{STRUCT_NAME}}Builder<'a: 'b, 'b> {";
@ -2636,6 +2735,37 @@ class RustGenerator : public BaseGenerator {
code_ += " v.in_buffer::<Self>(pos)";
code_ += " }";
code_ += "}";
code_ += "";
// Implement serde::Serialize
if (parser_.opts.rust_serialize) {
const auto numFields = struct_def.fields.vec.size();
code_.SetValue("NUM_FIELDS", NumToString(numFields));
code_ += "impl Serialize for {{STRUCT_NAME}} {";
code_ +=
" fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
code_ += " where";
code_ += " S: Serializer,";
code_ += " {";
if (numFields == 0) {
code_ +=
" let s = serializer.serialize_struct(\"{{STRUCT_NAME}}\", 0)?;";
} else {
code_ +=
" let mut s = serializer.serialize_struct(\"{{STRUCT_NAME}}\", "
"{{NUM_FIELDS}})?;";
}
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
code_ +=
" s.serialize_field(\"{{FIELD_NAME}}\", "
"&self.{{FIELD_NAME}}())?;";
});
code_ += " s.end()";
code_ += " }";
code_ += "}";
code_ += "";
}
// Generate a constructor that takes all fields as arguments.
code_ += "impl<'a> {{STRUCT_NAME}} {";
@ -2834,6 +2964,13 @@ class RustGenerator : public BaseGenerator {
code_ += indent + "use std::mem;";
code_ += indent + "use std::cmp::Ordering;";
code_ += "";
if (parser_.opts.rust_serialize) {
code_ += indent + "extern crate serde;";
code_ +=
indent +
"use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
code_ += "";
}
code_ += indent + "extern crate flatbuffers;";
code_ += indent + "use self::flatbuffers::{EndianScalar, Follow};";
}

View File

@ -220,8 +220,10 @@ class SwiftGenerator : public BaseGenerator {
IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}";
code_ += "private var _{{VALUENAME}}: " + valueType;
auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
auto base_value =
IsStruct(field.value.type) ? (type + "()") : field.value.constant;
auto is_bool = IsBool(field.value.type.base_type);
auto base_value = IsStruct(field.value.type) ? (type + "()")
: is_bool ? ("0" == field.value.constant ? "false" : "true")
: field.value.constant;
main_constructor.push_back("_" + name + " = " + name + accessing_value);
base_constructor.push_back("_" + name + " = " + base_value);
@ -712,7 +714,8 @@ class SwiftGenerator : public BaseGenerator {
if (IsBool(field.value.type.base_type)) {
std::string default_value =
"0" == field.value.constant ? "false" : "true";
field.IsOptional() ? "nil"
: ("0" == field.value.constant ? "false" : "true");
code_.SetValue("CONSTANT", default_value);
code_.SetValue("VALUETYPE", "Bool");
code_ += GenReaderMainBody(optional) + "\\";

View File

@ -343,8 +343,7 @@ class TsGenerator : public BaseGenerator {
switch (type.base_type) {
case BASE_TYPE_BOOL: return allowNull ? "boolean|null" : "boolean";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG:
return allowNull ? "bigint|null" : "bigint";
case BASE_TYPE_ULONG: return allowNull ? "bigint|null" : "bigint";
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
@ -907,8 +906,7 @@ class TsGenerator : public BaseGenerator {
// a string that contains values for things that can be created inline or
// the variable name from field_offset_decl
std::string field_offset_val;
const auto field_default_val =
GenDefaultValue(field, imports);
const auto field_default_val = GenDefaultValue(field, imports);
// Emit a scalar field
const auto is_string = IsString(field.value.type);
@ -1643,7 +1641,7 @@ class TsGenerator : public BaseGenerator {
std::string GetArgName(const FieldDef &field) {
auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) {
if (!IsScalar(field.value.type.base_type)) {
argname += "Offset";
} else {
argname = EscapeKeyword(argname);

View File

@ -144,7 +144,10 @@ void Parser::Message(const std::string &msg) {
}
void Parser::Warning(const std::string &msg) {
if (!opts.no_warnings) Message("warning: " + msg);
if (!opts.no_warnings) {
Message("warning: " + msg);
has_warning_ = true; // for opts.warnings_as_errors
}
}
CheckedError Parser::Error(const std::string &msg) {
@ -1674,8 +1677,9 @@ CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field,
if (opts.json_nested_legacy_flatbuffers) {
ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def, 0));
} else {
return Error("cannot parse nested_flatbuffer as bytes unless"
" --json-nested-bytes is set");
return Error(
"cannot parse nested_flatbuffer as bytes unless"
" --json-nested-bytes is set");
}
} else {
auto cursor_at_value_begin = cursor_;
@ -2164,9 +2168,7 @@ void EnumDef::SortByValue() {
});
else
std::sort(v.begin(), v.end(), [](const EnumVal *e1, const EnumVal *e2) {
if (e1->GetAsInt64() == e2->GetAsInt64()) {
return e1->name < e2->name;
}
if (e1->GetAsInt64() == e2->GetAsInt64()) { return e1->name < e2->name; }
return e1->GetAsInt64() < e2->GetAsInt64();
});
}
@ -3444,6 +3446,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
ECHECK(ParseDecl(source_filename));
}
}
if (opts.warnings_as_errors && has_warning_) {
return Error("treating warnings as errors, failed due to above warnings");
}
return NoError();
}

View File

@ -645,8 +645,7 @@ bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
case reflection::Bool:
case reflection::Byte:
case reflection::UByte:
if (!table->VerifyField<int8_t>(v, field_def->offset(),
sizeof(int8_t)))
if (!table->VerifyField<int8_t>(v, field_def->offset(), sizeof(int8_t)))
return false;
break;
case reflection::Short:
@ -668,13 +667,11 @@ bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
return false;
break;
case reflection::Float:
if (!table->VerifyField<float>(v, field_def->offset(),
sizeof(float)))
if (!table->VerifyField<float>(v, field_def->offset(), sizeof(float)))
return false;
break;
case reflection::Double:
if (!table->VerifyField<double>(v, field_def->offset(),
sizeof(double)))
if (!table->VerifyField<double>(v, field_def->offset(), sizeof(double)))
return false;
break;
case reflection::String:

View File

@ -1,40 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRC_COMPILER_CONFIG_H
#define SRC_COMPILER_CONFIG_H
// This file is here only because schema_interface.h, which is copied from gRPC,
// includes it. There is nothing for Flatbuffers to configure.
#endif // SRC_COMPILER_CONFIG_H

View File

@ -1,51 +1,17 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/compiler/cpp_generator.h"
#include <map>
#include "src/compiler/cpp_generator.h"
#include "flatbuffers/util.h"
#include <sstream>
#include "flatbuffers/util.h"
namespace grpc_cpp_generator {
namespace {
grpc::string message_header_ext() { return "_generated.h"; }
grpc::string service_header_ext() { return ".grpc.fb.h"; }
template <class T>
grpc::string as_string(T x) {
template<class T> grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
@ -76,10 +42,7 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
}
} // namespace
template <class T, size_t N>
T *array_end(T (&array)[N]) {
return array + N;
}
template<class T, size_t N> T *array_end(T (&array)[N]) { return array + N; }
void PrintIncludes(grpc_generator::Printer *printer,
const std::vector<grpc::string> &headers,
@ -92,9 +55,7 @@ void PrintIncludes(grpc_generator::Printer *printer,
auto &s = params.grpc_search_path;
if (!s.empty()) {
vars["l"] += s;
if (s[s.size() - 1] != '/') {
vars["l"] += '/';
}
if (s[s.size() - 1] != '/') { vars["l"] += '/'; }
}
for (auto i = headers.begin(); i != headers.end(); i++) {
@ -144,15 +105,16 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
std::map<grpc::string, grpc::string> vars;
static const char *headers_strs[] = {
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/method_handler.h",
"grpcpp/impl/codegen/proto_utils.h",
"grpcpp/impl/codegen/rpc_method.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/status.h",
"grpcpp/impl/codegen/stub_options.h",
"grpcpp/impl/codegen/sync_stream.h"};
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/method_handler.h",
"grpcpp/impl/codegen/proto_utils.h",
"grpcpp/impl/codegen/rpc_method.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/status.h",
"grpcpp/impl/codegen/stub_options.h",
"grpcpp/impl/codegen/sync_stream.h"
};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
printer->Print(vars, "\n");
@ -187,8 +149,8 @@ void PrintHeaderClientMethodInterfaces(
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
} async_prefixes[] = { { "Async", ", void* tag", ", tag" },
{ "PrepareAsync", "", "" } };
if (is_public) {
if (method->NoStreaming()) {
@ -196,8 +158,9 @@ void PrintHeaderClientMethodInterfaces(
*vars,
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
@ -228,8 +191,9 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, response));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -262,8 +226,9 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, request));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -295,8 +260,9 @@ void PrintHeaderClientMethodInterfaces(
"$Method$Raw(context));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -318,8 +284,9 @@ void PrintHeaderClientMethodInterfaces(
}
} else {
if (method->NoStreaming()) {
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
@ -334,8 +301,9 @@ void PrintHeaderClientMethodInterfaces(
"virtual ::grpc::ClientWriterInterface< $Request$>*"
" $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
@ -351,8 +319,9 @@ void PrintHeaderClientMethodInterfaces(
"virtual ::grpc::ClientReaderInterface< $Response$>* "
"$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
@ -367,8 +336,9 @@ void PrintHeaderClientMethodInterfaces(
"virtual ::grpc::ClientReaderWriterInterface< $Request$, "
"$Response$>* "
"$Method$Raw(::grpc::ClientContext* context) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
@ -393,8 +363,8 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
} async_prefixes[] = { { "Async", ", void* tag", ", tag" },
{ "PrepareAsync", "", "" } };
if (is_public) {
if (method->NoStreaming()) {
@ -402,8 +372,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
*vars,
"::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
@ -431,8 +402,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, response));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -463,8 +435,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, request));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -494,8 +467,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"$Method$Raw(context));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -516,8 +490,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
}
} else {
if (method->NoStreaming()) {
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
@ -531,8 +506,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"::grpc::ClientWriter< $Request$>* $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) "
"override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -547,8 +523,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"::grpc::ClientReader< $Response$>* $Method$Raw("
"::grpc::ClientContext* context, const $Request$& request)"
" override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -562,8 +539,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
printer->Print(*vars,
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$Method$Raw(::grpc::ClientContext* context) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
@ -630,7 +608,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
"class WithAsyncMethod_$Method$ : public BaseClass {\n");
printer->Print(
" private:\n"
" void BaseClassMustBeDerivedFromService(const Service */*service*/) {}\n");
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
"{}\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(*vars,
@ -849,7 +828,8 @@ void PrintHeaderServerMethodGeneric(
"class WithGenericMethod_$Method$ : public BaseClass {\n");
printer->Print(
" private:\n"
" void BaseClassMustBeDerivedFromService(const Service */*service*/) {}\n");
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
"{}\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(*vars,
@ -1001,9 +981,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print(*vars, "WithAsyncMethod_$method_name$<");
}
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
printer->Print(" >");
}
for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
printer->Print(" AsyncService;\n");
// Server side - Generic
@ -1028,9 +1006,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
}
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
if (service->method(i)->NoStreaming()) {
printer->Print(" >");
}
if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
}
printer->Print(" StreamedUnaryService;\n");
@ -1052,9 +1028,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (ServerOnlyStreaming(method.get())) {
printer->Print(" >");
}
if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
}
printer->Print(" SplitStreamedService;\n");
@ -1095,9 +1069,7 @@ grpc::string GetHeaderServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;
@ -1179,14 +1151,15 @@ grpc::string GetSourceIncludes(grpc_generator::File *file,
std::map<grpc::string, grpc::string> vars;
static const char *headers_strs[] = {
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/channel_interface.h",
"grpcpp/impl/codegen/client_unary_call.h",
"grpcpp/impl/codegen/method_handler.h",
"grpcpp/impl/codegen/rpc_service_method.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/sync_stream.h"};
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/channel_interface.h",
"grpcpp/impl/codegen/client_unary_call.h",
"grpcpp/impl/codegen/method_handler.h",
"grpcpp/impl/codegen/rpc_service_method.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/sync_stream.h"
};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
@ -1215,8 +1188,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
grpc::string start; // bool literal expressed as string
grpc::string method_params; // extra arguments to method
grpc::string create_args; // extra arguments to creator
} async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
{"PrepareAsync", "false", "", ", nullptr"}};
} async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" },
{ "PrepareAsync", "false", "", ", nullptr" } };
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::Status $ns$$Service$::Stub::$Method$("
@ -1226,8 +1199,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
" return ::grpc::internal::BlockingUnaryCall"
"(channel_.get(), rpcmethod_$Method$_, "
"context, request, response);\n}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
printer->Print(*vars,
@ -1257,8 +1231,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
@ -1289,8 +1264,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
@ -1321,8 +1297,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, "
"context);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
@ -1351,10 +1328,11 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::Status $ns$$Service$::Service::$Method$("
"::grpc::ServerContext* /*context*/, "
"const $Request$* /*request*/, $Response$* /*response*/) {\n");
printer->Print(
*vars,
"::grpc::Status $ns$$Service$::Service::$Method$("
"::grpc::ServerContext* /*context*/, "
"const $Request$* /*request*/, $Response$* /*response*/) {\n");
printer->Print(
" return ::grpc::Status("
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
@ -1519,9 +1497,7 @@ grpc::string GetSourceServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["ns"] = params.services_namespace + "::";
vars["prefix"] = params.services_namespace;
@ -1593,9 +1569,9 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
std::map<grpc::string, grpc::string> vars;
static const char *headers_strs[] = {
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/sync_stream.h",
"gmock/gmock.h",
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/sync_stream.h",
"gmock/gmock.h",
};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
@ -1625,15 +1601,17 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
grpc::string prefix;
grpc::string method_params; // extra arguments to method
int extra_method_param_count;
} async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
} async_prefixes[] = { { "Async", ", void* tag", 1 },
{ "PrepareAsync", "", 0 } };
if (method->NoStreaming()) {
printer->Print(
*vars,
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
@ -1648,12 +1626,13 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"MOCK_METHOD2($Method$Raw, "
"::grpc::ClientWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
printer->Print(*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncWriterInterface< $Request$>*"
@ -1666,8 +1645,9 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"MOCK_METHOD2($Method$Raw, "
"::grpc::ClientReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
@ -1685,8 +1665,9 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"MOCK_METHOD1($Method$Raw, "
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
"(::grpc::ClientContext* context));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
i++) {
auto &async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
@ -1727,9 +1708,7 @@ grpc::string GetMockServices(grpc_generator::File *file,
// Package string is empty or ends with a dot. It is used to fully qualify
// method names.
vars["Package"] = file->package();
if (!file->package().empty()) {
vars["Package"].append(".");
}
if (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;

View File

@ -1,36 +1,3 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
@ -41,12 +8,11 @@
#include <memory>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
# include <string>
# define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {

View File

@ -1,47 +1,13 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation AN/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <map>
#include <cctype>
#include <sstream>
#include "src/compiler/go_generator.h"
template <class T>
grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
#include <cctype>
#include <map>
#include <sstream>
template<class T> grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
}
inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
@ -56,18 +22,16 @@ namespace grpc_go_generator {
// Returns string with first letter to lowerCase
grpc::string unexportName(grpc::string s) {
if (s.empty())
return s;
s[0] = static_cast<char>(std::tolower(s[0]));
return s;
if (s.empty()) return s;
s[0] = static_cast<char>(std::tolower(s[0]));
return s;
}
// Returns string with first letter to uppercase
grpc::string exportName(grpc::string s) {
if (s.empty())
return s;
s[0] = static_cast<char>(std::toupper(s[0]));
return s;
if (s.empty()) return s;
s[0] = static_cast<char>(std::toupper(s[0]));
return s;
}
void GenerateError(grpc_generator::Printer *printer,
@ -82,50 +46,65 @@ void GenerateError(grpc_generator::Printer *printer,
}
// Generates imports for the service
void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
void GenerateImports(grpc_generator::File *file,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["filename"] = file->filename();
printer->Print("//Generated by gRPC Go plugin\n");
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$\n\n");
printer->Print(vars, "package $Package$\n\n");
printer->Print("import (\n");
printer->Indent();
printer->Print(vars, "$context$ \"context\"\n");
vars["filename"] = file->filename();
printer->Print("//Generated by gRPC Go plugin\n");
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$\n\n");
printer->Print(vars, "package $Package$\n\n");
printer->Print("import (\n");
printer->Indent();
printer->Print(vars, "$context$ \"context\"\n");
printer->Print("flatbuffers \"github.com/google/flatbuffers/go\"\n");
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
printer->Print("\"google.golang.org/grpc/codes\"\n");
printer->Print("\"google.golang.org/grpc/status\"\n");
printer->Outdent();
printer->Print(")\n\n");
printer->Outdent();
printer->Print(")\n\n");
}
// Generates Server method signature source
void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
void GenerateServerMethodSignature(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
if (method->NoStreaming()) {
printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$");
} else if (ServerOnlyStreaming(method)) {
printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$");
} else {
printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$");
}
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "")
? method->get_output_type_name()
: vars["CustomMethodIO"];
if (method->NoStreaming()) {
printer->Print(
vars,
"$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$");
} else if (ServerOnlyStreaming(method)) {
printer->Print(
vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$");
} else {
printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$");
}
}
void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
void GenerateServerMethod(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "in := new($Request$)\n");
vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "")
? method->get_output_type_name()
: vars["CustomMethodIO"];
vars["FullMethodName"] =
"/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print(
vars,
"func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec "
"func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) "
"(interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "in := new($Request$)\n");
vars["Error_Check"] = "err := dec(in); err != nil";
GenerateError(printer, vars);
printer->Print("if interceptor == nil {\n");
@ -133,258 +112,281 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, in)\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
printer->Indent();
printer->Print("Server: srv,\n");
printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
printer->Indent();
printer->Print("Server: srv,\n");
printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
printer->Outdent();
printer->Print("}\n");
printer->Outdent();
printer->Print("\n");
printer->Indent();
printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("return interceptor(ctx, in, info, handler)\n");
printer->Outdent();
printer->Print("}\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
printer->Indent();
if (ServerOnlyStreaming(method)) {
printer->Print(vars, "m := new($Request$)\n");
printer->Print(vars,
"handler := func(ctx $context$.Context, req interface{}) "
"(interface{}, error) {\n");
printer->Indent();
printer->Print(
vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("return interceptor(ctx, in, info, handler)\n");
printer->Outdent();
printer->Print("}\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
printer->Print(
vars,
"func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
printer->Indent();
if (ServerOnlyStreaming(method)) {
printer->Print(vars, "m := new($Request$)\n");
vars["Error_Check"] = "err := stream.RecvMsg(m); err != nil";
GenerateError(printer, vars, false);
printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
} else {
printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
}
printer->Outdent();
printer->Print("}\n\n");
printer->Print(
vars,
"return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
} else {
printer->Print(
vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
}
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genSendAndClose = ClientOnlyStreaming(method);
bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genSendAndClose = ClientOnlyStreaming(method);
printer->Print(vars, "type $Service$_$Method$Server interface {\n");
printer->Indent();
if (genSend) {
printer->Print(vars, "Send(*$Response$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Request$, error)\n");
}
if (genSendAndClose) {
printer->Print(vars, "SendAndClose(*$Response$) error\n");
}
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "type $Service$_$Method$Server interface {\n");
printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Response$) error\n"); }
if (genRecv) { printer->Print(vars, "Recv() (*$Request$, error)\n"); }
if (genSendAndClose) {
printer->Print(vars, "SendAndClose(*$Response$) error\n");
}
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
if (genSend) {
printer->Print(vars, "func (x *$StreamType$) Send(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genRecv) {
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Request$)\n");
if (genSend) {
printer->Print(vars,
"func (x *$StreamType$) Send(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genRecv) {
printer->Print(vars,
"func (x *$StreamType$) Recv() (*$Request$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Request$)\n");
vars["Error_Check"] = "err := x.ServerStream.RecvMsg(m); err != nil";
GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genSendAndClose) {
printer->Print(vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genSendAndClose) {
printer->Print(
vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
}
// Generates Client method signature source
void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
void GenerateClientMethodSignature(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]);
if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
vars["Request"] = "";
}
vars["Response"] = "*" + method->get_output_type_name();
if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
}
printer->Print(vars, "$Method$(ctx $context$.Context$Request$,\n\topts ...$grpc$.CallOption) ($Response$, error)$Ending$");
vars["Method"] = exportName(method->name());
vars["Request"] =
", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name()
: vars["CustomMethodIO"]);
if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
vars["Request"] = "";
}
vars["Response"] = "*" + method->get_output_type_name();
if (ClientOnlyStreaming(method) || method->BidiStreaming() ||
ServerOnlyStreaming(method)) {
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client";
}
printer->Print(vars,
"$Method$(ctx $context$.Context$Request$,\n\topts "
"...$grpc$.CallOption) ($Response$, error)$Ending$");
}
// Generates Client method source
void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
void GenerateClientMethod(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
vars["Ending"] = " {\n";
GenerateClientMethodSignature(method, printer, vars);
printer->Indent();
vars["Method"] = exportName(method->name());
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
vars["Response"] = method->get_output_type_name();
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
if (method->NoStreaming()) {
printer->Print(vars, "out := new($Response$)\n");
printer->Print(vars, "err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n");
GenerateClientMethodSignature(method, printer, vars);
printer->Indent();
vars["Method"] = exportName(method->name());
vars["Request"] = (vars["CustomMethodIO"] == "")
? method->get_input_type_name()
: vars["CustomMethodIO"];
vars["Response"] = method->get_output_type_name();
vars["FullMethodName"] =
"/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
if (method->NoStreaming()) {
printer->Print(vars, "out := new($Response$)\n");
printer->Print(
vars,
"err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n");
vars["Error_Check"] = "err != nil";
GenerateError(printer, vars);
printer->Print("return out, nil\n");
printer->Outdent();
printer->Print("}\n\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
printer->Print(vars, "stream, err := c.cc.NewStream(ctx, &$MethodDesc$, \"$FullMethodName$\", opts...)\n");
printer->Print("return out, nil\n");
printer->Outdent();
printer->Print("}\n\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
printer->Print(vars,
"stream, err := c.cc.NewStream(ctx, &$MethodDesc$, "
"\"$FullMethodName$\", opts...)\n");
vars["Error_Check"] = "err != nil";
GenerateError(printer, vars);
printer->Print(vars, "x := &$StreamType${stream}\n");
if (ServerOnlyStreaming(method)) {
printer->Print(vars, "x := &$StreamType${stream}\n");
if (ServerOnlyStreaming(method)) {
vars["Error_Check"] = "err := x.ClientStream.SendMsg(in); err != nil";
GenerateError(printer, vars);
vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
GenerateError(printer, vars);
}
printer->Print("return x, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
printer->Print("return x, nil\n");
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genCloseAndRecv = ClientOnlyStreaming(method);
bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genCloseAndRecv = ClientOnlyStreaming(method);
//Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
printer->Indent();
if (genSend) {
printer->Print(vars, "Send(*$Request$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Response$, error)\n");
}
if (genCloseAndRecv) {
printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
}
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
// Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
printer->Indent();
if (genSend) { printer->Print(vars, "Send(*$Request$) error\n"); }
if (genRecv) { printer->Print(vars, "Recv() (*$Response$, error)\n"); }
if (genCloseAndRecv) {
printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
}
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
//Stream Client
printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
// Stream Client
printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
if (genSend) {
printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n");
printer->Indent();
printer->Print("return x.ClientStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genSend) {
printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n");
printer->Indent();
printer->Print("return x.ClientStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genRecv) {
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Response$)\n");
if (genRecv) {
printer->Print(vars,
"func (x *$StreamType$) Recv() (*$Response$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Response$)\n");
vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genCloseAndRecv) {
printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
printer->Indent();
if (genCloseAndRecv) {
printer->Print(
vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
printer->Indent();
vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
GenerateError(printer, vars);
printer->Print(vars, "m := new($Response$)\n");
printer->Print(vars, "m := new($Response$)\n");
vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
}
// Generates client API for the service
void GenerateService(const grpc_generator::Service *service, grpc_generator::Printer* printer,
void GenerateService(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Service"] = exportName(service->name());
// Client Interface
printer->Print(vars, "// Client API for $Service$ service\n");
printer->Print(vars, "type $Service$Client interface {\n");
printer->Indent();
vars["Service"] = exportName(service->name());
// Client Interface
printer->Print(vars, "// Client API for $Service$ service\n");
printer->Print(vars, "type $Service$Client interface {\n");
printer->Indent();
vars["Ending"] = "\n";
for (int i = 0; i < service->method_count(); i++) {
GenerateClientMethodSignature(service->method(i).get(), printer, vars);
}
printer->Outdent();
printer->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
GenerateClientMethodSignature(service->method(i).get(), printer, vars);
}
printer->Outdent();
printer->Print("}\n\n");
// Client structure
vars["ServiceUnexported"] = unexportName(vars["Service"]);
printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
printer->Indent();
printer->Print(vars, "cc $grpc$.ClientConnInterface\n");
printer->Outdent();
printer->Print("}\n\n");
// Client structure
vars["ServiceUnexported"] = unexportName(vars["Service"]);
printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
printer->Indent();
printer->Print(vars, "cc $grpc$.ClientConnInterface\n");
printer->Outdent();
printer->Print("}\n\n");
// NewClient
printer->Print(vars, "func New$Service$Client(cc $grpc$.ClientConnInterface) $Service$Client {\n");
printer->Indent();
printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
printer->Outdent();
printer->Print("\n}\n\n");
// NewClient
printer->Print(vars,
"func New$Service$Client(cc $grpc$.ClientConnInterface) "
"$Service$Client {\n");
printer->Indent();
printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
printer->Outdent();
printer->Print("\n}\n\n");
int unary_methods = 0, streaming_methods = 0;
vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc";
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
if (method->NoStreaming()) {
vars["MethodDesc"] = vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]";
unary_methods++;
} else {
vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" + as_string(streaming_methods) + "]";
streaming_methods++;
}
GenerateClientMethod(method.get(), printer, vars);
}
int unary_methods = 0, streaming_methods = 0;
vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc";
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
if (method->NoStreaming()) {
vars["MethodDesc"] =
vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]";
unary_methods++;
} else {
vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" +
as_string(streaming_methods) + "]";
streaming_methods++;
}
GenerateClientMethod(method.get(), printer, vars);
}
//Server Interface
printer->Print(vars, "// Server API for $Service$ service\n");
printer->Print(vars, "type $Service$Server interface {\n");
printer->Indent();
// Server Interface
printer->Print(vars, "// Server API for $Service$ service\n");
printer->Print(vars, "type $Service$Server interface {\n");
printer->Indent();
vars["Ending"] = "\n";
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethodSignature(service->method(i).get(), printer, vars);
}
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethodSignature(service->method(i).get(), printer, vars);
}
printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "type Unimplemented$Service$Server struct {\n");
printer->Print("}\n\n");
@ -397,13 +399,17 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Print(vars, "func (Unimplemented$Service$Server) ");
GenerateServerMethodSignature(method.get(), printer, vars);
printer->Indent();
printer->Print(vars, "return $Nil$status.Errorf(codes.Unimplemented, \"method $Method$ not implemented\")\n");
printer->Print(vars,
"return $Nil$status.Errorf(codes.Unimplemented, \"method "
"$Method$ not implemented\")\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
}
printer->Print(vars, "func (Unimplemented$Service$Server) mustEmbedUnimplemented$Service$Server() {}");
printer->Print(vars,
"func (Unimplemented$Service$Server) "
"mustEmbedUnimplemented$Service$Server() {}");
printer->Print("\n\n");
printer->Print(vars, "type Unsafe$Service$Server interface {\n");
@ -411,91 +417,89 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
printer->Outdent();
printer->Print("}\n\n");
// Server registration.
printer->Print(vars, "func Register$Service$Server(s $grpc$.ServiceRegistrar, srv $Service$Server) {\n");
printer->Indent();
printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
printer->Outdent();
printer->Print("}\n\n");
// Server registration.
printer->Print(vars,
"func Register$Service$Server(s $grpc$.ServiceRegistrar, srv "
"$Service$Server) {\n");
printer->Indent();
printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
printer->Outdent();
printer->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethod(service->method(i).get(), printer, vars);
}
//Service Descriptor
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
printer->Indent();
printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n");
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "MethodName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$,\n");
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (!method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "StreamName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$,\n");
if (ClientOnlyStreaming(method.get())) {
printer->Print("ClientStreams: true,\n");
} else if (ServerOnlyStreaming(method.get())) {
printer->Print("ServerStreams: true,\n");
} else {
printer->Print("ServerStreams: true,\n");
printer->Print("ClientStreams: true,\n");
}
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Outdent();
printer->Print("}\n");
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethod(service->method(i).get(), printer, vars);
}
// Service Descriptor
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
printer->Indent();
printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n");
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "MethodName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$,\n");
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (!method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "StreamName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$,\n");
if (ClientOnlyStreaming(method.get())) {
printer->Print("ClientStreams: true,\n");
} else if (ServerOnlyStreaming(method.get())) {
printer->Print("ServerStreams: true,\n");
} else {
printer->Print("ServerStreams: true,\n");
printer->Print("ClientStreams: true,\n");
}
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Outdent();
printer->Print("}\n");
}
// Returns source for the service
grpc::string GenerateServiceSource(grpc_generator::File *file,
const grpc_generator::Service *service,
grpc_go_generator::Parameters *parameters) {
grpc::string out;
auto p = file->CreatePrinter(&out, '\t');
grpc::string out;
auto p = file->CreatePrinter(&out, '\t');
p->SetIndentationSize(1);
auto printer = p.get();
std::map<grpc::string, grpc::string> vars;
vars["Package"] = parameters->package_name;
vars["ServicePrefix"] = parameters->service_prefix;
if (!parameters->service_prefix.empty())
vars["ServicePrefix"].append(".");
vars["grpc"] = "grpc";
vars["context"] = "context";
GenerateImports(file, printer, vars);
if (parameters->custom_method_io_type != "") {
vars["CustomMethodIO"] = parameters->custom_method_io_type;
}
GenerateService(service, printer, vars);
return out;
auto printer = p.get();
std::map<grpc::string, grpc::string> vars;
vars["Package"] = parameters->package_name;
vars["ServicePrefix"] = parameters->service_prefix;
if (!parameters->service_prefix.empty()) vars["ServicePrefix"].append(".");
vars["grpc"] = "grpc";
vars["context"] = "context";
GenerateImports(file, printer, vars);
if (parameters->custom_method_io_type != "") {
vars["CustomMethodIO"] = parameters->custom_method_io_type;
}
GenerateService(service, printer, vars);
return out;
}
}// Namespace grpc_go_generator
} // Namespace grpc_go_generator

View File

@ -1,40 +1,8 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
//go generator is used to generate GRPC code for serialization system, such as flatbuffers
// go generator is used to generate GRPC code for serialization system, such as
// flatbuffers
#include <memory>
#include <vector>
@ -43,14 +11,15 @@
namespace grpc_go_generator {
struct Parameters {
//Defines the custom parameter types for methods
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
// Defines the custom parameter types for methods
// eg: flatbuffers uses flatbuffers.Builder as input for the client and output
// for the server
grpc::string custom_method_io_type;
//Package name for the service
// Package name for the service
grpc::string package_name;
//Prefix for RPC Calls
// Prefix for RPC Calls
grpc::string service_prefix;
};
@ -59,6 +28,6 @@ grpc::string GenerateServiceSource(grpc_generator::File *file,
const grpc_generator::Service *service,
grpc_go_generator::Parameters *parameters);
}
} // namespace grpc_go_generator
#endif // GRPC_INTERNAL_COMPILER_GO_GENERATOR_H

View File

@ -23,21 +23,18 @@
#include <utility>
#include <vector>
// just to get flatbuffer_version_string()
#include <flatbuffers/flatbuffers.h>
#include <flatbuffers/util.h>
#include "flatbuffers/util.h"
#define to_string flatbuffers::NumToString
// Stringify helpers used solely to cast GRPC_VERSION
#ifndef STR
#define STR(s) #s
# define STR(s) # s
#endif
#ifndef XSTR
#define XSTR(s) STR(s)
# define XSTR(s) STR(s)
#endif
typedef grpc_generator::Printer Printer;
typedef std::map<grpc::string, grpc::string> VARS;
typedef grpc_generator::Service ServiceDescriptor;
@ -48,12 +45,11 @@ typedef grpc_generator::Method MethodDescriptor;
namespace grpc_java_generator {
typedef std::string string;
// Generates imports for the service
void GenerateImports(grpc_generator::File* file,
grpc_generator::Printer* printer, VARS& vars) {
void GenerateImports(grpc_generator::File *file,
grpc_generator::Printer *printer, VARS &vars) {
vars["filename"] = file->filename();
printer->Print(
vars,
"//Generated by flatc compiler (version $flatc_version$)\n");
printer->Print(vars,
"//Generated by flatc compiler (version $flatc_version$)\n");
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$.fbs\n\n");
printer->Print(vars, "package $Package$;\n\n");
@ -67,7 +63,7 @@ void GenerateImports(grpc_generator::File* file,
// Adjust a method name prefix identifier to follow the JavaBean spec:
// - decapitalize the first letter
// - remove embedded underscores & capitalize the following letter
static string MixedLower(const string& word) {
static string MixedLower(const string &word) {
string w;
w += static_cast<string::value_type>(tolower(word[0]));
bool after_underscore = false;
@ -87,7 +83,7 @@ static string MixedLower(const string& word) {
// - An underscore is inserted where a lower case letter is followed by an
// upper case letter.
// - All letters are converted to upper case
static string ToAllUpperCase(const string& word) {
static string ToAllUpperCase(const string &word) {
string w;
for (size_t i = 0; i < word.length(); ++i) {
w += static_cast<string::value_type>(toupper(word[i]));
@ -98,47 +94,47 @@ static string ToAllUpperCase(const string& word) {
return w;
}
static inline string LowerMethodName(const MethodDescriptor* method) {
static inline string LowerMethodName(const MethodDescriptor *method) {
return MixedLower(method->name());
}
static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
static inline string MethodPropertiesFieldName(const MethodDescriptor *method) {
return "METHOD_" + ToAllUpperCase(method->name());
}
static inline string MethodPropertiesGetterName(
const MethodDescriptor* method) {
const MethodDescriptor *method) {
return MixedLower("get_" + method->name() + "_method");
}
static inline string MethodIdFieldName(const MethodDescriptor* method) {
static inline string MethodIdFieldName(const MethodDescriptor *method) {
return "METHODID_" + ToAllUpperCase(method->name());
}
static inline string JavaClassName(VARS& vars, const string& name) {
static inline string JavaClassName(VARS &vars, const string &name) {
// string name = google::protobuf::compiler::java::ClassName(desc);
return vars["Package"] + name;
}
static inline string ServiceClassName(const string& service_name) {
static inline string ServiceClassName(const string &service_name) {
return service_name + "Grpc";
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in
// distribution.
template <typename ITR>
static void GrpcSplitStringToIteratorUsing(const string& full,
const char* delim, ITR& result) {
template<typename ITR>
static void GrpcSplitStringToIteratorUsing(const string &full,
const char *delim, ITR &result) {
// Optimize the common case where delim is a single character.
if (delim[0] != '\0' && delim[1] == '\0') {
char c = delim[0];
const char* p = full.data();
const char* end = p + full.size();
const char *p = full.data();
const char *end = p + full.size();
while (p != end) {
if (*p == c) {
++p;
} else {
const char* start = p;
const char *start = p;
while (++p != end && *p != c)
;
*result++ = string(start, p - start);
@ -160,13 +156,13 @@ static void GrpcSplitStringToIteratorUsing(const string& full,
}
}
static void GrpcSplitStringUsing(const string& full, const char* delim,
std::vector<string>* result) {
static void GrpcSplitStringUsing(const string &full, const char *delim,
std::vector<string> *result) {
std::back_insert_iterator<std::vector<string>> it(*result);
GrpcSplitStringToIteratorUsing(full, delim, it);
}
static std::vector<string> GrpcSplit(const string& full, const char* delim) {
static std::vector<string> GrpcSplit(const string &full, const char *delim) {
std::vector<string> result;
GrpcSplitStringUsing(full, delim, &result);
return result;
@ -174,7 +170,7 @@ static std::vector<string> GrpcSplit(const string& full, const char* delim) {
// TODO(nmittler): Remove once protobuf includes javadoc methods in
// distribution.
static string GrpcEscapeJavadoc(const string& input) {
static string GrpcEscapeJavadoc(const string &input) {
string result;
result.reserve(input.size() * 2);
@ -221,9 +217,7 @@ static string GrpcEscapeJavadoc(const string& input) {
// Java interprets Unicode escape sequences anywhere!
result.append("&#92;");
break;
default:
result.push_back(c);
break;
default: result.push_back(c); break;
}
prev = c;
@ -232,7 +226,7 @@ static string GrpcEscapeJavadoc(const string& input) {
return result;
}
static std::vector<string> GrpcGetDocLines(const string& comments) {
static std::vector<string> GrpcGetDocLines(const string &comments) {
if (!comments.empty()) {
// TODO(kenton): Ideally we should parse the comment text as Markdown and
// write it back as HTML, but this requires a Markdown parser. For now
@ -243,27 +237,23 @@ static std::vector<string> GrpcGetDocLines(const string& comments) {
string escapedComments = GrpcEscapeJavadoc(comments);
std::vector<string> lines = GrpcSplit(escapedComments, "\n");
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
while (!lines.empty() && lines.back().empty()) { lines.pop_back(); }
return lines;
}
return std::vector<string>();
}
static std::vector<string> GrpcGetDocLinesForDescriptor(
const DescriptorType* descriptor) {
const DescriptorType *descriptor) {
return descriptor->GetAllComments();
// return GrpcGetDocLines(descriptor->GetLeadingComments("///"));
}
static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
const std::vector<string>& lines,
static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
const std::vector<string> &lines,
bool surroundWithPreTag) {
if (!lines.empty()) {
if (surroundWithPreTag) {
printer->Print(" * <pre>\n");
}
if (surroundWithPreTag) { printer->Print(" * <pre>\n"); }
for (size_t i = 0; i < lines.size(); i++) {
// Most lines should start with a space. Watch out for lines that start
@ -277,73 +267,72 @@ static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
}
}
if (surroundWithPreTag) {
printer->Print(" * </pre>\n");
}
if (surroundWithPreTag) { printer->Print(" * </pre>\n"); }
}
}
static void GrpcWriteDocComment(Printer* printer, VARS& vars,
const string& comments) {
static void GrpcWriteDocComment(Printer *printer, VARS &vars,
const string &comments) {
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLines(comments);
GrpcWriteDocCommentBody(printer, vars, lines, false);
printer->Print(" */\n");
}
static void GrpcWriteServiceDocComment(Printer* printer, VARS& vars,
const ServiceDescriptor* service) {
static void GrpcWriteServiceDocComment(Printer *printer, VARS &vars,
const ServiceDescriptor *service) {
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
GrpcWriteDocCommentBody(printer, vars, lines, true);
printer->Print(" */\n");
}
void GrpcWriteMethodDocComment(Printer* printer, VARS& vars,
const MethodDescriptor* method) {
void GrpcWriteMethodDocComment(Printer *printer, VARS &vars,
const MethodDescriptor *method) {
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
GrpcWriteDocCommentBody(printer, vars, lines, true);
printer->Print(" */\n");
}
//outputs static singleton extractor for type stored in "extr_type" and "extr_type_name" vars
static void PrintTypeExtractor(Printer* p, VARS& vars) {
p->Print(
vars,
"private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> "
"extractorOf$extr_type_name$;\n"
"private static FlatbuffersUtils.FBExtactor<$extr_type$> "
"getExtractorOf$extr_type_name$() {\n"
" if (extractorOf$extr_type_name$ != null) return "
"extractorOf$extr_type_name$;\n"
" synchronized ($service_class_name$.class) {\n"
" if (extractorOf$extr_type_name$ != null) return "
"extractorOf$extr_type_name$;\n"
" extractorOf$extr_type_name$ = new "
"FlatbuffersUtils.FBExtactor<$extr_type$>() {\n"
" public $extr_type$ extract (ByteBuffer buffer) {\n"
" return "
"$extr_type$.getRootAs$extr_type_name$(buffer);\n"
" }\n"
" };\n"
" return extractorOf$extr_type_name$;\n"
" }\n"
"}\n\n");
// outputs static singleton extractor for type stored in "extr_type" and
// "extr_type_name" vars
static void PrintTypeExtractor(Printer *p, VARS &vars) {
p->Print(vars,
"private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> "
"extractorOf$extr_type_name$;\n"
"private static FlatbuffersUtils.FBExtactor<$extr_type$> "
"getExtractorOf$extr_type_name$() {\n"
" if (extractorOf$extr_type_name$ != null) return "
"extractorOf$extr_type_name$;\n"
" synchronized ($service_class_name$.class) {\n"
" if (extractorOf$extr_type_name$ != null) return "
"extractorOf$extr_type_name$;\n"
" extractorOf$extr_type_name$ = new "
"FlatbuffersUtils.FBExtactor<$extr_type$>() {\n"
" public $extr_type$ extract (ByteBuffer buffer) {\n"
" return "
"$extr_type$.getRootAs$extr_type_name$(buffer);\n"
" }\n"
" };\n"
" return extractorOf$extr_type_name$;\n"
" }\n"
"}\n\n");
}
static void PrintMethodFields(Printer* p, VARS& vars,
const ServiceDescriptor* service) {
static void PrintMethodFields(Printer *p, VARS &vars,
const ServiceDescriptor *service) {
p->Print("// Static method descriptors that strictly reflect the proto.\n");
vars["service_name"] = service->name();
//set of names of rpc input- and output- types that were already encountered.
//this is needed to avoid duplicating type extractor since it's possible that
//the same type is used as an input or output type of more than a single RPC method
// set of names of rpc input- and output- types that were already encountered.
// this is needed to avoid duplicating type extractor since it's possible that
// the same type is used as an input or output type of more than a single RPC
// method
std::set<std::string> encounteredTypes;
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy
vars["arg_in_id"] = to_string(2L * i); // trying to make msvc 10 happy
vars["arg_out_id"] = to_string(2L * i + 1);
vars["method_name"] = method->name();
vars["input_type_name"] = method->get_input_type_name();
@ -353,8 +342,10 @@ static void PrintMethodFields(Printer* p, VARS& vars,
vars["method_field_name"] = MethodPropertiesFieldName(method.get());
vars["method_new_field_name"] = MethodPropertiesGetterName(method.get());
vars["method_method_name"] = MethodPropertiesGetterName(method.get());
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
bool client_streaming =
method->ClientStreaming() || method->BidiStreaming();
bool server_streaming =
method->ServerStreaming() || method->BidiStreaming();
if (client_streaming) {
if (server_streaming) {
vars["method_type"] = "BIDI_STREAMING";
@ -394,32 +385,32 @@ static void PrintMethodFields(Printer* p, VARS& vars,
}
p->Print(
vars,
"@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/"
"1901\")\n"
"public static $MethodDescriptor$<$input_type$,\n"
" $output_type$> $method_method_name$() {\n"
" $MethodDescriptor$<$input_type$, $output_type$> "
"$method_new_field_name$;\n"
" if (($method_new_field_name$ = "
"$service_class_name$.$method_new_field_name$) == null) {\n"
" synchronized ($service_class_name$.class) {\n"
" if (($method_new_field_name$ = "
"$service_class_name$.$method_new_field_name$) == null) {\n"
" $service_class_name$.$method_new_field_name$ = "
"$method_new_field_name$ = \n"
" $MethodDescriptor$.<$input_type$, "
"$output_type$>newBuilder()\n"
" .setType($MethodType$.$method_type$)\n"
" .setFullMethodName(generateFullMethodName(\n"
" \"$Package$$service_name$\", \"$method_name$\"))\n"
" .setSampledToLocalTracing(true)\n"
" .setRequestMarshaller(FlatbuffersUtils.marshaller(\n"
" $input_type$.class, "
"getExtractorOf$input_type_name$()))\n"
" .setResponseMarshaller(FlatbuffersUtils.marshaller(\n"
" $output_type$.class, "
"getExtractorOf$output_type_name$()))\n");
vars,
"@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/"
"1901\")\n"
"public static $MethodDescriptor$<$input_type$,\n"
" $output_type$> $method_method_name$() {\n"
" $MethodDescriptor$<$input_type$, $output_type$> "
"$method_new_field_name$;\n"
" if (($method_new_field_name$ = "
"$service_class_name$.$method_new_field_name$) == null) {\n"
" synchronized ($service_class_name$.class) {\n"
" if (($method_new_field_name$ = "
"$service_class_name$.$method_new_field_name$) == null) {\n"
" $service_class_name$.$method_new_field_name$ = "
"$method_new_field_name$ = \n"
" $MethodDescriptor$.<$input_type$, "
"$output_type$>newBuilder()\n"
" .setType($MethodType$.$method_type$)\n"
" .setFullMethodName(generateFullMethodName(\n"
" \"$Package$$service_name$\", \"$method_name$\"))\n"
" .setSampledToLocalTracing(true)\n"
" .setRequestMarshaller(FlatbuffersUtils.marshaller(\n"
" $input_type$.class, "
"getExtractorOf$input_type_name$()))\n"
" .setResponseMarshaller(FlatbuffersUtils.marshaller(\n"
" $output_type$.class, "
"getExtractorOf$output_type_name$()))\n");
// vars["proto_method_descriptor_supplier"] = service->name() +
// "MethodDescriptorSupplier";
@ -451,11 +442,11 @@ enum StubType {
enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 };
static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
const ServiceDescriptor* service);
static void PrintBindServiceMethodBody(Printer *p, VARS &vars,
const ServiceDescriptor *service);
// Prints a client interface or implementation class, or a server interface.
static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
StubType type) {
const string service_name = service->name();
vars["service_name"] = service_name;
@ -476,7 +467,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
break;
case BLOCKING_CLIENT_INTERFACE:
interface = true;
FLATBUFFERS_FALLTHROUGH(); // fall thru
FLATBUFFERS_FALLTHROUGH(); // fall thru
case BLOCKING_CLIENT_IMPL:
call_type = BLOCKING_CALL;
stub_name += "BlockingStub";
@ -484,7 +475,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
break;
case FUTURE_CLIENT_INTERFACE:
interface = true;
FLATBUFFERS_FALLTHROUGH(); // fall thru
FLATBUFFERS_FALLTHROUGH(); // fall thru
case FUTURE_CLIENT_IMPL:
call_type = FUTURE_CALL;
stub_name += "FutureStub";
@ -501,9 +492,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
vars["client_name"] = client_name;
// Class head
if (!interface) {
GrpcWriteServiceDocComment(p, vars, service);
}
if (!interface) { GrpcWriteServiceDocComment(p, vars, service); }
if (impl_base) {
p->Print(vars,
"public static abstract class $abstract_name$ implements "
@ -546,8 +535,10 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
vars["lower_method_name"] = LowerMethodName(&*method);
vars["method_method_name"] = MethodPropertiesGetterName(&*method);
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
bool client_streaming =
method->ClientStreaming() || method->BidiStreaming();
bool server_streaming =
method->ServerStreaming() || method->BidiStreaming();
if (call_type == BLOCKING_CALL && client_streaming) {
// Blocking client interface with client streaming is not available
@ -563,9 +554,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
p->Print("\n");
// TODO(nmittler): Replace with WriteMethodDocComment once included by the
// protobuf distro.
if (!interface) {
GrpcWriteMethodDocComment(p, vars, &*method);
}
if (!interface) { GrpcWriteMethodDocComment(p, vars, &*method); }
p->Print("public ");
switch (call_type) {
case BLOCKING_CALL:
@ -630,8 +619,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
"responseObserver);\n");
}
break;
default:
break;
default: break;
}
} else if (!interface) {
switch (call_type) {
@ -706,15 +694,15 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
}
static bool CompareMethodClientStreaming(
const std::unique_ptr<const grpc_generator::Method>& method1,
const std::unique_ptr<const grpc_generator::Method>& method2) {
const std::unique_ptr<const grpc_generator::Method> &method1,
const std::unique_ptr<const grpc_generator::Method> &method2) {
return method1->ClientStreaming() < method2->ClientStreaming();
}
// Place all method invocations into a single class to reduce memory footprint
// on Android.
static void PrintMethodHandlerClass(Printer* p, VARS& vars,
const ServiceDescriptor* service) {
static void PrintMethodHandlerClass(Printer *p, VARS &vars,
const ServiceDescriptor *service) {
// Sort method ids based on ClientStreaming() so switch tables are compact.
std::vector<std::unique_ptr<const grpc_generator::Method>> sorted_methods(
service->method_count());
@ -724,7 +712,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
stable_sort(sorted_methods.begin(), sorted_methods.end(),
CompareMethodClientStreaming);
for (size_t i = 0; i < sorted_methods.size(); i++) {
auto& method = sorted_methods[i];
auto &method = sorted_methods[i];
vars["method_id"] = to_string(i);
vars["method_id_name"] = MethodIdFieldName(&*method);
p->Print(vars,
@ -757,9 +745,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (method->ClientStreaming() || method->BidiStreaming()) {
continue;
}
if (method->ClientStreaming() || method->BidiStreaming()) { continue; }
vars["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
@ -791,9 +777,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
if (!(method->ClientStreaming() || method->BidiStreaming())) {
continue;
}
if (!(method->ClientStreaming() || method->BidiStreaming())) { continue; }
vars["method_id_name"] = MethodIdFieldName(&*method);
vars["lower_method_name"] = LowerMethodName(&*method);
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
@ -818,8 +802,8 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
p->Print("}\n\n");
}
static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
const ServiceDescriptor* service) {
static void PrintGetServiceDescriptorMethod(Printer *p, VARS &vars,
const ServiceDescriptor *service) {
vars["service_name"] = service->name();
// vars["proto_base_descriptor_supplier"] = service->name() +
// "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] =
@ -911,8 +895,8 @@ static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
p->Print("}\n");
}
static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
const ServiceDescriptor* service) {
static void PrintBindServiceMethodBody(Printer *p, VARS &vars,
const ServiceDescriptor *service) {
vars["service_name"] = service->name();
p->Indent();
p->Print(vars,
@ -927,8 +911,10 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
vars["method_id_name"] = MethodIdFieldName(&*method);
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
bool client_streaming =
method->ClientStreaming() || method->BidiStreaming();
bool server_streaming =
method->ServerStreaming() || method->BidiStreaming();
if (client_streaming) {
if (server_streaming) {
vars["calls_method"] = "asyncBidiStreamingCall";
@ -962,8 +948,8 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
p->Outdent();
}
static void PrintService(Printer* p, VARS& vars,
const ServiceDescriptor* service,
static void PrintService(Printer *p, VARS &vars,
const ServiceDescriptor *service,
bool disable_version) {
vars["service_name"] = service->name();
vars["service_class_name"] = ServiceClassName(service->name());
@ -1043,7 +1029,7 @@ static void PrintService(Printer* p, VARS& vars,
p->Print("}\n");
}
void PrintStaticImports(Printer* p) {
void PrintStaticImports(Printer *p) {
p->Print(
"import java.nio.ByteBuffer;\n"
"import static "
@ -1076,8 +1062,8 @@ void PrintStaticImports(Printer* p) {
"io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n");
}
void GenerateService(const grpc_generator::Service* service,
grpc_generator::Printer* printer, VARS& vars,
void GenerateService(const grpc_generator::Service *service,
grpc_generator::Printer *printer, VARS &vars,
bool disable_version) {
// All non-generated classes must be referred by fully qualified names to
// avoid collision with generated classes.
@ -1113,8 +1099,8 @@ void GenerateService(const grpc_generator::Service* service,
}
grpc::string GenerateServiceSource(
grpc_generator::File* file, const grpc_generator::Service* service,
grpc_java_generator::Parameters* parameters) {
grpc_generator::File *file, const grpc_generator::Service *service,
grpc_java_generator::Parameters *parameters) {
grpc::string out;
auto printer = file->CreatePrinter(&out);
VARS vars;

View File

@ -21,7 +21,6 @@
#include <utility>
#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
namespace grpc_python_generator {

View File

@ -19,11 +19,10 @@
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#include <map>
#include <memory>
#include <vector>
#include "src/compiler/config.h"
#ifndef GRPC_CUSTOM_STRING
# include <string>
# define GRPC_CUSTOM_STRING std::string

View File

@ -1,40 +1,22 @@
/*
* Copyright 2020 Google Inc. All rights reserved.
*
* Copyright 2020, 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* 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.
*/
#include <memory>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING

View File

@ -1,41 +1,7 @@
/*
*
* Copyright 2020, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <memory>
#include <vector>
#include <set>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING
@ -58,4 +24,3 @@ grpc::string GenerateInterface(grpc_generator::File *file,
const grpc_generator::Service *service,
const grpc::string &filename);
} // namespace grpc_ts_generator

View File

@ -285,9 +285,7 @@ class FlatBufferBuilder {
FieldLoc fl = { off, field };
buf_.scratch_push_small(fl);
num_field_loc++;
if (field > max_voffset_) {
max_voffset_ = field;
}
if (field > max_voffset_) { max_voffset_ = field; }
}
// Like PushElement, but additionally tracks the field this represents.
@ -1074,7 +1072,7 @@ class FlatBufferBuilder {
void SwapBufAllocator(FlatBufferBuilder &other) {
buf_.swap_allocator(other.buf_);
}
/// @brief The length of a FlatBuffer file header.
static const size_t kFileIdentifierLength =
::flatbuffers::kFileIdentifierLength;

View File

@ -226,27 +226,13 @@ struct TypeTable {
};
// String which identifies the current version of FlatBuffers.
// flatbuffer_version_string is used by Google developers to identify which
// applications uploaded to Google Play are using this library. This allows
// the development team at Google to determine the popularity of the library.
// How it works: Applications that are uploaded to the Google Play Store are
// scanned for this version string. We track which applications are using it
// to measure popularity. You are free to remove it (of course) but we would
// appreciate if you left it in.
inline const char *flatbuffers_version_string() {
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
}
// Weak linkage is culled by VS & doesn't work on cygwin.
// clang-format off
#if !defined(_WIN32) && !defined(__CYGWIN__)
extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
volatile __attribute__((weak)) const char *flatbuffer_version_string =
"FlatBuffers "
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
#endif // !defined(_WIN32) && !defined(__CYGWIN__)
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
inline E operator | (E lhs, E rhs){\
return E(T(lhs) | T(rhs));\

View File

@ -49,6 +49,8 @@ class FlatCompiler {
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
typedef bool (*ParsingCompletedFn)(const flatbuffers::Parser &parser,
const std::string &output_path);
GenerateFn generate;
const char *lang_name;
@ -58,6 +60,7 @@ class FlatCompiler {
FlatCOption option;
MakeRuleFn make_rule;
BfbsGenerator *bfbs_generator;
ParsingCompletedFn parsing_completed;
};
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
@ -84,6 +87,7 @@ class FlatCompiler {
int Compile(int argc, const char **argv);
std::string GetShortUsageString(const char *program_name) const;
std::string GetUsageString(const char *program_name) const;
private:

View File

@ -371,10 +371,7 @@ void AppendToString(std::string &s, T &&v, bool keys_quoted) {
class Reference {
public:
Reference()
: data_(nullptr),
parent_width_(0),
byte_width_(0),
type_(FBT_NULL) {}
: data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
Type type)
@ -1645,8 +1642,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// comes at the cost of using additional memory the same size of
// the buffer being verified, so it is by default off.
std::vector<uint8_t> *reuse_tracker = nullptr,
bool _check_alignment = true,
size_t max_depth = 64)
bool _check_alignment = true, size_t max_depth = 64)
: buf_(buf),
size_(buf_len),
depth_(0),
@ -1689,18 +1685,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
auto o = static_cast<size_t>(p - buf_);
return VerifyBefore(o, len);
}
bool VerifyByteWidth(size_t width) {
return Check(width == 1 || width == 2 || width == 4 || width == 8);
}
bool VerifyType(int type) {
return Check(type >= 0 && type < FBT_MAX_TYPE);
}
bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }
bool VerifyOffset(uint64_t off, const uint8_t *p) {
return Check(off <= static_cast<uint64_t>(size_)) &&
off <= static_cast<uint64_t>(p - buf_);
off <= static_cast<uint64_t>(p - buf_);
}
bool VerifyAlignment(const uint8_t *p, size_t size) const {
@ -1708,16 +1702,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return Check((o & (size - 1)) == 0 || !check_alignment_);
}
// Macro, since we want to escape from parent function & use lazy args.
#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \
if (reuse_tracker_) { \
auto packed_type = PACKED_TYPE; \
auto existing = (*reuse_tracker_)[P - buf_]; \
if (existing == packed_type) return true; \
/* Fail verification if already set with different type! */ \
if (!Check(existing == 0)) return false; \
(*reuse_tracker_)[P - buf_] = packed_type; \
}
// Macro, since we want to escape from parent function & use lazy args.
#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \
if (reuse_tracker_) { \
auto packed_type = PACKED_TYPE; \
auto existing = (*reuse_tracker_)[P - buf_]; \
if (existing == packed_type) return true; \
/* Fail verification if already set with different type! */ \
if (!Check(existing == 0)) return false; \
(*reuse_tracker_)[P - buf_] = packed_type; \
}
bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) {
// Any kind of nesting goes thru this function, so guard against that
@ -1727,19 +1721,19 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
return false;
auto size_byte_width = r.byte_width_;
FLEX_CHECK_VERIFIED(p, PackedType(Builder::WidthB(size_byte_width), r.type_));
if (!VerifyBeforePointer(p, size_byte_width))
return false;
FLEX_CHECK_VERIFIED(p,
PackedType(Builder::WidthB(size_byte_width), r.type_));
if (!VerifyBeforePointer(p, size_byte_width)) return false;
auto sized = Sized(p, size_byte_width);
auto num_elems = sized.size();
auto elem_byte_width =
r.type_ == FBT_STRING || r.type_ == FBT_BLOB ? uint8_t(1) : r.byte_width_;
auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
? uint8_t(1)
: r.byte_width_;
auto max_elems = SIZE_MAX / elem_byte_width;
if (!Check(num_elems < max_elems))
return false; // Protect against byte_size overflowing.
auto byte_size = num_elems * elem_byte_width;
if (!VerifyFromPointer(p, byte_size))
return false;
if (!VerifyFromPointer(p, byte_size)) return false;
if (elem_type == FBT_NULL) {
// Verify type bytes after the vector.
if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
@ -1760,28 +1754,25 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
// The vector part of the map has already been verified.
const size_t num_prefixed_fields = 3;
if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields))
return false;
if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
p -= byte_width * num_prefixed_fields;
auto off = ReadUInt64(p, byte_width);
if (!VerifyOffset(off, p))
return false;
if (!VerifyOffset(off, p)) return false;
auto key_byte_with =
static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
if (!VerifyByteWidth(key_byte_with))
return false;
static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
if (!VerifyByteWidth(key_byte_with)) return false;
return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
p - off, FBT_KEY);
}
bool VerifyKey(const uint8_t* p) {
bool VerifyKey(const uint8_t *p) {
FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
while (p < buf_ + size_)
if (*p++) return true;
return false;
}
#undef FLEX_CHECK_VERIFIED
#undef FLEX_CHECK_VERIFIED
bool VerifyTerminator(const String &s) {
return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
@ -1799,37 +1790,26 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// All remaining types are an offset.
auto off = ReadUInt64(r.data_, r.parent_width_);
if (!VerifyOffset(off, r.data_))
return false;
if (!VerifyOffset(off, r.data_)) return false;
auto p = r.Indirect();
if (!VerifyAlignment(p, r.byte_width_))
return false;
if (!VerifyAlignment(p, r.byte_width_)) return false;
switch (r.type_) {
case FBT_INDIRECT_INT:
case FBT_INDIRECT_UINT:
case FBT_INDIRECT_FLOAT:
return VerifyFromPointer(p, r.byte_width_);
case FBT_KEY:
return VerifyKey(p);
case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
case FBT_KEY: return VerifyKey(p);
case FBT_MAP:
return VerifyVector(r, p, FBT_NULL) &&
VerifyKeys(p, r.byte_width_);
case FBT_VECTOR:
return VerifyVector(r, p, FBT_NULL);
case FBT_VECTOR_INT:
return VerifyVector(r, p, FBT_INT);
return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
case FBT_VECTOR_BOOL:
case FBT_VECTOR_UINT:
return VerifyVector(r, p, FBT_UINT);
case FBT_VECTOR_FLOAT:
return VerifyVector(r, p, FBT_FLOAT);
case FBT_VECTOR_KEY:
return VerifyVector(r, p, FBT_KEY);
case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
case FBT_VECTOR_STRING_DEPRECATED:
// Use of FBT_KEY here intentional, see elsewhere.
return VerifyVector(r, p, FBT_KEY);
case FBT_BLOB:
return VerifyVector(r, p, FBT_UINT);
case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
case FBT_STRING:
return VerifyVector(r, p, FBT_UINT) &&
VerifyTerminator(String(p, r.byte_width_));
@ -1844,12 +1824,10 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
case FBT_VECTOR_FLOAT4: {
uint8_t len = 0;
auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
if (!VerifyType(vtype))
return false;
if (!VerifyType(vtype)) return false;
return VerifyFromPointer(p, r.byte_width_ * len);
}
default:
return false;
default: return false;
}
}
@ -1859,8 +1837,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
auto end = buf_ + size_;
auto byte_width = *--end;
auto packed_type = *--end;
return VerifyByteWidth(byte_width) &&
Check(end - buf_ >= byte_width) &&
return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
VerifyRef(Reference(end - byte_width, byte_width, packed_type));
}
@ -1875,14 +1852,14 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
std::vector<uint8_t> *reuse_tracker_;
};
// Utility function that contructs the Verifier for you, see above for parameters.
// Utility function that contructs the Verifier for you, see above for
// parameters.
inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
std::vector<uint8_t> *reuse_tracker = nullptr) {
Verifier verifier(buf, buf_len, reuse_tracker);
return verifier.VerifyBuffer();
}
#ifdef FLATBUFFERS_H_
// This is a verifier utility function that works together with the
// FlatBuffers verifier, which should only be present if flatbuffer.h
@ -1890,9 +1867,8 @@ inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
inline bool VerifyNestedFlexBuffer(const flatbuffers::Vector<uint8_t> *nv,
flatbuffers::Verifier &verifier) {
if (!nv) return true;
return verifier.Check(
flexbuffers::VerifyBuffer(nv->data(), nv->size(),
verifier.GetFlexReuseTracker()));
return verifier.Check(flexbuffers::VerifyBuffer(
nv->data(), nv->size(), verifier.GetFlexReuseTracker()));
}
#endif

View File

@ -72,8 +72,8 @@ namespace flatbuffers {
// - Go type.
// - C# / .Net type.
// - Python type.
// - Rust type.
// - Kotlin type.
// - Rust type.
// using these macros, we can now write code dealing with types just once, e.g.
@ -468,6 +468,10 @@ inline bool IsUnion(const Type &type) {
return type.enum_def != nullptr && type.enum_def->is_union;
}
inline bool IsUnionType(const Type &type) {
return IsUnion(type) && IsInteger(type.base_type);
}
inline bool IsVector(const Type &type) {
return type.base_type == BASE_TYPE_VECTOR;
}
@ -591,6 +595,7 @@ struct IDLOptions {
std::string filename_suffix;
std::string filename_extension;
bool no_warnings;
bool warnings_as_errors;
std::string project_root;
bool cs_global_alias;
bool json_nested_flatbuffers;
@ -625,6 +630,9 @@ struct IDLOptions {
// If set, require all fields in a table to be explicitly numbered.
bool require_explicit_ids;
// If set, implement serde::Serialize for generated Rust types
bool rust_serialize;
// The corresponding language bit will be set if a language is included
// for code generation.
unsigned long lang_to_generate;
@ -681,6 +689,7 @@ struct IDLOptions {
filename_suffix("_generated"),
filename_extension(),
no_warnings(false),
warnings_as_errors(false),
project_root(""),
cs_global_alias(false),
json_nested_flatbuffers(true),
@ -688,6 +697,7 @@ struct IDLOptions {
json_nested_legacy_flatbuffers(false),
mini_reflect(IDLOptions::kNone),
require_explicit_ids(false),
rust_serialize(false),
lang_to_generate(0),
set_empty_strings_to_null(true),
set_empty_vectors_to_null(true) {}
@ -787,6 +797,7 @@ class Parser : public ParserState {
root_struct_def_(nullptr),
opts(options),
uses_flexbuffers_(false),
has_warning_(false),
advanced_features_(0),
source_(nullptr),
anonymous_counter_(0),
@ -1021,6 +1032,7 @@ class Parser : public ParserState {
IDLOptions opts;
bool uses_flexbuffers_;
bool has_warning_;
uint64_t advanced_features_;

View File

@ -1413,6 +1413,11 @@ inline bool SchemaBufferHasIdentifier(const void *buf) {
buf, SchemaIdentifier());
}
inline bool SizePrefixedSchemaBufferHasIdentifier(const void *buf) {
return flatbuffers::BufferHasIdentifier(
buf, SchemaIdentifier(), true);
}
inline bool VerifySchemaBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());

View File

@ -112,18 +112,19 @@ class Table {
// Verify a particular field.
template<typename T>
bool VerifyField(const Verifier &verifier, voffset_t field, size_t align) const {
bool VerifyField(const Verifier &verifier, voffset_t field,
size_t align) const {
// Calling GetOptionalFieldOffset should be safe now thanks to
// VerifyTable().
auto field_offset = GetOptionalFieldOffset(field);
// Check the actual field.
return !field_offset ||
verifier.VerifyField<T>(data_, field_offset, align);
return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
}
// VerifyField for required fields.
template<typename T>
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field, size_t align) const {
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
size_t align) const {
auto field_offset = GetOptionalFieldOffset(field);
return verifier.Check(field_offset != 0) &&
verifier.VerifyField<T>(data_, field_offset, align);

View File

@ -17,15 +17,15 @@
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
#include <errno.h>
#include <ctype.h>
#include <errno.h>
#include "flatbuffers/base.h"
#include "flatbuffers/stl_emulation.h"
#ifndef FLATBUFFERS_PREFER_PRINTF
# include <sstream>
# include <iomanip>
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>

View File

@ -81,14 +81,15 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Verify relative to a known-good base pointer.
bool VerifyFieldStruct(const uint8_t *base, voffset_t elem_off, size_t elem_len,
size_t align) const {
bool VerifyFieldStruct(const uint8_t *base, voffset_t elem_off,
size_t elem_len, size_t align) const {
auto f = static_cast<size_t>(base - buf_) + elem_off;
return VerifyAlignment(f, align) && Verify(f, elem_len);
}
template<typename T>
bool VerifyField(const uint8_t *base, voffset_t elem_off, size_t align) const {
bool VerifyField(const uint8_t *base, voffset_t elem_off,
size_t align) const {
auto f = static_cast<size_t>(base - buf_) + elem_off;
return VerifyAlignment(f, align) && Verify(f, sizeof(T));
}
@ -259,9 +260,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// clang-format on
}
std::vector<uint8_t> *GetFlexReuseTracker() {
return flex_reuse_tracker_;
}
std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
void SetFlexReuseTracker(std::vector<uint8_t> *rt) {
flex_reuse_tracker_ = rt;