GRPC C++  1.8.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 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
20 #define GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
21 
22 #include <type_traits>
23 
31 
32 namespace grpc {
33 
34 extern CoreCodegenInterface* g_core_codegen_interface;
35 
36 namespace internal {
37 
38 class GrpcBufferWriterPeer;
39 
40 const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024;
41 
43  public:
44  GrpcBufferWriter(grpc_byte_buffer** bp, int block_size, int total_size)
45  : block_size_(block_size),
46  total_size_(total_size),
47  byte_count_(0),
48  have_backup_(false) {
50  slice_buffer_ = &(*bp)->data.raw.slice_buffer;
51  }
52 
53  ~GrpcBufferWriter() override {
54  if (have_backup_) {
56  }
57  }
58 
59  bool Next(void** data, int* size) override {
60  // Protobuf should not ask for more memory than total_size_.
62  if (have_backup_) {
64  have_backup_ = false;
65  } else {
66  // When less than a whole block is needed, only allocate that much.
67  // But make sure the allocated slice is not inlined.
68  size_t remain = total_size_ - byte_count_ > block_size_
69  ? block_size_
72  remain > GRPC_SLICE_INLINED_SIZE ? remain
74  }
76  // On win x64, int is only 32bit
78  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
80  return true;
81  }
82 
83  void BackUp(int count) override {
85  if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
87  } else {
89  &slice_, GRPC_SLICE_LENGTH(slice_) - count);
91  }
92  // It's dangerous to keep an inlined grpc_slice as the backup slice, since
93  // on a following Next() call, a reference will be returned to this slice
94  // via GRPC_SLICE_START_PTR, which will not be an adddress held by
95  // slice_buffer_.
97  byte_count_ -= count;
98  }
99 
100  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
101 
102  protected:
103  friend class GrpcBufferWriterPeer;
104  const int block_size_;
105  const int total_size_;
106  int64_t byte_count_;
111 };
112 
114  public:
116  : byte_count_(0), backup_count_(0), status_() {
118  buffer)) {
120  "Couldn't initialize byte buffer reader");
121  }
122  }
123  ~GrpcBufferReader() override {
125  }
126 
127  bool Next(const void** data, int* size) override {
128  if (!status_.ok()) {
129  return false;
130  }
131  if (backup_count_ > 0) {
134  GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
135  *size = (int)backup_count_;
136  backup_count_ = 0;
137  return true;
138  }
140  &slice_)) {
141  return false;
142  }
144  *data = GRPC_SLICE_START_PTR(slice_);
145  // On win x64, int is only 32bit
147  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
148  return true;
149  }
150 
151  Status status() const { return status_; }
152 
153  void BackUp(int count) override { backup_count_ = count; }
154 
155  bool Skip(int count) override {
156  const void* data;
157  int size;
158  while (Next(&data, &size)) {
159  if (size >= count) {
160  BackUp(size - count);
161  return true;
162  }
163  // size < count;
164  count -= size;
165  }
166  // error or we have too large count;
167  return false;
168  }
169 
170  grpc::protobuf::int64 ByteCount() const override {
171  return byte_count_ - backup_count_;
172  }
173 
174  protected:
175  int64_t byte_count_;
176  int64_t backup_count_;
180 };
181 
182 // BufferWriter must be a subclass of io::ZeroCopyOutputStream.
183 template <class BufferWriter, class T>
185  grpc_byte_buffer** bp, bool* own_buffer) {
186  static_assert(
187  std::is_base_of<protobuf::io::ZeroCopyOutputStream, BufferWriter>::value,
188  "BufferWriter must be a subclass of io::ZeroCopyOutputStream");
189  *own_buffer = true;
190  int byte_size = msg.ByteSize();
191  if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) {
194  GRPC_SLICE_END_PTR(slice) ==
195  msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice)));
198 
199  return g_core_codegen_interface->ok();
200  }
201  BufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength, byte_size);
202  return msg.SerializeToZeroCopyStream(&writer)
204  : Status(StatusCode::INTERNAL, "Failed to serialize message");
205 }
206 
207 // BufferReader must be a subclass of io::ZeroCopyInputStream.
208 template <class BufferReader, class T>
211  static_assert(
212  std::is_base_of<protobuf::io::ZeroCopyInputStream, BufferReader>::value,
213  "BufferReader must be a subclass of io::ZeroCopyInputStream");
214  if (buffer == nullptr) {
215  return Status(StatusCode::INTERNAL, "No payload");
216  }
217  Status result = g_core_codegen_interface->ok();
218  {
219  BufferReader reader(buffer);
220  if (!reader.status().ok()) {
221  return reader.status();
222  }
224  decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
225  if (!msg->ParseFromCodedStream(&decoder)) {
226  result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
227  }
228  if (!decoder.ConsumedEntireMessage()) {
229  result = Status(StatusCode::INTERNAL, "Did not read entire message");
230  }
231  }
233  return result;
234 }
235 
236 } // namespace internal
237 
238 // this is needed so the following class does not conflict with protobuf
239 // serializers that utilize internal-only tools.
240 #ifdef GRPC_OPEN_SOURCE_PROTO
241 // This class provides a protobuf serializer. It translates between protobuf
242 // objects and grpc_byte_buffers. More information about SerializationTraits can
243 // be found in include/grpc++/impl/codegen/serialization_traits.h.
244 template <class T>
245 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
246  grpc::protobuf::Message, T>::value>::type> {
247  public:
248  static Status Serialize(const grpc::protobuf::Message& msg,
249  grpc_byte_buffer** bp, bool* own_buffer) {
250  return internal::GenericSerialize<internal::GrpcBufferWriter, T>(
251  msg, bp, own_buffer);
252  }
253 
254  static Status Deserialize(grpc_byte_buffer* buffer,
256  return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer,
257  msg);
258  }
259 };
260 #endif
261 
262 } // namespace grpc
263 
264 #endif // GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
Status GenericDeserialize(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg)
Definition: proto_utils.h:209
virtual void grpc_slice_buffer_pop(grpc_slice_buffer *sb)=0
virtual grpc_slice grpc_slice_malloc(size_t length)=0
Definition: proto_utils.h:113
~GrpcBufferWriter() override
Definition: proto_utils.h:53
virtual void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader)=0
Status status_
Definition: proto_utils.h:179
int64_t byte_count_
Definition: proto_utils.h:106
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:170
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:135
const int kGrpcBufferWriterMaxBufferLength
Definition: proto_utils.h:40
Status GenericSerialize(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp, bool *own_buffer)
Definition: proto_utils.h:184
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. ...
Definition: slice.h:81
~GrpcBufferReader() override
Definition: proto_utils.h:123
int64_t byte_count_
Definition: proto_utils.h:175
bool Next(const void **data, int *size) override
Definition: proto_utils.h:127
const int total_size_
Definition: proto_utils.h:105
Definition: grpc_types.h:41
grpc_slice backup_slice_
Definition: proto_utils.h:109
#define GRPC_SLICE_START_PTR(slice)
Definition: slice.h:117
bool Skip(int count) override
Definition: proto_utils.h:155
Represents an expandable array of slices, to be interpreted as a single item.
Definition: slice.h:99
#define GRPC_SLICE_END_PTR(slice)
Definition: slice.h:126
void BackUp(int count) override
Definition: proto_utils.h:153
virtual void grpc_byte_buffer_destroy(grpc_byte_buffer *bb)=0
#define GRPC_SLICE_INLINED_SIZE
Definition: slice.h:69
GrpcBufferWriter(grpc_byte_buffer **bp, int block_size, int total_size)
Definition: proto_utils.h:44
::google::protobuf::io::ZeroCopyInputStream ZeroCopyInputStream
Definition: config_protobuf.h:88
struct grpc_slice_refcount * refcount
Definition: slice.h:82
void BackUp(int count) override
Definition: proto_utils.h:83
grpc_slice slice_
Definition: proto_utils.h:178
const int block_size_
Definition: proto_utils.h:104
CoreCodegenInterface * g_core_codegen_interface
Definition: call.h:46
virtual grpc_byte_buffer * grpc_raw_byte_buffer_create(grpc_slice *slice, size_t nslices)=0
Definition: proto_utils.h:42
bool have_backup_
Definition: proto_utils.h:108
friend class GrpcBufferWriterPeer
Definition: proto_utils.h:103
::google::protobuf::int64 int64
Definition: config_protobuf.h:73
grpc_slice slice_
Definition: proto_utils.h:110
virtual grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split)=0
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:100
virtual void grpc_slice_unref(grpc_slice slice)=0
bool Next(void **data, int *size) override
Definition: proto_utils.h:59
virtual void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice slice)=0
bool ok() const
Is the status OK?
Definition: status.h:64
Did it work? If it didn't, why?
Definition: status.h:30
grpc_slice_buffer * slice_buffer_
Definition: proto_utils.h:107
int64_t backup_count_
Definition: proto_utils.h:176
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:87
#define GRPC_SLICE_LENGTH(slice)
Definition: slice.h:120
GrpcBufferReader(grpc_byte_buffer *buffer)
Definition: proto_utils.h:115
Definition: byte_buffer_reader.h:28
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:119
grpc_byte_buffer_reader reader_
Definition: proto_utils.h:177
Status status() const
Definition: proto_utils.h:151
::google::protobuf::Message Message
Definition: config_protobuf.h:72
::google::protobuf::io::CodedInputStream CodedInputStream
Definition: config_protobuf.h:89