1/*
2 *
3 * Copyright 2017 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 GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
20#define GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
21
22#include <grpc/impl/codegen/byte_buffer.h>
23
24#include <grpcpp/impl/codegen/config.h>
25#include <grpcpp/impl/codegen/core_codegen_interface.h>
26#include <grpcpp/impl/codegen/serialization_traits.h>
27#include <grpcpp/impl/codegen/slice.h>
28#include <grpcpp/impl/codegen/status.h>
29
30#include <vector>
31
32namespace grpc_impl {
33namespace internal {
34
35template <class RequestType, class ResponseType>
36class CallbackUnaryHandler;
37template <class RequestType, class ResponseType>
38class CallbackServerStreamingHandler;
39template <class ServiceType, class RequestType, class ResponseType>
40class RpcMethodHandler;
41template <class ServiceType, class RequestType, class ResponseType>
42class ServerStreamingHandler;
43template <::grpc::StatusCode code>
44class ErrorMethodHandler;
45
46} // namespace internal
47} // namespace grpc_impl
48
49namespace grpc {
50
51class ServerInterface;
52class ByteBuffer;
53class ServerInterface;
54
55namespace internal {
56class CallOpSendMessage;
57template <class R>
58class CallOpRecvMessage;
59class CallOpGenericRecvMessage;
60class ExternalConnectionAcceptorImpl;
61template <class R>
62class DeserializeFuncType;
63class GrpcByteBufferPeer;
64
65} // namespace internal
66/// A sequence of bytes.
67class ByteBuffer final {
68 public:
69 /// Constuct an empty buffer.
70 ByteBuffer() : buffer_(nullptr) {}
71
72 /// Construct buffer from \a slices, of which there are \a nslices.
73 ByteBuffer(const Slice* slices, size_t nslices) {
74 // The following assertions check that the representation of a grpc::Slice
75 // is identical to that of a grpc_slice: it has a grpc_slice field, and
76 // nothing else.
77 static_assert(std::is_same<decltype(slices[0].slice_), grpc_slice>::value,
78 "Slice must have same representation as grpc_slice");
79 static_assert(sizeof(Slice) == sizeof(grpc_slice),
80 "Slice must have same representation as grpc_slice");
81 // The following assertions check that the representation of a ByteBuffer is
82 // identical to grpc_byte_buffer*: it has a grpc_byte_buffer* field,
83 // and nothing else.
84 static_assert(std::is_same<decltype(buffer_), grpc_byte_buffer*>::value,
85 "ByteBuffer must have same representation as "
86 "grpc_byte_buffer*");
87 static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*),
88 "ByteBuffer must have same representation as "
89 "grpc_byte_buffer*");
90 // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
91 // than its advertised side effect of increasing the reference count of the
92 // slices it processes, and such an increase does not affect the semantics
93 // seen by the caller of this constructor.
94 buffer_ = g_core_codegen_interface->grpc_raw_byte_buffer_create(
95 slice: reinterpret_cast<grpc_slice*>(const_cast<Slice*>(slices)), nslices);
96 }
97
98 /// Constuct a byte buffer by referencing elements of existing buffer
99 /// \a buf. Wrapper of core function grpc_byte_buffer_copy . This is not
100 /// a deep copy; it is just a referencing. As a result, its performance is
101 /// size-independent.
102 ByteBuffer(const ByteBuffer& buf) : buffer_(nullptr) { operator=(buf); }
103
104 ~ByteBuffer() {
105 if (buffer_) {
106 g_core_codegen_interface->grpc_byte_buffer_destroy(bb: buffer_);
107 }
108 }
109
110 /// Wrapper of core function grpc_byte_buffer_copy . This is not
111 /// a deep copy; it is just a referencing. As a result, its performance is
112 /// size-independent.
113 ByteBuffer& operator=(const ByteBuffer& buf) {
114 if (this != &buf) {
115 Clear(); // first remove existing data
116 }
117 if (buf.buffer_) {
118 // then copy
119 buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(bb: buf.buffer_);
120 }
121 return *this;
122 }
123
124 /// Dump (read) the buffer contents into \a slices.
125 Status Dump(std::vector<Slice>* slices) const;
126
127 /// Remove all data.
128 void Clear() {
129 if (buffer_) {
130 g_core_codegen_interface->grpc_byte_buffer_destroy(bb: buffer_);
131 buffer_ = nullptr;
132 }
133 }
134
135 /// Make a duplicate copy of the internals of this byte
136 /// buffer so that we have our own owned version of it.
137 /// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable.
138 /// This is not a deep copy; it is a referencing and its performance
139 /// is size-independent.
140 void Duplicate() {
141 buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(bb: buffer_);
142 }
143
144 /// Forget underlying byte buffer without destroying
145 /// Use this only for un-owned byte buffers
146 void Release() { buffer_ = nullptr; }
147
148 /// Buffer size in bytes.
149 size_t Length() const {
150 return buffer_ == nullptr
151 ? 0
152 : g_core_codegen_interface->grpc_byte_buffer_length(bb: buffer_);
153 }
154
155 /// Swap the state of *this and *other.
156 void Swap(ByteBuffer* other) {
157 grpc_byte_buffer* tmp = other->buffer_;
158 other->buffer_ = buffer_;
159 buffer_ = tmp;
160 }
161
162 /// Is this ByteBuffer valid?
163 bool Valid() const { return (buffer_ != nullptr); }
164
165 private:
166 friend class SerializationTraits<ByteBuffer, void>;
167 friend class ServerInterface;
168 friend class internal::CallOpSendMessage;
169 template <class R>
170 friend class internal::CallOpRecvMessage;
171 friend class internal::CallOpGenericRecvMessage;
172 template <class ServiceType, class RequestType, class ResponseType>
173 friend class ::grpc_impl::internal::RpcMethodHandler;
174 template <class ServiceType, class RequestType, class ResponseType>
175 friend class ::grpc_impl::internal::ServerStreamingHandler;
176 template <class RequestType, class ResponseType>
177 friend class ::grpc_impl::internal::CallbackUnaryHandler;
178 template <class RequestType, class ResponseType>
179 friend class ::grpc_impl::internal::CallbackServerStreamingHandler;
180 template <StatusCode code>
181 friend class ::grpc_impl::internal::ErrorMethodHandler;
182 template <class R>
183 friend class internal::DeserializeFuncType;
184 friend class ProtoBufferReader;
185 friend class ProtoBufferWriter;
186 friend class internal::GrpcByteBufferPeer;
187 friend class internal::ExternalConnectionAcceptorImpl;
188
189 grpc_byte_buffer* buffer_;
190
191 // takes ownership
192 void set_buffer(grpc_byte_buffer* buf) {
193 if (buffer_) {
194 Clear();
195 }
196 buffer_ = buf;
197 }
198
199 grpc_byte_buffer* c_buffer() { return buffer_; }
200 grpc_byte_buffer** c_buffer_ptr() { return &buffer_; }
201
202 class ByteBufferPointer {
203 public:
204 ByteBufferPointer(const ByteBuffer* b)
205 : bbuf_(const_cast<ByteBuffer*>(b)) {}
206 operator ByteBuffer*() { return bbuf_; }
207 operator grpc_byte_buffer*() { return bbuf_->buffer_; }
208 operator grpc_byte_buffer**() { return &bbuf_->buffer_; }
209
210 private:
211 ByteBuffer* bbuf_;
212 };
213 ByteBufferPointer bbuf_ptr() const { return ByteBufferPointer(this); }
214};
215
216template <>
217class SerializationTraits<ByteBuffer, void> {
218 public:
219 static Status Deserialize(ByteBuffer* byte_buffer, ByteBuffer* dest) {
220 dest->set_buffer(byte_buffer->buffer_);
221 return Status::OK;
222 }
223 static Status Serialize(const ByteBuffer& source, ByteBuffer* buffer,
224 bool* own_buffer) {
225 *buffer = source;
226 *own_buffer = true;
227 return g_core_codegen_interface->ok();
228 }
229};
230
231} // namespace grpc
232
233#endif // GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
234

source code of include/grpcpp/impl/codegen/byte_buffer.h