mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-25 02:36:09 +00:00
Added RPC declarations to the schema parser.
This is the first step in RPC support. Actual code generation to follow. Change-Id: I96c40fec3db671d100dd9eb509a71c5cbe55bfb2 Tested: on Linux. Bug: 20122696
This commit is contained in:
@@ -225,6 +225,20 @@ This declaration in the schema will change that to whatever you want:
|
|||||||
|
|
||||||
file_extension "ext";
|
file_extension "ext";
|
||||||
|
|
||||||
|
### RPC interface declarations
|
||||||
|
|
||||||
|
You can declare RPC calls in a schema, that define a set of functions
|
||||||
|
that take a FlatBuffer as an argument (the request) and return a FlatBuffer
|
||||||
|
as the response (both of which must be table types):
|
||||||
|
|
||||||
|
rpc_service MonsterStorage {
|
||||||
|
Store(Monster):StoreResponse;
|
||||||
|
Retrieve(MonsterId):Monster;
|
||||||
|
}
|
||||||
|
|
||||||
|
What code this produces and how it is used depends on language and RPC system
|
||||||
|
used, FlatBuffers itself does not offer this functionality.
|
||||||
|
|
||||||
### Comments & documentation
|
### Comments & documentation
|
||||||
|
|
||||||
May be written as in most C-based languages. Additionally, a triple
|
May be written as in most C-based languages. Additionally, a triple
|
||||||
|
|||||||
@@ -306,6 +306,15 @@ struct EnumDef : public Definition {
|
|||||||
Type underlying_type;
|
Type underlying_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RPCCall {
|
||||||
|
std::string name;
|
||||||
|
StructDef *request, *response;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServiceDef : public Definition {
|
||||||
|
SymbolTable<RPCCall> calls;
|
||||||
|
};
|
||||||
|
|
||||||
// Container of options that may apply to any of the source/text generators.
|
// Container of options that may apply to any of the source/text generators.
|
||||||
struct IDLOptions {
|
struct IDLOptions {
|
||||||
bool strict_json;
|
bool strict_json;
|
||||||
@@ -479,6 +488,7 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
||||||
StructDef **dest);
|
StructDef **dest);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
||||||
|
FLATBUFFERS_CHECKED_ERROR ParseService();
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
||||||
bool isextend, bool inside_oneof);
|
bool isextend, bool inside_oneof);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
|
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
|
||||||
@@ -501,6 +511,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
SymbolTable<StructDef> structs_;
|
SymbolTable<StructDef> structs_;
|
||||||
SymbolTable<EnumDef> enums_;
|
SymbolTable<EnumDef> enums_;
|
||||||
|
SymbolTable<ServiceDef> services_;
|
||||||
std::vector<Namespace *> namespaces_;
|
std::vector<Namespace *> namespaces_;
|
||||||
std::string error_; // User readable error_ if Parse() == false
|
std::string error_; // User readable error_ if Parse() == false
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,8 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
|||||||
TD(FileExtension, 268, "file_extension") \
|
TD(FileExtension, 268, "file_extension") \
|
||||||
TD(Include, 269, "include") \
|
TD(Include, 269, "include") \
|
||||||
TD(Attribute, 270, "attribute") \
|
TD(Attribute, 270, "attribute") \
|
||||||
TD(Null, 271, "null")
|
TD(Null, 271, "null") \
|
||||||
|
TD(Service, 272, "rpc_service")
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
||||||
#endif
|
#endif
|
||||||
@@ -360,6 +361,10 @@ CheckedError Parser::Next() {
|
|||||||
token_ = kTokenNull;
|
token_ = kTokenNull;
|
||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
if (attribute_ == "rpc_service") {
|
||||||
|
token_ = kTokenService;
|
||||||
|
return NoError();
|
||||||
|
}
|
||||||
// If not, it is a user-defined identifier:
|
// If not, it is a user-defined identifier:
|
||||||
token_ = kTokenIdentifier;
|
token_ = kTokenIdentifier;
|
||||||
return NoError();
|
return NoError();
|
||||||
@@ -1243,6 +1248,45 @@ CheckedError Parser::ParseDecl() {
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckedError Parser::ParseService() {
|
||||||
|
std::vector<std::string> service_comment = doc_comment_;
|
||||||
|
NEXT();
|
||||||
|
auto service_name = attribute_;
|
||||||
|
EXPECT(kTokenIdentifier);
|
||||||
|
auto &service_def = *new ServiceDef();
|
||||||
|
service_def.name = service_name;
|
||||||
|
service_def.file = file_being_parsed_;
|
||||||
|
service_def.doc_comment = service_comment;
|
||||||
|
service_def.defined_namespace = namespaces_.back();
|
||||||
|
if (services_.Add(namespaces_.back()->GetFullyQualifiedName(service_name),
|
||||||
|
&service_def))
|
||||||
|
return Error("service already exists: " + service_name);
|
||||||
|
ECHECK(ParseMetaData(service_def));
|
||||||
|
EXPECT('{');
|
||||||
|
do {
|
||||||
|
auto rpc_name = attribute_;
|
||||||
|
EXPECT(kTokenIdentifier);
|
||||||
|
EXPECT('(');
|
||||||
|
Type reqtype, resptype;
|
||||||
|
ECHECK(ParseTypeIdent(reqtype));
|
||||||
|
EXPECT(')');
|
||||||
|
EXPECT(':');
|
||||||
|
ECHECK(ParseTypeIdent(resptype));
|
||||||
|
if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed ||
|
||||||
|
resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed)
|
||||||
|
return Error("rpc request and response types must be tables");
|
||||||
|
auto &rpc = *new RPCCall();
|
||||||
|
rpc.name = rpc_name;
|
||||||
|
rpc.request = reqtype.struct_def;
|
||||||
|
rpc.response = resptype.struct_def;
|
||||||
|
if (service_def.calls.Add(rpc_name, &rpc))
|
||||||
|
return Error("rpc already exists: " + rpc_name);
|
||||||
|
EXPECT(';');
|
||||||
|
} while (token_ != '}');
|
||||||
|
NEXT();
|
||||||
|
return NoError();
|
||||||
|
}
|
||||||
|
|
||||||
bool Parser::SetRootType(const char *name) {
|
bool Parser::SetRootType(const char *name) {
|
||||||
root_struct_def_ = structs_.Lookup(name);
|
root_struct_def_ = structs_.Lookup(name);
|
||||||
if (!root_struct_def_)
|
if (!root_struct_def_)
|
||||||
@@ -1739,6 +1783,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
|||||||
EXPECT(kTokenStringConstant);
|
EXPECT(kTokenStringConstant);
|
||||||
EXPECT(';');
|
EXPECT(';');
|
||||||
known_attributes_.insert(name);
|
known_attributes_.insert(name);
|
||||||
|
} else if (token_ == kTokenService) {
|
||||||
|
ECHECK(ParseService());
|
||||||
} else {
|
} else {
|
||||||
ECHECK(ParseDecl());
|
ECHECK(ParseDecl());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ table Monster {
|
|||||||
testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64");
|
testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpc_service MonsterStorage {
|
||||||
|
Store(Monster):Stat;
|
||||||
|
Retrieve(Stat):Monster;
|
||||||
|
}
|
||||||
|
|
||||||
root_type Monster;
|
root_type Monster;
|
||||||
|
|
||||||
file_identifier "MONS";
|
file_identifier "MONS";
|
||||||
|
|||||||
Reference in New Issue
Block a user