GRPC C++  1.6.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 
42 class GrpcBufferWriter final
44  public:
45  explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size)
46  : block_size_(block_size), byte_count_(0), have_backup_(false) {
48  slice_buffer_ = &(*bp)->data.raw.slice_buffer;
49  }
50 
51  ~GrpcBufferWriter() override {
52  if (have_backup_) {
54  }
55  }
56 
57  bool Next(void** data, int* size) override {
58  if (have_backup_) {
59  slice_ = backup_slice_;
60  have_backup_ = false;
61  } else {
62  slice_ = g_core_codegen_interface->grpc_slice_malloc(block_size_);
63  }
64  *data = GRPC_SLICE_START_PTR(slice_);
65  // On win x64, int is only 32bit
66  GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
67  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
68  g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
69  return true;
70  }
71 
72  void BackUp(int count) override {
74  if (count == block_size_) {
75  backup_slice_ = slice_;
76  } else {
78  &slice_, GRPC_SLICE_LENGTH(slice_) - count);
79  g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
80  }
81  // It's dangerous to keep an inlined grpc_slice as the backup slice, since
82  // on a following Next() call, a reference will be returned to this slice
83  // via GRPC_SLICE_START_PTR, which will not be an adddress held by
84  // slice_buffer_.
85  have_backup_ = backup_slice_.refcount != NULL;
86  byte_count_ -= count;
87  }
88 
89  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
90 
91  private:
92  friend class GrpcBufferWriterPeer;
93  const int block_size_;
94  int64_t byte_count_;
95  grpc_slice_buffer* slice_buffer_;
96  bool have_backup_;
97  grpc_slice backup_slice_;
98  grpc_slice slice_;
99 };
100 
101 class GrpcBufferReader final
103  public:
105  : byte_count_(0), backup_count_(0), status_() {
107  buffer)) {
108  status_ = Status(StatusCode::INTERNAL,
109  "Couldn't initialize byte buffer reader");
110  }
111  }
112  ~GrpcBufferReader() override {
114  }
115 
116  bool Next(const void** data, int* size) override {
117  if (!status_.ok()) {
118  return false;
119  }
120  if (backup_count_ > 0) {
121  *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) -
122  backup_count_;
123  GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
124  *size = (int)backup_count_;
125  backup_count_ = 0;
126  return true;
127  }
129  &slice_)) {
130  return false;
131  }
133  *data = GRPC_SLICE_START_PTR(slice_);
134  // On win x64, int is only 32bit
135  GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
136  byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
137  return true;
138  }
139 
140  Status status() const { return status_; }
141 
142  void BackUp(int count) override { backup_count_ = count; }
143 
144  bool Skip(int count) override {
145  const void* data;
146  int size;
147  while (Next(&data, &size)) {
148  if (size >= count) {
149  BackUp(size - count);
150  return true;
151  }
152  // size < count;
153  count -= size;
154  }
155  // error or we have too large count;
156  return false;
157  }
158 
159  grpc::protobuf::int64 ByteCount() const override {
160  return byte_count_ - backup_count_;
161  }
162 
163  private:
164  int64_t byte_count_;
165  int64_t backup_count_;
166  grpc_byte_buffer_reader reader_;
167  grpc_slice slice_;
168  Status status_;
169 };
170 
171 } // namespace internal
172 
173 template <class T>
174 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
175  grpc::protobuf::Message, T>::value>::type> {
176  public:
178  grpc_byte_buffer** bp, bool* own_buffer) {
179  *own_buffer = true;
180  int byte_size = msg.ByteSize();
184  GRPC_SLICE_END_PTR(slice) ==
185  msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice)));
188  return g_core_codegen_interface->ok();
189  } else {
192  return msg.SerializeToZeroCopyStream(&writer)
194  : Status(StatusCode::INTERNAL, "Failed to serialize message");
195  }
196  }
197 
200  if (buffer == nullptr) {
201  return Status(StatusCode::INTERNAL, "No payload");
202  }
203  Status result = g_core_codegen_interface->ok();
204  {
205  internal::GrpcBufferReader reader(buffer);
206  if (!reader.status().ok()) {
207  return reader.status();
208  }
210  decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
211  if (!msg->ParseFromCodedStream(&decoder)) {
212  result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
213  }
214  if (!decoder.ConsumedEntireMessage()) {
215  result = Status(StatusCode::INTERNAL, "Did not read entire message");
216  }
217  }
219  return result;
220  }
221 };
222 
223 } // namespace grpc
224 
225 #endif // GRPCXX_IMPL_CODEGEN_PROTO_UTILS_H
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:101
~GrpcBufferWriter() override
Definition: proto_utils.h:51
virtual void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader)=0
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:159
#define GPR_CODEGEN_ASSERT(x)
Codegen specific version of GPR_ASSERT.
Definition: core_codegen_interface.h:126
const int kGrpcBufferWriterMaxBufferLength
Definition: proto_utils.h:40
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. ...
Definition: slice.h:76
~GrpcBufferReader() override
Definition: proto_utils.h:112
bool Next(const void **data, int *size) override
Definition: proto_utils.h:116
Definition: grpc_types.h:41
#define GRPC_SLICE_START_PTR(slice)
Definition: slice.h:112
bool Skip(int count) override
Definition: proto_utils.h:144
Represents an expandable array of slices, to be interpreted as a single item.
Definition: slice.h:94
#define GRPC_SLICE_END_PTR(slice)
Definition: slice.h:121
void BackUp(int count) override
Definition: proto_utils.h:142
static Status Deserialize(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg)
Definition: proto_utils.h:198
virtual void grpc_byte_buffer_destroy(grpc_byte_buffer *bb)=0
Defines how to serialize and deserialize some type.
Definition: serialization_traits.h:49
::google::protobuf::io::ZeroCopyInputStream ZeroCopyInputStream
Definition: config_protobuf.h:86
static Status Serialize(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp, bool *own_buffer)
Definition: proto_utils.h:177
struct grpc_slice_refcount * refcount
Definition: slice.h:77
void BackUp(int count) override
Definition: proto_utils.h:72
CoreCodegenInterface * g_core_codegen_interface
Definition: call.h:49
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:45
Definition: proto_utils.h:42
friend class GrpcBufferWriterPeer
Definition: proto_utils.h:92
::google::protobuf::int64 int64
Definition: config_protobuf.h:71
virtual grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split)=0
grpc::protobuf::int64 ByteCount() const override
Definition: proto_utils.h:89
virtual void grpc_slice_unref(grpc_slice slice)=0
bool Next(void **data, int *size) override
Definition: proto_utils.h:57
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
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:85
#define GRPC_SLICE_LENGTH(slice)
Definition: slice.h:115
GrpcBufferReader(grpc_byte_buffer *buffer)
Definition: proto_utils.h:104
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
Status status() const
Definition: proto_utils.h:140
::google::protobuf::Message Message
Definition: config_protobuf.h:70
::google::protobuf::io::CodedInputStream CodedInputStream
Definition: config_protobuf.h:87