Commit 1906f0e2 authored by Giorgio Azzinnaro's avatar Giorgio Azzinnaro

Parse nested message

Normalized descriptor pool generation
parent 2a4e546b
......@@ -21,4 +21,12 @@ message Nested {
string nested_field_one_str = 1 [ (profanedb.protobuf.options).key = true ];
int64 nested_field_two_int = 2;
double nested_field_three_double = 3;
message KeyableNestedInNested {
string nested_in_nested_field_one_str = 1 [ (profanedb.protobuf.options).key = true ];
}
// message NotKeyableNestedInNested {
// int32 nested_in_nested_field_one_int = 1;
// }
}
......@@ -37,10 +37,10 @@ profanedb::protobuf::GetResp profanedb::storage::Db::Get(const profanedb::protob
profanedb::protobuf::PutResp profanedb::storage::Db::Put(const profanedb::protobuf::PutReq & request)
{
auto map = parser.NormalizeMessage(request.serializable());
auto map = normalizer.NormalizeMessage(request.serializable());
for (auto const & obj: map) {
std::cout << obj.first << ":" << std::endl << obj.second.SerializeAsString() << std::endl;
std::cout << obj.first << ":" << std::endl << obj.second->SerializeAsString() << std::endl;
}
}
......
......@@ -25,5 +25,26 @@ profanedb::storage::Normalizer::Normalizer(Parser & parser)
new google::protobuf::MergedDescriptorDatabase(parser.rootDescriptorDb.get(), parser.normalizedDescriptorDb.get()))
, normalizedPool(new google::protobuf::DescriptorPool(normalizedMergedDescriptorDb.get()))
{
std::cout << normalizedPool->FindFileByName("test.proto")->DebugString() << std::endl;
}
map< std::string, std::shared_ptr<google::protobuf::Message> > profanedb::storage::Normalizer::NormalizeMessage(
const google::protobuf::Any & serializable)
{
// Any messages have a type url beginning with `type.googleapis.com/`, this is stripped
std::string type = serializable.type_url();
auto definition = std::unique_ptr<const google::protobuf::Descriptor>(schemaPool->FindMessageTypeByName(type.substr(type.rfind('/')+1, std::string::npos)));
// Having the definition our message factory can simply generate a container,
auto container = std::unique_ptr<google::protobuf::Message>(messageFactory.GetPrototype(definition.get())->New());
// and convert the bytes coming from Any into it
serializable.UnpackTo(container.get());
// The method getting a Message as paramater does the actual normalization of data
return this->NormalizeMessage(*container);
}
map< std::string, std::shared_ptr<google::protobuf::Message> > profanedb::storage::Normalizer::NormalizeMessage(
const google::protobuf::Message & message) const
{
}
......@@ -23,22 +23,41 @@
#include <map>
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/any.h>
#include <google/protobuf/message.h>
#include "parser.h"
namespace profanedb {
namespace storage {
// Normalizer takes care of converting a message as defined by the user
// into a map of keys and Messages,
// where any keyable nested message is brought to top level
// and its key is used as reference in the parent message
class Normalizer
{
public:
Normalizer(Parser & parser);
// This is just a layer on top of NormalizeMessage(Message) to parse an Any message
map< std::string, std::shared_ptr<google::protobuf::Message> > NormalizeMessage(
const google::protobuf::Any & serializable);
// Unnest keyable messages and assign their key to their parent object
map< std::string, std::shared_ptr<google::protobuf::Message> > NormalizeMessage(
const google::protobuf::Message & message) const;
private:
// This holds the schema as defined by the user (needed to parse the incoming messages)
std::shared_ptr<google::protobuf::DescriptorPool> schemaPool;
// A reference to /usr/include and profanedb/protobuf/options.proto
// + keyable message fields converted to hold a reference of their key
std::unique_ptr<google::protobuf::MergedDescriptorDatabase> normalizedMergedDescriptorDb;
std::shared_ptr<google::protobuf::DescriptorPool> normalizedPool;
google::protobuf::DynamicMessageFactory messageFactory;
};
}
}
......
This diff is collapsed.
......@@ -41,19 +41,16 @@ using namespace google::protobuf;
namespace profanedb {
namespace storage {
// Given a Any message, Parser looks for the corresponding definition in .proto files,
// and generates a map with keys of nested messages
// Parser loads the whole schema definition,
// and generates descriptors where nested keyable messages are made into references.
// These references are the actual keys
// which will be used to store this nested messages.
class Parser
{
friend class Normalizer;
public:
Parser(const Config::ProfaneDB & profaneConfig);
~Parser();
// Using the provided schema, get a map with all nested messages and their unique key
map<std::string, const Message &> NormalizeMessage(const Any & serializable);
map<std::string, const Message &> NormalizeMessage(const Message & message);
private:
std::unique_ptr<compiler::SourceTreeDescriptorDatabase> rootDescriptorDb;
......@@ -63,11 +60,15 @@ private:
std::shared_ptr<DescriptorPool> schemaPool;
std::unique_ptr<SimpleDescriptorDatabase> normalizedDescriptorDb;
// Change nested message fields in proto if reference is to be set
void ParseMessageDescriptor(
const google::protobuf::Descriptor & desc,
google::protobuf::DescriptorProto & proto
);
DynamicMessageFactory messageFactory;
// Given a Field
string FieldToKey(const Message & container, const FieldDescriptor & fd);
// Check if a message has a key defined in its schema
bool IsKeyable(const google::protobuf::Descriptor & desc);
// A simple ErrorCollector for debug, write to stderr
class ErrorCollector : public compiler::MultiFileErrorCollector {
......
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