mcpack2pb.h 5.61 KB
Newer Older
gejun's avatar
gejun committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
// mcpack2pb - Make protobuf be front-end of mcpack/compack
// Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved

// Author: The baidu-rpc authors (pbrpc@baidu.com)
// Date: Mon Oct 19 17:17:36 CST 2015

#ifndef PUBLIC_MCPACK2PB_MCPACK_MCPACK2PB_H
#define PUBLIC_MCPACK2PB_MCPACK_MCPACK2PB_H

#include <google/protobuf/message.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include "base/containers/flat_map.h"
#include "base/iobuf.h"
#include "mcpack2pb/parser.h"
#include "mcpack2pb/serializer.h"

namespace mcpack2pb {

typedef bool (*SetFieldFn)(::google::protobuf::Message* msg,
                           UnparsedValue& value);

// Mapping from filed name to its parsing&setting function.
typedef base::FlatMap<base::StringPiece, SetFieldFn> FieldMap;

enum SerializationFormat {
    FORMAT_COMPACK,
    FORMAT_MCPACK_V2
};

struct MessageHandler {
    // Parse `msg' from `input' as a mcpack_v2 or compack object.
    // Returns number of bytes consumed.
    size_t (*parse)(::google::protobuf::Message* msg,
                    ::google::protobuf::io::ZeroCopyInputStream* input);

    // Parse `msg' from `input' as a mcpack_v2 or compack object removed with header.
    // Returns true on success.
    bool (*parse_body)(::google::protobuf::Message* msg,
                       ::google::protobuf::io::ZeroCopyInputStream* input,
                       size_t size);
    
    // Serialize `msg' as a mcpack_v2 or compack object into `output'.
    // The serialization format is decided by `format'.
    // Returns true on success.
    bool (*serialize)(const ::google::protobuf::Message& msg,
                      ::google::protobuf::io::ZeroCopyOutputStream* output,
                      SerializationFormat format);

    // Serialize `msg' as a mcpack_v2 or compack object without header into
    // `serializer'. The serialization format is decided by `format'.
    // Returns true on success.
    void (*serialize_body)(const ::google::protobuf::Message& msg,
                           Serializer& serializer,
                           SerializationFormat format);

    // -------------------
    //  Helper functions
    // -------------------

    // Parse `msg' from IOBuf or array which may contain more data than just
    // the message.
    // Returns bytes parsed, 0 on error.
    size_t parse_from_iobuf_prefix(::google::protobuf::Message* msg,
                                   const ::base::IOBuf& buf);
    size_t parse_from_array_prefix(::google::protobuf::Message* msg,
                                   const void* data, int size);
    // Parse `msg' from IOBuf or array which may just contain the message.
    // Returns true on success.
    bool parse_from_iobuf(::google::protobuf::Message* msg,
                          const ::base::IOBuf& buf);
    bool parse_from_array(::google::protobuf::Message* msg,
                          const void* data, int size);
    // Serialize `msg' to IOBuf or string.
    // Returns true on success.
    bool serialize_to_iobuf(const ::google::protobuf::Message& msg,
                            ::base::IOBuf* buf, SerializationFormat format);

    // TODO(gejun): serialize_to_string is not supported because OutputStream
    // requires the embedded zero-copy stream to return permanent memory blocks
    // to support reserve() however the string inside StringOutputStream may
    // be resized and invalidates previous returned memory blocks.
};

static const MessageHandler INVALID_MESSAGE_HANDLER = {NULL, NULL, NULL, NULL};

// if the *.pb.cc and *.pb.h was generated by mcpack2pb. This function will be
// called with the mcpack/compack parser and serializer BEFORE main().
void register_message_handler_or_die(const std::string& full_name,
                                     const MessageHandler& handler);

// Find the registered parser/serializer by `full_name'
// e.g. "example.SampleMessage".
// If the handler was not registered, function pointers inside are NULL.
MessageHandler find_message_handler(const std::string& full_name);

// inline impl.
inline size_t MessageHandler::parse_from_iobuf_prefix(
    ::google::protobuf::Message* msg, const ::base::IOBuf& buf) {
    if (parse == NULL) {
        LOG(ERROR) << "`parse' is NULL";
        return 0;
    }
    ::base::IOBufAsZeroCopyInputStream zc_stream(buf);
    return parse(msg, &zc_stream);
}

inline bool MessageHandler::parse_from_iobuf(
    ::google::protobuf::Message* msg, const ::base::IOBuf& buf) {
    if (parse == NULL) {
        LOG(ERROR) << "`parse' is NULL";
        return 0;
    }
    ::base::IOBufAsZeroCopyInputStream zc_stream(buf);
    return parse(msg, &zc_stream) == buf.size();
}

inline size_t MessageHandler::parse_from_array_prefix(
    ::google::protobuf::Message* msg, const void* data, int size) {
    if (parse == NULL) {
        LOG(ERROR) << "`parse' is NULL";
        return 0;
    }
    ::google::protobuf::io::ArrayInputStream zc_stream(data, size);
    return parse(msg, &zc_stream);
}

inline bool MessageHandler::parse_from_array(
    ::google::protobuf::Message* msg, const void* data, int size) {
    if (parse == NULL) {
        LOG(ERROR) << "`parse' is NULL";
        return 0;
    }
    ::google::protobuf::io::ArrayInputStream zc_stream(data, size);
    return (int)parse(msg, &zc_stream) == size;
}

inline bool MessageHandler::serialize_to_iobuf(
    const ::google::protobuf::Message& msg,
    ::base::IOBuf* buf, SerializationFormat format) {
    if (serialize == NULL) {
        LOG(ERROR) << "`serialize' is NULL";
        return false;
    }
    ::base::IOBufAsZeroCopyOutputStream zc_stream(buf);
    return serialize(msg, &zc_stream, format);
}

} // namespace mcpack2pb

#endif // PUBLIC_MCPACK2PB_MCPACK_MCPACK2PB_H