Protocol Buffers - Google's data interchange format (grpc依赖) https://developers.google.com/protocol-buffers/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
9.1 KiB

//
// upb - a minimalist implementation of protocol buffers.
//
// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
// Author: Josh Haberman <jhaberman@gmail.com>
//
// IMPORTANT NOTE! This file is compiled TWICE, once with UPB_GOOGLE3 defined
// and once without! This allows us to provide functionality against proto2
// and protobuf opensource both in a single binary without the two conflicting.
// However we must be careful not to violate the ODR.
#include "upb/google/bridge.h"
#include <stdio.h>
#include <map>
#include <string>
#include "upb/def.h"
#include "upb/google/proto1.h"
#include "upb/google/proto2.h"
#include "upb/handlers.h"
namespace upb {
namespace proto2_bridge_google3 { class Defs; }
namespace proto2_bridge_opensource { class Defs; }
} // namespace upb
#ifdef UPB_GOOGLE3
#include "net/proto2/public/descriptor.h"
#include "net/proto2/public/message.h"
#include "net/proto2/proto/descriptor.pb.h"
namespace goog = ::proto2;
namespace me = ::upb::proto2_bridge_google3;
#else
#include "google/protobuf/descriptor.h"
#include "google/protobuf/message.h"
#include "google/protobuf/descriptor.pb.h"
namespace goog = ::google::protobuf;
namespace me = ::upb::proto2_bridge_opensource;
#endif
class me::Defs {
public:
void OnMessage(Handlers* h) {
const upb::MessageDef* md = h->message_def();
const goog::Message& m = *message_map_[md];
const goog::Descriptor* d = m.GetDescriptor();
for (upb::MessageDef::ConstIterator i(md); !i.Done(); i.Next()) {
const upb::FieldDef* upb_f = i.field();
const goog::FieldDescriptor* proto2_f =
d->FindFieldByNumber(upb_f->number());
if (!proto2_f) {
proto2_f = d->file()->pool()->FindExtensionByNumber(d, upb_f->number());
}
assert(proto2_f);
if (!upb::google::TrySetWriteHandlers(proto2_f, m, upb_f, h)
#ifdef UPB_GOOGLE3
&& !upb::google::TrySetProto1WriteHandlers(proto2_f, m, upb_f, h)
#endif
) {
// Unsupported reflection class.
//
// Should we fall back to using the public Reflection interface in this
// case? It's unclear whether it's supported behavior for users to
// create their own Reflection classes.
assert(false);
}
}
}
static void StaticOnMessage(void* closure, upb::Handlers* handlers) {
me::Defs* defs = static_cast<me::Defs*>(closure);
defs->OnMessage(handlers);
}
void AddSymbol(const std::string& name, upb::Def* def) {
assert(symbol_map_.find(name) == symbol_map_.end());
symbol_map_[name] = def;
}
void AddMessage(const goog::Message* m, upb::MessageDef* md) {
assert(message_map_.find(md) == message_map_.end());
message_map_[md] = m;
AddSymbol(m->GetDescriptor()->full_name(), md->Upcast());
}
upb::Def* FindSymbol(const std::string& name) {
SymbolMap::iterator iter = symbol_map_.find(name);
return iter != symbol_map_.end() ? iter->second : NULL;
}
void Flatten(std::vector<upb::Def*>* defs) {
SymbolMap::iterator iter;
for (iter = symbol_map_.begin(); iter != symbol_map_.end(); ++iter) {
defs->push_back(iter->second);
}
}
private:
// Maps a new upb::MessageDef* to a corresponding proto2 Message* whose
// derived class is of the correct type according to the message the user
// gave us.
typedef std::map<const upb::MessageDef*, const goog::Message*> MessageMap;
MessageMap message_map_;
// Maps a type name to a upb Def we have constructed to represent it.
typedef std::map<std::string, upb::Def*> SymbolMap;
SymbolMap symbol_map_;
};
namespace upb {
namespace google {
// For submessage fields, stores a pointer to an instance of the submessage in
// *subm (but it is *not* guaranteed to be a prototype).
FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f,
upb::MessageDef* md, const goog::Message** subm) {
// To parse weak submessages effectively, we need to represent them in the
// upb::Def schema even though they are not reflected in the proto2
// descriptors (weak fields are represented as FieldDescriptor::TYPE_BYTES).
const goog::Message* weak_prototype = NULL;
#ifdef UPB_GOOGLE3
weak_prototype = upb::google::GetProto1WeakPrototype(m, f);
#endif
upb::FieldDef* upb_f = upb::FieldDef::New(&upb_f);
upb::Status status;
upb_f->set_number(f->number(), &status);
upb_f->set_name(f->name(), &status);
upb_f->set_label(upb::FieldDef::ConvertLabel(f->label()));
upb_f->set_descriptor_type(
weak_prototype ? UPB_DESCRIPTOR_TYPE_MESSAGE
: upb::FieldDef::ConvertDescriptorType(f->type()));
if (weak_prototype) {
upb_f->set_subdef_name(
weak_prototype->GetDescriptor()->full_name(), &status);
} else {
switch (upb_f->type()) {
case UPB_TYPE_INT32:
upb_f->set_default_value(MakeValue(f->default_value_int32()));
break;
case UPB_TYPE_INT64:
upb_f->set_default_value(
MakeValue(static_cast<int64_t>(f->default_value_int64())));
break;
case UPB_TYPE_UINT32:
upb_f->set_default_value(MakeValue(f->default_value_uint32()));
break;
case UPB_TYPE_UINT64:
upb_f->set_default_value(
MakeValue(static_cast<uint64_t>(f->default_value_uint64())));
break;
case UPB_TYPE_DOUBLE:
upb_f->set_default_value(MakeValue(f->default_value_double()));
break;
case UPB_TYPE_FLOAT:
upb_f->set_default_value(MakeValue(f->default_value_float()));
break;
case UPB_TYPE_BOOL:
upb_f->set_default_value(MakeValue(f->default_value_bool()));
break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
upb_f->set_default_string(f->default_value_string(), &status);
break;
case UPB_TYPE_MESSAGE:
upb_f->set_subdef_name(f->message_type()->full_name(), &status);
break;
case UPB_TYPE_ENUM:
// We set the enum default numerically.
upb_f->set_default_value(
MakeValue(static_cast<int32_t>(f->default_value_enum()->number())));
upb_f->set_subdef_name(f->enum_type()->full_name(), &status);
break;
}
}
md->AddField(upb_f, &upb_f, &status);
UPB_ASSERT_STATUS(&status);
if (weak_prototype) {
*subm = weak_prototype;
} else if (f->cpp_type() == goog::FieldDescriptor::CPPTYPE_MESSAGE) {
*subm = upb::google::GetFieldPrototype(m, f);
#ifdef UPB_GOOGLE3
if (!*subm) *subm = upb::google::GetProto1FieldPrototype(m, f);
#endif
assert(*subm);
}
return upb_f;
}
upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, const void* owner) {
upb::EnumDef* e = upb::EnumDef::New(owner);
upb::Status status;
e->set_full_name(desc->full_name(), &status);
for (int i = 0; i < desc->value_count(); i++) {
const goog::EnumValueDescriptor* val = desc->value(i);
bool success = e->AddValue(val->name(), val->number(), &status);
UPB_ASSERT_VAR(success, success);
}
UPB_ASSERT_STATUS(&status);
return e;
}
static upb::MessageDef* NewMessageDef(const goog::Message& m, const void* owner,
me::Defs* defs) {
upb::MessageDef* md = upb::MessageDef::New(owner);
const goog::Descriptor* d = m.GetDescriptor();
upb::Status status;
md->set_full_name(m.GetDescriptor()->full_name(), &status);
// Must do this before processing submessages to prevent infinite recursion.
defs->AddMessage(&m, md);
std::vector<const goog::FieldDescriptor*> fields;
d->file()->pool()->FindAllExtensions(d, &fields);
for (int i = 0; i < d->field_count(); i++) {
fields.push_back(d->field(i));
}
for (int i = 0; i < fields.size(); i++) {
const goog::FieldDescriptor* proto2_f = fields[i];
assert(proto2_f);
#ifdef UPB_GOOGLE3
// Skip lazy fields for now since we can't properly handle them.
if (proto2_f->options().lazy()) continue;
#endif
const goog::Message* subm_prototype;
upb::FieldDef* f = AddFieldDef(m, proto2_f, md, &subm_prototype);
if (!f->HasSubDef()) continue;
upb::Def* subdef = defs->FindSymbol(f->subdef_name());
if (!subdef) {
if (f->type() == UPB_TYPE_ENUM) {
subdef = NewEnumDef(proto2_f->enum_type(), owner)->Upcast();
defs->AddSymbol(subdef->full_name(), subdef);
} else {
assert(f->IsSubMessage());
assert(subm_prototype);
subdef = NewMessageDef(*subm_prototype, owner, defs)->Upcast();
}
}
f->set_subdef(subdef, &status);
}
UPB_ASSERT_STATUS(&status);
return md;
}
const upb::Handlers* NewWriteHandlers(const goog::Message& m,
const void* owner) {
me::Defs defs;
const upb::MessageDef* md = NewMessageDef(m, owner, &defs);
std::vector<upb::Def*> defs_vec;
defs.Flatten(&defs_vec);
Status status;
bool success = Def::Freeze(defs_vec, &status);
UPB_ASSERT_VAR(success, success);
const upb::Handlers* ret = upb::Handlers::NewFrozen(
md, NULL, owner, me::Defs::StaticOnMessage, &defs);
// Unref all defs, since they're now ref'd by the handlers.
for (int i = 0; i < static_cast<int>(defs_vec.size()); i++) {
defs_vec[i]->Unref(owner);
}
return ret;
}
} // namespace google
} // namespace upb