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.netty; 18 19 import com.google.common.base.Preconditions; 20 import io.grpc.internal.AbstractReadableBuffer; 21 import io.netty.buffer.ByteBuf; 22 import java.io.IOException; 23 import java.io.OutputStream; 24 import java.nio.ByteBuffer; 25 26 /** 27 * A {@link java.nio.Buffer} implementation that is backed by a Netty {@link ByteBuf}. This class 28 * does not call {@link ByteBuf#retain}, so if that is needed it should be called prior to creating 29 * this buffer. 30 */ 31 class NettyReadableBuffer extends AbstractReadableBuffer { 32 private final ByteBuf buffer; 33 private boolean closed; 34 NettyReadableBuffer(ByteBuf buffer)35 NettyReadableBuffer(ByteBuf buffer) { 36 this.buffer = Preconditions.checkNotNull(buffer, "buffer"); 37 } 38 buffer()39 ByteBuf buffer() { 40 return buffer; 41 } 42 43 @Override readableBytes()44 public int readableBytes() { 45 return buffer.readableBytes(); 46 } 47 48 @Override skipBytes(int length)49 public void skipBytes(int length) { 50 buffer.skipBytes(length); 51 } 52 53 @Override readUnsignedByte()54 public int readUnsignedByte() { 55 return buffer.readUnsignedByte(); 56 } 57 58 @Override readBytes(byte[] dest, int index, int length)59 public void readBytes(byte[] dest, int index, int length) { 60 buffer.readBytes(dest, index, length); 61 } 62 63 @Override readBytes(ByteBuffer dest)64 public void readBytes(ByteBuffer dest) { 65 buffer.readBytes(dest); 66 } 67 68 @Override readBytes(OutputStream dest, int length)69 public void readBytes(OutputStream dest, int length) { 70 try { 71 buffer.readBytes(dest, length); 72 } catch (IOException e) { 73 throw new RuntimeException(e); 74 } 75 } 76 77 @Override readBytes(int length)78 public NettyReadableBuffer readBytes(int length) { 79 return new NettyReadableBuffer(buffer.readRetainedSlice(length)); 80 } 81 82 @Override hasArray()83 public boolean hasArray() { 84 return buffer.hasArray(); 85 } 86 87 @Override array()88 public byte[] array() { 89 return buffer.array(); 90 } 91 92 @Override arrayOffset()93 public int arrayOffset() { 94 return buffer.arrayOffset() + buffer.readerIndex(); 95 } 96 97 @Override markSupported()98 public boolean markSupported() { 99 return true; 100 } 101 102 @Override mark()103 public void mark() { 104 buffer.markReaderIndex(); 105 } 106 107 @Override reset()108 public void reset() { 109 buffer.resetReaderIndex(); 110 } 111 112 @Override byteBufferSupported()113 public boolean byteBufferSupported() { 114 return buffer.nioBufferCount() > 0; 115 } 116 117 @Override getByteBuffer()118 public ByteBuffer getByteBuffer() { 119 return buffer.nioBufferCount() == 1 ? buffer.nioBuffer() : buffer.nioBuffers()[0]; 120 } 121 122 /** 123 * If the first call to close, calls {@link ByteBuf#release} to release the internal Netty buffer. 124 */ 125 @Override close()126 public void close() { 127 // Don't allow slices to close. Also, only allow close to be called once. 128 if (!closed) { 129 closed = true; 130 buffer.release(); 131 } 132 } 133 } 134