summaryrefslogtreecommitdiff
path: root/protobuf/demo/cpp/StreamProtobuf.h
blob: ff2bfd665a9b982e0341ca3c3b44071726822b2e (plain)
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
// **********************************************************************
//
// Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
//
// This copy of Ice Protobuf is licensed to you under the terms
// described in the ICE_PROTOBUF_LICENSE file included in this
// distribution.
//
// **********************************************************************

#ifndef STREAM_PROTOBUF_H
#define STREAM_PROTOBUF_H

#include <Ice/Ice.h>
#include <google/protobuf/message_lite.h>

#ifdef ICE_CPP11
#include <type_traits>
#endif

//
// Tell Ice how to marshal and unmarshal a protobuf message to/from a sequence<byte>
//
namespace Ice
{

#ifdef ICE_CPP11
//
// We'll use std::enable_if to give protobuf its own helper category (see below)
//
const StreamHelperCategory StreamHelperCategoryProtobuf = 100;
#else
//
// We just assume a single "custom" category: Unknown
//
const StreamHelperCategory StreamHelperCategoryProtobuf = StreamHelperCategoryUnknown;
#endif

#ifdef ICE_CPP11

template<typename T>
struct StreamableTraits<T, typename std::enable_if<std::is_base_of< ::google::protobuf::MessageLite, T>::value >::type>
{
    static const StreamHelperCategory helper = StreamHelperCategoryProtobuf;
    static const int minWireSize = 1;
    static const bool fixedLength = false;
};

#else
//
// We use the default 'Unknown' StreamHelperCategory
//
#endif

template<typename T>
struct StreamHelper<T, StreamHelperCategoryProtobuf>
{
    template<class S> static inline void
    write(S* stream, const ::google::protobuf::MessageLite& v)
    {
        std::vector<Byte> data(v.ByteSize());
        if(!v.IsInitialized())
        {
            throw MarshalException(__FILE__, __LINE__,
                                   "message not fully initialized: " + v.InitializationErrorString());
        }

        Byte* r = v.SerializeWithCachedSizesToArray(&data[0]);
        if(r != &data[0] + data.size())
        {
            throw MarshalException(__FILE__, __LINE__, "message modified during marshaling");
        }

        stream->write(&data[0], &data[0] + data.size());
    }

    template<class S> static inline void
    read(S* stream, ::google::protobuf::MessageLite& v)
    {
        std::pair<const Byte*, const Byte*> data;
        stream->read(data);
        if(!v.ParseFromArray(data.first, static_cast<int>(data.second - data.first)))
        {
            throw MarshalException(__FILE__, __LINE__, "ParseFromArray failed");
        }
    }
};

//
// Use default marshaling/unmarshaling, with optionalFormat = OptionalFormatVSize
//
template<>
struct GetOptionalFormat<StreamHelperCategoryProtobuf, 1, false>
{
    static const OptionalFormat value = OptionalFormatVSize;
};

}
#endif