aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/grpc/include/grpc/event_engine/slice_buffer.h
blob: 35bf56bd8ab75e3ec6b9f2b1946c8f23ba3b969b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef GRPC_EVENT_ENGINE_SLICE_BUFFER_H
#define GRPC_EVENT_ENGINE_SLICE_BUFFER_H

#include <grpc/support/port_platform.h>

#include <string.h>

#include <cstdint>
#include <util/generic/string.h>
#include <util/string/cast.h>

#include "y_absl/strings/string_view.h"
#include "y_absl/utility/utility.h"

#include <grpc/event_engine/internal/slice_cast.h>
#include <grpc/event_engine/slice.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/log.h>

namespace grpc_event_engine {
namespace experimental {

/// A Wrapper around \a grpc_slice_buffer pointer.
///
/// A slice buffer holds the memory for a collection of slices.
/// The SliceBuffer object itself is meant to only hide the C-style API,
/// and won't hold the data itself. In terms of lifespan, the
/// grpc_slice_buffer ought to be kept somewhere inside the caller's objects,
/// like a transport or an endpoint.
///
/// This lifespan rule is likely to change in the future, as we may
/// collapse the grpc_slice_buffer structure straight into this class.
///
/// The SliceBuffer API is basically a replica of the grpc_slice_buffer's,
/// and its documentation will move here once we remove the C structure,
/// which should happen before the EventEngine's API is no longer
/// an experimental API.
class SliceBuffer {
 public:
  SliceBuffer() { grpc_slice_buffer_init(&slice_buffer_); }
  SliceBuffer(const SliceBuffer& other) = delete;
  SliceBuffer(SliceBuffer&& other) noexcept
      : slice_buffer_(other.slice_buffer_) {
    grpc_slice_buffer_init(&slice_buffer_);
    grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
  }
  /// Upon destruction, the underlying raw slice buffer is cleaned out and all
  /// slices are unreffed.
  ~SliceBuffer() { grpc_slice_buffer_destroy(&slice_buffer_); }

  SliceBuffer& operator=(const SliceBuffer&) = delete;
  SliceBuffer& operator=(SliceBuffer&& other) noexcept {
    grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
    return *this;
  }

  /// Swap the contents of this SliceBuffer with the contents of another.
  void Swap(SliceBuffer& other) {
    grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
  }

  /// Appends a new slice into the SliceBuffer and makes an attempt to merge
  /// this slice with the last slice in the SliceBuffer.
  void Append(Slice slice);

  /// Adds a new slice into the SliceBuffer at the next available index.
  /// Returns the index at which the new slice is added.
  size_t AppendIndexed(Slice slice);

  /// Returns the number of slices held by the SliceBuffer.
  size_t Count() { return slice_buffer_.count; }

  /// Removes/deletes the last n bytes in the SliceBuffer.
  void RemoveLastNBytes(size_t n) {
    grpc_slice_buffer_trim_end(&slice_buffer_, n, nullptr);
  }

  /// Move the first n bytes of the SliceBuffer into a memory pointed to by dst.
  void MoveFirstNBytesIntoBuffer(size_t n, void* dst) {
    grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst);
  }

  /// Removes/deletes the last n bytes in the SliceBuffer and add it to the
  /// other SliceBuffer
  void MoveLastNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
    grpc_slice_buffer_trim_end(&slice_buffer_, n, &other.slice_buffer_);
  }

  /// Move the first n bytes of the SliceBuffer into the other SliceBuffer
  void MoveFirstNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
    grpc_slice_buffer_move_first(&slice_buffer_, n, &other.slice_buffer_);
  }

  /// Removes and unrefs all slices in the SliceBuffer.
  void Clear() { grpc_slice_buffer_reset_and_unref(&slice_buffer_); }

  /// Removes the first slice in the SliceBuffer and returns it.
  Slice TakeFirst();

  /// Prepends the slice to the the front of the SliceBuffer.
  void Prepend(Slice slice);

  /// Increased the ref-count of slice at the specified index and returns the
  /// associated slice.
  Slice RefSlice(size_t index);

  /// Array access into the SliceBuffer. It returns a non mutable reference to
  /// the slice at the specified index
  const Slice& operator[](size_t index) const {
    return internal::SliceCast<Slice>(slice_buffer_.slices[index]);
  }

  /// Return mutable reference to the slice at the specified index
  Slice& MutableSliceAt(size_t index) const {
    return internal::SliceCast<Slice>(slice_buffer_.slices[index]);
  }

  /// The total number of bytes held by the SliceBuffer
  size_t Length() const { return slice_buffer_.length; }

  /// Return a pointer to the back raw grpc_slice_buffer
  grpc_slice_buffer* c_slice_buffer() { return &slice_buffer_; }

  // Returns a SliceBuffer that transfers slices into this new SliceBuffer,
  // leaving the input parameter empty.
  static SliceBuffer TakeCSliceBuffer(grpc_slice_buffer& slice_buffer) {
    return SliceBuffer(&slice_buffer);
  }

 private:
  // Transfers slices into this new SliceBuffer, leaving the parameter empty.
  // Does not take ownership of the slice_buffer argument.
  explicit SliceBuffer(grpc_slice_buffer* slice_buffer) {
    grpc_slice_buffer_init(&slice_buffer_);
    grpc_slice_buffer_swap(&slice_buffer_, slice_buffer);
  }
  /// The backing raw slice buffer.
  grpc_slice_buffer slice_buffer_;
};

}  // namespace experimental
}  // namespace grpc_event_engine

#endif  // GRPC_EVENT_ENGINE_SLICE_BUFFER_H