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
parent fbc8af40
...@@ -225,6 +225,20 @@ This declaration in the schema will change that to whatever you want: ...@@ -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 { ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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() { ...@@ -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() { ...@@ -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, ...@@ -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 { ...@@ -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";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment