diff options
Diffstat (limited to 'bindings/cpp/upb/proto2_bridge.hpp')
-rw-r--r-- | bindings/cpp/upb/proto2_bridge.hpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/bindings/cpp/upb/proto2_bridge.hpp b/bindings/cpp/upb/proto2_bridge.hpp new file mode 100644 index 0000000..ace08ce --- /dev/null +++ b/bindings/cpp/upb/proto2_bridge.hpp @@ -0,0 +1,170 @@ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011-2012 Google Inc. See LICENSE for details. +// Author: Josh Haberman <jhaberman@gmail.com> +// +// A bridge between upb and proto2, allows populating proto2 generated +// classes using upb's parser, translating between descriptors and defs, etc. +// +// This is designed to be able to be compiled against either the open-source +// version of protocol buffers or the Google-internal proto2. The two are +// the same in most ways, but live in different namespaces (proto2 vs +// google::protobuf) and have a few other more minor differences. +// +// The bridge gives you a lot of control over which fields will be written to +// the message (fields that are not written will just be skipped), and whether +// unknown fields are written to the UnknownFieldSet. This can save a lot of +// work if the client only cares about some subset of the fields. +// +// Example usage: +// +// // Build a def that will have all fields and parse just like proto2 would. +// const upb::MessageDef* md = upb::proto2_bridge::NewMessageDef(&MyProto()); +// +// // JIT the parser; should only be done once ahead-of-time. +// upb::Handlers* handlers = upb::NewHandlersForMessage(md); +// upb::DecoderPlan* plan = upb::DecoderPlan::New(handlers); +// handlers->Unref(); +// +// // The actual parsing. +// MyProto proto; +// upb::Decoder decoder; +// upb::StringSource source(buf, len); +// decoder.ResetPlan(plan, 0); +// decoder.ResetInput(source.AllBytes(), &proto); +// CHECK(decoder.Decode() == UPB_OK) << decoder.status(); +// +// To parse only one field and skip all others: +// +// const upb::MessageDef* md = +// upb::proto2_bridge::NewEmptyMessageDef(MyProto().GetPrototype()); +// upb::proto2_bridge::AddFieldDef( +// MyProto::descriptor()->FindFieldByName("my_field"), md); +// upb::Finalize(md); +// +// // Now continue with "JIT the parser" from above. +// +// Note that there is currently no support for +// CodedInputStream::SetExtensionRegistry(), which allows specifying a separate +// DescriptorPool and MessageFactory for extensions. Since this is a property +// of the input in proto2, it's difficult to build a plan ahead-of-time that +// can properly support this. If it's an important use case, the caller should +// probably build a upb plan explicitly. + +#ifndef UPB_PROTO2_BRIDGE +#define UPB_PROTO2_BRIDGE + +#include <vector> + +namespace google { +namespace protobuf { +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; +class FileDescriptor; +class Message; +} // namespace google +} // namespace protobuf + +namespace proto2 { +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; +class FileDescriptor; +class Message; +} // namespace proto2 + + +namespace upb { + +class Def; +class FieldDef; +class MessageDef; + +namespace proto2_bridge { + +// Unfinalized defs //////////////////////////////////////////////////////////// + +// Creating of UNFINALIZED defs. All of these functions return defs that are +// still mutable and have not been finalized. They must be finalized before +// using them to parse anything. This is useful if you want more control over +// the process of constructing defs, eg. to add the specific set of fields you +// care about. + +// Creates a new upb::MessageDef that corresponds to the type in the given +// prototype message. The MessageDef will not have any fields added to it. +upb::MessageDef *NewEmptyMessageDef(const proto2::Message& m, void *owner); +upb::MessageDef *NewEmptyMessageDef(const google::protobuf::Message& desc, + void *owner); + +// Adds a new upb::FieldDef to the given MessageDef corresponding to the given +// FieldDescriptor. The FieldDef will be given an accessor and offset so that +// it can be used to read and write data into the proto2::Message classes. +// The given MessageDef must have been constructed with NewEmptyDefForMessage() +// and f->containing_type() must correspond to the message that was used. +// +// Any submessage, group, or enum fields will be given symbolic references to +// the subtype, which must be resolved before the MessageDef can be finalized. +// +// On success, returns the FieldDef that was added (caller does not own a ref). +// If an existing field had the same name or number, returns NULL. +upb::FieldDef* AddFieldDef(const proto2::FieldDescriptor* f, + upb::MessageDef* md); +upb::FieldDef* AddFieldDef(const google::protobuf::FieldDescriptor* f, + upb::MessageDef* md); + +// Given a MessageDef that was constructed with NewEmptyDefForMessage(), adds +// FieldDefs for all fields defined in the original message, but not for any +// extensions or unknown fields. The given MessageDef must not have any fields +// that have the same name or number as any of the fields we are adding (the +// easiest way to guarantee this is to start with an empty MessageDef). +// +// Returns true on success or false if any of the fields could not be added. +void AddAllFields(upb::MessageDef* md); + +// TODO(haberman): Add: +// // Adds a handler that will store unknown fields in the UnknownFieldSet. +// void AddUnknownFieldHandler(upb::MessageDef* md); + +// Returns a new upb::MessageDef that contains handlers for all fields, unknown +// fields, and any extensions in the descriptor's pool. The resulting +// def/handlers should be equivalent to the generated code constructed by the +// protobuf compiler (or the code in DynamicMessage) for the given type. +// The subdefs for message/enum fields (if any) will be referenced symbolically, +// and will need to be resolved before being finalized. +// +// TODO(haberman): Add missing support (LazyField, MessageSet, and extensions). +// +// TODO(haberman): possibly add a similar function that lets you supply a +// separate DescriptorPool and MessageFactory for extensions, to support +// proto2's io::CodedInputStream::SetExtensionRegistry(). +upb::MessageDef* NewFullMessageDef(const proto2::Message& m, void *owner); +upb::MessageDef* NewFullMessageDef(const google::protobuf::Message& m, + void *owner); + +// Returns a new upb::EnumDef that corresponds to the given EnumDescriptor. +// Caller owns a ref on the returned EnumDef. +upb::EnumDef* NewEnumDef(const proto2::EnumDescriptor* desc, void *owner); +upb::EnumDef* NewEnumDef(const google::protobuf::EnumDescriptor* desc, + void *owner); + +// Finalized defs ////////////////////////////////////////////////////////////// + +// These functions return FINALIZED defs, meaning that they are immutable and +// ready for use. Since they are immutable you cannot make any further changes +// to eg. the set of fields, but these functions are more convenient if you +// simply want to parse a message exactly how the built-in proto2 parser would. + +// Creates a returns a finalized MessageDef for the give message and its entire +// type tree that will include all fields and unknown handlers (ie. it will +// parse just like proto2 would). +const upb::MessageDef* NewFinalMessageDef(const proto2::Message& m, + void *owner); +const upb::MessageDef* NewFinalMessageDef(const google::protobuf::Message& m, + void *owner); + +} // namespace proto2_bridge +} // namespace upb + +#endif |