• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20123

22 Dec 2025 07:27PM UTC coverage: 88.719% (-0.03%) from 88.747%
#20123

push

github

web-flow
core: Delete ReadableBuffer.readBytes(ByteBuffer) (#12580)

At the very least it isn't used now. The method is as old as
ReadableBuffer itself (05a2b252b), but it appears to have never actually
been used.

35445 of 39952 relevant lines covered (88.72%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.07
/../core/src/main/java/io/grpc/internal/ReadableBuffers.java
1
/*
2
 * Copyright 2014 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.internal;
18

19
import static java.nio.charset.StandardCharsets.UTF_8;
20

21
import com.google.common.base.Preconditions;
22
import io.grpc.Detachable;
23
import io.grpc.HasByteBuffer;
24
import io.grpc.KnownLength;
25
import java.io.IOException;
26
import java.io.InputStream;
27
import java.io.OutputStream;
28
import java.nio.Buffer;
29
import java.nio.ByteBuffer;
30
import java.nio.InvalidMarkException;
31
import java.nio.charset.Charset;
32
import javax.annotation.Nullable;
33

34
/**
35
 * Utility methods for creating {@link ReadableBuffer} instances.
36
 */
37
public final class ReadableBuffers {
38
  private static final ReadableBuffer EMPTY_BUFFER = new ByteArrayWrapper(new byte[0]);
1✔
39

40
  /**
41
   * Returns an empty {@link ReadableBuffer} instance.
42
   */
43
  public static ReadableBuffer empty() {
44
    return EMPTY_BUFFER;
1✔
45
  }
46

47
  /**
48
   * Shortcut for {@code wrap(bytes, 0, bytes.length}.
49
   */
50
  public static ReadableBuffer wrap(byte[] bytes) {
51
    return new ByteArrayWrapper(bytes, 0, bytes.length);
1✔
52
  }
53

54
  /**
55
   * Creates a new {@link ReadableBuffer} that is backed by the given byte array.
56
   *
57
   * @param bytes the byte array being wrapped.
58
   * @param offset the starting offset for the buffer within the byte array.
59
   * @param length the length of the buffer from the {@code offset} index.
60
   */
61
  public static ReadableBuffer wrap(byte[] bytes, int offset, int length) {
62
    return new ByteArrayWrapper(bytes, offset, length);
1✔
63
  }
64

65
  /**
66
   * Creates a new {@link ReadableBuffer} that is backed by the given {@link ByteBuffer}. Calls to
67
   * read from the buffer will increment the position of the {@link ByteBuffer}.
68
   */
69
  public static ReadableBuffer wrap(ByteBuffer bytes) {
70
    return new ByteReadableBufferWrapper(bytes);
1✔
71
  }
72

73
  /**
74
   * Reads an entire {@link ReadableBuffer} to a new array. After calling this method, the buffer
75
   * will contain no readable bytes.
76
   */
77
  public static byte[] readArray(ReadableBuffer buffer) {
78
    Preconditions.checkNotNull(buffer, "buffer");
1✔
79
    int length = buffer.readableBytes();
1✔
80
    byte[] bytes = new byte[length];
1✔
81
    buffer.readBytes(bytes, 0, length);
1✔
82
    return bytes;
1✔
83
  }
84

85
  /**
86
   * Reads the entire {@link ReadableBuffer} to a new {@link String} with the given charset.
87
   */
88
  public static String readAsString(ReadableBuffer buffer, Charset charset) {
89
    Preconditions.checkNotNull(charset, "charset");
1✔
90
    byte[] bytes = readArray(buffer);
1✔
91
    return new String(bytes, charset);
1✔
92
  }
93

94
  /**
95
   * Reads the entire {@link ReadableBuffer} to a new {@link String} using UTF-8 decoding.
96
   */
97
  public static String readAsStringUtf8(ReadableBuffer buffer) {
98
    return readAsString(buffer, UTF_8);
1✔
99
  }
100

101
  /**
102
   * Creates a new {@link InputStream} backed by the given buffer. Any read taken on the stream will
103
   * automatically increment the read position of this buffer. Closing the stream, however, does not
104
   * affect the original buffer.
105
   *
106
   * @param buffer the buffer backing the new {@link InputStream}.
107
   * @param owner if {@code true}, the returned stream will close the buffer when closed.
108
   */
109
  public static InputStream openStream(ReadableBuffer buffer, boolean owner) {
110
    return new BufferInputStream(owner ? buffer : ignoreClose(buffer));
1✔
111
  }
112

113
  /**
114
   * Decorates the given {@link ReadableBuffer} to ignore calls to {@link ReadableBuffer#close}.
115
   *
116
   * @param buffer the buffer to be decorated.
117
   * @return a wrapper around {@code buffer} that ignores calls to {@link ReadableBuffer#close}.
118
   */
119
  public static ReadableBuffer ignoreClose(ReadableBuffer buffer) {
120
    return new ForwardingReadableBuffer(buffer) {
1✔
121
      @Override
122
      public void close() {
123
        // Ignore.
124
      }
1✔
125
    };
126
  }
127

128
  /**
129
   * A {@link ReadableBuffer} that is backed by a byte array.
130
   */
131
  private static class ByteArrayWrapper extends AbstractReadableBuffer {
132
    int offset;
133
    final int end;
134
    final byte[] bytes;
135
    int mark = -1;
1✔
136

137
    ByteArrayWrapper(byte[] bytes) {
138
      this(bytes, 0, bytes.length);
1✔
139
    }
1✔
140

141
    ByteArrayWrapper(byte[] bytes, int offset, int length) {
1✔
142
      Preconditions.checkArgument(offset >= 0, "offset must be >= 0");
1✔
143
      Preconditions.checkArgument(length >= 0, "length must be >= 0");
1✔
144
      Preconditions.checkArgument(offset + length <= bytes.length,
1✔
145
          "offset + length exceeds array boundary");
146
      this.bytes = Preconditions.checkNotNull(bytes, "bytes");
1✔
147
      this.offset = offset;
1✔
148
      this.end = offset + length;
1✔
149
    }
1✔
150

151
    @Override
152
    public int readableBytes() {
153
      return end - offset;
1✔
154
    }
155

156
    @Override
157
    public void skipBytes(int length) {
158
      checkReadable(length);
1✔
159
      offset += length;
1✔
160
    }
1✔
161

162
    @Override
163
    public int readUnsignedByte() {
164
      checkReadable(1);
1✔
165
      return bytes[offset++] & 0xFF;
1✔
166
    }
167

168
    @Override
169
    public void readBytes(byte[] dest, int destIndex, int length) {
170
      System.arraycopy(bytes, offset, dest, destIndex, length);
1✔
171
      offset += length;
1✔
172
    }
1✔
173

174
    @Override
175
    public void readBytes(OutputStream dest, int length) throws IOException {
176
      checkReadable(length);
1✔
177
      dest.write(bytes, offset, length);
1✔
178
      offset += length;
1✔
179
    }
1✔
180

181
    @Override
182
    public ByteArrayWrapper readBytes(int length) {
183
      checkReadable(length);
1✔
184
      int originalOffset = offset;
1✔
185
      offset += length;
1✔
186
      return new ByteArrayWrapper(bytes, originalOffset, length);
1✔
187
    }
188

189
    @Override
190
    public boolean hasArray() {
191
      return true;
1✔
192
    }
193

194
    @Override
195
    public byte[] array() {
196
      return bytes;
1✔
197
    }
198

199
    @Override
200
    public int arrayOffset() {
201
      return offset;
1✔
202
    }
203

204
    @Override
205
    public boolean markSupported() {
206
      return true;
1✔
207
    }
208

209
    @Override
210
    public void mark() {
211
      mark = offset;
1✔
212
    }
1✔
213

214
    @Override
215
    public void reset() {
216
      if (mark == -1) {
1✔
217
        throw new InvalidMarkException();
1✔
218
      }
219
      offset = mark;
1✔
220
    }
1✔
221
  }
222

223
  /**
224
   * A {@link ReadableBuffer} that is backed by a {@link ByteBuffer}.
225
   */
226
  private static class ByteReadableBufferWrapper extends AbstractReadableBuffer {
227
    final ByteBuffer bytes;
228

229
    ByteReadableBufferWrapper(ByteBuffer bytes) {
1✔
230
      this.bytes = Preconditions.checkNotNull(bytes, "bytes");
1✔
231
    }
1✔
232

233
    @Override
234
    public int readableBytes() {
235
      return bytes.remaining();
1✔
236
    }
237

238
    @Override
239
    public int readUnsignedByte() {
240
      checkReadable(1);
1✔
241
      return bytes.get() & 0xFF;
1✔
242
    }
243

244
    @Override
245
    public void skipBytes(int length) {
246
      checkReadable(length);
×
247
      ((Buffer) bytes).position(bytes.position() + length);
×
248
    }
×
249

250
    @Override
251
    public void readBytes(byte[] dest, int destOffset, int length) {
252
      checkReadable(length);
1✔
253
      bytes.get(dest, destOffset, length);
1✔
254
    }
1✔
255

256
    @Override
257
    public void readBytes(OutputStream dest, int length) throws IOException {
258
      checkReadable(length);
1✔
259
      if (hasArray()) {
1✔
260
        dest.write(array(), arrayOffset(), length);
1✔
261
        ((Buffer) bytes).position(bytes.position() + length);
1✔
262
      } else {
263
        // The buffer doesn't support array(). Copy the data to an intermediate buffer.
264
        byte[] array = new byte[length];
×
265
        bytes.get(array);
×
266
        dest.write(array);
×
267
      }
268
    }
1✔
269

270
    @Override
271
    public ByteReadableBufferWrapper readBytes(int length) {
272
      checkReadable(length);
1✔
273
      ByteBuffer buffer = bytes.duplicate();
1✔
274
      ((Buffer) buffer).limit(bytes.position() + length);
1✔
275
      ((Buffer) bytes).position(bytes.position() + length);
1✔
276
      return new ByteReadableBufferWrapper(buffer);
1✔
277
    }
278

279
    @Override
280
    public boolean hasArray() {
281
      return bytes.hasArray();
1✔
282
    }
283

284
    @Override
285
    public byte[] array() {
286
      return bytes.array();
1✔
287
    }
288

289
    @Override
290
    public int arrayOffset() {
291
      return bytes.arrayOffset() + bytes.position();
1✔
292
    }
293

294
    @Override
295
    public boolean markSupported() {
296
      return true;
×
297
    }
298

299
    @Override
300
    public void mark() {
301
      bytes.mark();
1✔
302
    }
1✔
303

304
    @Override
305
    public void reset() {
306
      bytes.reset();
1✔
307
    }
1✔
308

309
    @Override
310
    public boolean byteBufferSupported() {
311
      return true;
1✔
312
    }
313

314
    @Override
315
    public ByteBuffer getByteBuffer() {
316
      return bytes.slice();
1✔
317
    }
318
  }
319

320
  /**
321
   * An {@link InputStream} that is backed by a {@link ReadableBuffer}.
322
   */
323
  private static final class BufferInputStream extends InputStream
324
      implements KnownLength, HasByteBuffer, Detachable {
325
    private ReadableBuffer buffer;
326

327
    public BufferInputStream(ReadableBuffer buffer) {
1✔
328
      this.buffer = Preconditions.checkNotNull(buffer, "buffer");
1✔
329
    }
1✔
330

331
    @Override
332
    public int available() throws IOException {
333
      return buffer.readableBytes();
1✔
334
    }
335

336
    @Override
337
    public int read() {
338
      if (buffer.readableBytes() == 0) {
1✔
339
        // EOF.
340
        return -1;
1✔
341
      }
342
      return buffer.readUnsignedByte();
1✔
343
    }
344

345
    @Override
346
    public int read(byte[] dest, int destOffset, int length) throws IOException {
347
      if (buffer.readableBytes() == 0) {
1✔
348
        // EOF.
349
        return -1;
1✔
350
      }
351

352
      length = Math.min(buffer.readableBytes(), length);
1✔
353
      buffer.readBytes(dest, destOffset, length);
1✔
354
      return length;
1✔
355
    }
356

357
    @Override
358
    public long skip(long n) throws IOException {
359
      int length = (int) Math.min(buffer.readableBytes(), n);
1✔
360
      buffer.skipBytes(length);
1✔
361
      return length;
1✔
362
    }
363

364
    @Override
365
    public void mark(int readlimit) {
366
      buffer.mark();
1✔
367
    }
1✔
368

369
    @Override
370
    public void reset() throws IOException {
371
      buffer.reset();
1✔
372
    }
1✔
373

374
    @Override
375
    public boolean markSupported() {
376
      return buffer.markSupported();
1✔
377
    }
378

379
    @Override
380
    public boolean byteBufferSupported() {
381
      return buffer.byteBufferSupported();
1✔
382
    }
383

384
    @Nullable
385
    @Override
386
    public ByteBuffer getByteBuffer() {
387
      return buffer.getByteBuffer();
1✔
388
    }
389

390
    @Override
391
    public InputStream detach() {
392
      ReadableBuffer detachedBuffer = buffer;
1✔
393
      buffer = buffer.readBytes(0);
1✔
394
      detachedBuffer.touch();
1✔
395
      return new BufferInputStream(detachedBuffer);
1✔
396
    }
397

398
    @Override
399
    public void close() throws IOException {
400
      buffer.close();
1✔
401
    }
1✔
402
  }
403

404
  private ReadableBuffers() {}
405
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc