GRPC C++  1.4.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
proto_utils.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015, Google Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #ifndef GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
35 #define GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
36 
37 #include <type_traits>
38 
46 
47 namespace grpc {
48 
49 extern CoreCodegenInterface* g_core_codegen_interface;
50 
51 namespace internal {
52 
53 class GrpcBufferWriterPeer;
54 
55 const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024;
56 
58  public:
59  explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size)
60  : block_size_(block_size), byte_count_(0), have_backup_(false) {
62  slice_buffer_ = &(*bp)->data.raw.slice_buffer;
63  }
64 
65  ~GrpcBufferWriter() override {
66  if (have_backup_) {
68  }
69  }
70 
71  bool Next(void** data, int* size) override {
72  if (have_backup_) {
73  slice_ = backup_slice_;
74  have_backup_ = false;
75  } else {
76  slice_ = g_core_codegen_interface->grpc_slice_malloc(block_size_);
77  }
78  *data = GRPC_SLICE_START_PTR(slice_);
79  // On win x64, int is only 32bit
80  GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
81  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
82  g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
83  return true;
84  }
85 
86  void BackUp(int count) override {
88  if (count == block_size_) {
89  backup_slice_ = slice_;
90  } else {
92  &slice_, GRPC_SLICE_LENGTH(slice_) - count);
93  g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
94  }
95  // It's dangerous to keep an inlined grpc_slice as the backup slice, since
96  // on a following Next() call, a reference will be returned to this slice
97  // via GRPC_SLICE_START_PTR, which will not be an adddress held by
98  // slice_buffer_.
99  have_backup_ = backup_slice_.refcount != NULL;
100  byte_count_ -= count;
101  }
102 
103  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
104 
105  grpc_slice_buffer* SliceBuffer() { return slice_buffer_; }
106 
107  private:
108  friend class GrpcBufferWriterPeer;
109  const int block_size_;
110  int64_t byte_count_;
111  grpc_slice_buffer* slice_buffer_;
112  bool have_backup_;
113  grpc_slice backup_slice_;
114  grpc_slice slice_;
115 };
116 
118  public:
120  : byte_count_(0), backup_count_(0), status_() {
122  buffer)) {
124  "Couldn't initialize byte buffer reader");
125  }
126  }
127  ~GrpcBufferReader() override {
129  }
130 
131  bool Next(const void** data, int* size) override {
132  if (!status_.ok()) {
133  return false;
134  }
135  if (backup_count_ > 0) {
138  GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
139  *size = (int)backup_count_;
140  backup_count_ = 0;
141  return true;
142  }
144  &slice_)) {
145  return false;
146  }
148  *data = GRPC_SLICE_START_PTR(slice_);
149  // On win x64, int is only 32bit
151  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
152  return true;
153  }
154 
155  Status status() const { return status_; }
156 
157  void BackUp(int count) override { backup_count_ = count; }
158 
159  bool Skip(int count) override {
160  const void* data;
161  int size;
162  while (Next(&data, &size)) {
163  if (size >= count) {
164  BackUp(size - count);
165  return true;
166  }
167  // size < count;
168  count -= size;
169  }
170  // error or we have too large count;
171  return false;
172  }
173 
174  grpc::protobuf::int64 ByteCount() const override {
175  return byte_count_ - backup_count_;
176  }
177 
178  protected:
179  int64_t byte_count_;
180  int64_t backup_count_;
184 };
185 
186 template <class BufferWriter, class T>
188  grpc_byte_buffer** bp, bool* own_buffer) {
189  static_assert(
190  std::is_base_of<protobuf::io::ZeroCopyOutputStream, BufferWriter>::value,
191  "BufferWriter must be a subclass of io::ZeroCopyOutputStream");
192  *own_buffer = true;
193  int byte_size = msg.ByteSize();
197  GRPC_SLICE_END_PTR(slice) ==
198  msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice)));
201  return g_core_codegen_interface->ok();
202  } else {
203  BufferWriter writer(bp, internal::kGrpcBufferWriterMaxBufferLength);
204  return msg.SerializeToZeroCopyStream(&writer)
206  : Status(StatusCode::INTERNAL, "Failed to serialize message");
207  }
208 }
209 
210 template <class BufferReader, class T>
213  static_assert(
214  std::is_base_of<protobuf::io::ZeroCopyInputStream, BufferReader>::value,
215  "BufferReader must be a subclass of io::ZeroCopyInputStream");
216  if (buffer == nullptr) {
217  return Status(StatusCode::INTERNAL, "No payload");
218  }
219  Status result = g_core_codegen_interface->ok();
220  {
221  BufferReader reader(buffer);
222  if (!reader.status().ok()) {
223  return reader.status();
224  }
226  decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
227  if (!msg->ParseFromCodedStream(&decoder)) {
228  result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
229  }
230  if (!decoder.ConsumedEntireMessage()) {
231  result = Status(StatusCode::INTERNAL, "Did not read entire message");
232  }
233  }
235  return result;
236 }
237 
238 } // namespace internal
239 
240 // this is needed so the following class does not conflict with protobuf
241 // serializers that utilize internal-only tools.
242 #ifdef GRPC_OPEN_SOURCE_PROTO
243 // This class provides a protobuf serializer. It translates between protobuf
244 // objects and grpc_byte_buffers. More information about SerializationTraits can
245 // be found in include/grpc++/impl/codegen/serialization_traits.h.
246 template <class T>
247 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
248  grpc::protobuf::Message, T>::value>::type> {
249  public:
250  static Status Serialize(const grpc::protobuf::Message& msg,
251  grpc_byte_buffer** bp, bool* own_buffer) {
252  return internal::GenericSerialize<internal::GrpcBufferWriter, T>(
253  msg, bp, own_buffer);
254  }
255 
256  static Status Deserialize(grpc_byte_buffer* buffer,
258  return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer,
259  msg);
260  }
261 };
262 #endif
263 
264 } // namespace grpc
265 
266 #endif // GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
Status GenericDeserialize(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg)
Definition: proto_utils.h:211
virtual void grpc_slice_buffer_pop(grpc_slice_buffer *sb)=0
virtual grpc_slice grpc_slice_malloc(size_t length)=0
grpc_slice_buffer * SliceBuffer()
Definition: proto_utils.h:105
Definition: proto_utils.h:117
~GrpcBufferWriter() override
Definition: proto_utils.h:65
virtual void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader)=0
Status status_
Definition: proto_utils.h:183
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:174
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:137
const int kGrpcBufferWriterMaxBufferLength
Definition: proto_utils.h:55
Status GenericSerialize(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp, bool *own_buffer)
Definition: proto_utils.h:187
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. ...
Definition: slice.h:91
~GrpcBufferReader() override
Definition: proto_utils.h:127
int64_t byte_count_
Definition: proto_utils.h:179
bool Next(const void **data, int *size) override
Definition: proto_utils.h:131
Definition: grpc_types.h:56
#define GRPC_SLICE_START_PTR(slice)
Definition: slice.h:127
bool Skip(int count) override
Definition: proto_utils.h:159
Represents an expandable array of slices, to be interpreted as a single item.
Definition: slice.h:109
#define GRPC_SLICE_END_PTR(slice)
Definition: slice.h:136
void BackUp(int count) override
Definition: proto_utils.h:157
virtual void grpc_byte_buffer_destroy(grpc_byte_buffer *bb)=0
::google::protobuf::io::ZeroCopyInputStream ZeroCopyInputStream
Definition: config_protobuf.h:103
struct grpc_slice_refcount * refcount
Definition: slice.h:92
void BackUp(int count) override
Definition: proto_utils.h:86
grpc_slice slice_
Definition: proto_utils.h:182
CoreCodegenInterface * g_core_codegen_interface
Definition: call.h:64
virtual grpc_byte_buffer * grpc_raw_byte_buffer_create(grpc_slice *slice, size_t nslices)=0
GrpcBufferWriter(grpc_byte_buffer **bp, int block_size)
Definition: proto_utils.h:59
Definition: proto_utils.h:57
friend class GrpcBufferWriterPeer
Definition: proto_utils.h:108
::google::protobuf::int64 int64
Definition: config_protobuf.h:88
virtual grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split)=0
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:103
virtual void grpc_slice_unref(grpc_slice slice)=0
bool Next(void **data, int *size) override
Definition: proto_utils.h:71
virtual void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice slice)=0
bool ok() const
Is the status OK?
Definition: status.h:76
Did it work? If it didn't, why?
Definition: status.h:45
int64_t backup_count_
Definition: proto_utils.h:180
virtual const Status & ok()=0
virtual int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, grpc_slice *slice)=0
::google::protobuf::io::ZeroCopyOutputStream ZeroCopyOutputStream
Definition: config_protobuf.h:102
#define GRPC_SLICE_LENGTH(slice)
Definition: slice.h:130
GrpcBufferReader(grpc_byte_buffer *buffer)
Definition: proto_utils.h:119
Definition: byte_buffer_reader.h:43
virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer) GRPC_MUST_USE_RESULT=0
Internal errors.
Definition: status_code_enum.h:134
grpc_byte_buffer_reader reader_
Definition: proto_utils.h:181
Status status() const
Definition: proto_utils.h:155
::google::protobuf::Message Message
Definition: config_protobuf.h:87
::google::protobuf::io::CodedInputStream CodedInputStream
Definition: config_protobuf.h:104