1 // Copyright 2022 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_EVENT_ENGINE_SLICE_BUFFER_H 16 #define GRPC_EVENT_ENGINE_SLICE_BUFFER_H 17 18 #include <grpc/event_engine/internal/slice_cast.h> 19 #include <grpc/event_engine/slice.h> 20 #include <grpc/impl/codegen/slice.h> 21 #include <grpc/slice.h> 22 #include <grpc/slice_buffer.h> 23 #include <grpc/support/port_platform.h> 24 #include <string.h> 25 26 #include <cstdint> 27 #include <string> 28 29 #include "absl/strings/string_view.h" 30 #include "absl/utility/utility.h" 31 32 namespace grpc_event_engine { 33 namespace experimental { 34 35 /// A Wrapper around \a grpc_slice_buffer pointer. 36 /// 37 /// A slice buffer holds the memory for a collection of slices. 38 /// The SliceBuffer object itself is meant to only hide the C-style API, 39 /// and won't hold the data itself. In terms of lifespan, the 40 /// grpc_slice_buffer ought to be kept somewhere inside the caller's objects, 41 /// like a transport or an endpoint. 42 /// 43 /// This lifespan rule is likely to change in the future, as we may 44 /// collapse the grpc_slice_buffer structure straight into this class. 45 /// 46 /// The SliceBuffer API is basically a replica of the grpc_slice_buffer's, 47 /// and its documentation will move here once we remove the C structure, 48 /// which should happen before the EventEngine's API is no longer 49 /// an experimental API. 50 class SliceBuffer { 51 public: SliceBuffer()52 SliceBuffer() { grpc_slice_buffer_init(&slice_buffer_); } 53 SliceBuffer(const SliceBuffer& other) = delete; SliceBuffer(SliceBuffer && other)54 SliceBuffer(SliceBuffer&& other) noexcept 55 : slice_buffer_(other.slice_buffer_) { 56 grpc_slice_buffer_init(&slice_buffer_); 57 grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_); 58 } 59 /// Upon destruction, the underlying raw slice buffer is cleaned out and all 60 /// slices are unreffed. ~SliceBuffer()61 ~SliceBuffer() { grpc_slice_buffer_destroy(&slice_buffer_); } 62 63 SliceBuffer& operator=(const SliceBuffer&) = delete; 64 SliceBuffer& operator=(SliceBuffer&& other) noexcept { 65 grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_); 66 return *this; 67 } 68 69 /// Swap the contents of this SliceBuffer with the contents of another. Swap(SliceBuffer & other)70 void Swap(SliceBuffer& other) { 71 grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_); 72 } 73 74 /// Appends a new slice into the SliceBuffer and makes an attempt to merge 75 /// this slice with the last slice in the SliceBuffer. 76 void Append(Slice slice); 77 78 /// Adds a new slice into the SliceBuffer at the next available index. 79 /// Returns the index at which the new slice is added. 80 size_t AppendIndexed(Slice slice); 81 82 /// Returns the number of slices held by the SliceBuffer. Count()83 size_t Count() { return slice_buffer_.count; } 84 85 /// Removes/deletes the last n bytes in the SliceBuffer. RemoveLastNBytes(size_t n)86 void RemoveLastNBytes(size_t n) { 87 grpc_slice_buffer_trim_end(&slice_buffer_, n, nullptr); 88 } 89 90 /// Move the first n bytes of the SliceBuffer into a memory pointed to by dst. MoveFirstNBytesIntoBuffer(size_t n,void * dst)91 void MoveFirstNBytesIntoBuffer(size_t n, void* dst) { 92 grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst); 93 } 94 95 /// Removes/deletes the last n bytes in the SliceBuffer and add it to the 96 /// other SliceBuffer MoveLastNBytesIntoSliceBuffer(size_t n,SliceBuffer & other)97 void MoveLastNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) { 98 grpc_slice_buffer_trim_end(&slice_buffer_, n, &other.slice_buffer_); 99 } 100 101 /// Move the first n bytes of the SliceBuffer into the other SliceBuffer MoveFirstNBytesIntoSliceBuffer(size_t n,SliceBuffer & other)102 void MoveFirstNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) { 103 grpc_slice_buffer_move_first(&slice_buffer_, n, &other.slice_buffer_); 104 } 105 106 /// Removes and unrefs all slices in the SliceBuffer. Clear()107 void Clear() { grpc_slice_buffer_reset_and_unref(&slice_buffer_); } 108 109 /// Removes the first slice in the SliceBuffer and returns it. 110 Slice TakeFirst(); 111 112 /// Prepends the slice to the the front of the SliceBuffer. 113 void Prepend(Slice slice); 114 115 /// Increased the ref-count of slice at the specified index and returns the 116 /// associated slice. 117 Slice RefSlice(size_t index); 118 119 /// Array access into the SliceBuffer. It returns a non mutable reference to 120 /// the slice at the specified index 121 const Slice& operator[](size_t index) const { 122 return internal::SliceCast<Slice>(slice_buffer_.slices[index]); 123 } 124 125 /// Return mutable reference to the slice at the specified index MutableSliceAt(size_t index)126 Slice& MutableSliceAt(size_t index) const { 127 return internal::SliceCast<Slice>(slice_buffer_.slices[index]); 128 } 129 130 /// The total number of bytes held by the SliceBuffer Length()131 size_t Length() const { return slice_buffer_.length; } 132 133 /// Return a pointer to the back raw grpc_slice_buffer c_slice_buffer()134 grpc_slice_buffer* c_slice_buffer() { return &slice_buffer_; } 135 136 // Returns a SliceBuffer that transfers slices into this new SliceBuffer, 137 // leaving the input parameter empty. TakeCSliceBuffer(grpc_slice_buffer & slice_buffer)138 static SliceBuffer TakeCSliceBuffer(grpc_slice_buffer& slice_buffer) { 139 return SliceBuffer(&slice_buffer); 140 } 141 142 private: 143 // Transfers slices into this new SliceBuffer, leaving the parameter empty. 144 // Does not take ownership of the slice_buffer argument. SliceBuffer(grpc_slice_buffer * slice_buffer)145 explicit SliceBuffer(grpc_slice_buffer* slice_buffer) { 146 grpc_slice_buffer_init(&slice_buffer_); 147 grpc_slice_buffer_swap(&slice_buffer_, slice_buffer); 148 } 149 /// The backing raw slice buffer. 150 grpc_slice_buffer slice_buffer_; 151 }; 152 153 } // namespace experimental 154 } // namespace grpc_event_engine 155 156 #endif // GRPC_EVENT_ENGINE_SLICE_BUFFER_H 157