Fix setBytes on read-only ByteBuffer

Motivation:

The method setBytes did not work correctly because read-only ByteBuffer
does not allow access to its underlying array.

Modifications:

New case was added for ByteBuffer's that are not direct and do not have an array.
These must be handled by copying the data into a temporary array. Unit test was
added to test this case.

Result:

It is now possible to use read-only ByteBuffer as the source
for the setBytes method.
This commit is contained in:
Janecek Jakub 2015-11-16 17:01:36 +01:00 committed by Norman Maurer
parent 8accc52b03
commit a4ebdd0eca
2 changed files with 60 additions and 2 deletions

View File

@ -362,11 +362,21 @@ final class UnsafeByteBufUtil {
// Copy from direct memory
long srcAddress = PlatformDependent.directBufferAddress(src);
PlatformDependent.copyMemory(srcAddress + src.position(), addr, src.remaining());
} else {
src.position(src.position() + length);
} else if (src.hasArray()) {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
src.position(src.position() + length);
} else {
ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
try {
byte[] tmp = tmpBuf.array();
src.get(tmp, tmpBuf.arrayOffset(), length); // moves the src position too
PlatformDependent.copyMemory(tmp, 0, addr, length);
} finally {
tmpBuf.release();
}
}
src.position(src.position() + length);
}
static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {

View File

@ -0,0 +1,48 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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.
*/
package io.netty.buffer;
import org.junit.Test;
import java.nio.ByteBuffer;
import static io.netty.util.internal.PlatformDependent.directBufferAddress;
import static org.junit.Assert.assertArrayEquals;
public class UnsafeByteBufUtilTest {
@Test
public void testSetBytesOnReadOnlyByteBuffer() throws Exception {
byte[] testData = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int length = testData.length;
ByteBuffer readOnlyBuffer = ByteBuffer.wrap(testData).asReadOnlyBuffer();
UnpooledByteBufAllocator alloc = new UnpooledByteBufAllocator(true);
UnpooledDirectByteBuf targetBuffer = new UnpooledDirectByteBuf(alloc, length, length);
try {
UnsafeByteBufUtil.setBytes(targetBuffer, directBufferAddress(targetBuffer.nioBuffer()), 0, readOnlyBuffer);
byte[] check = new byte[length];
targetBuffer.getBytes(0, check, 0, length);
assertArrayEquals("The byte array's copy does not equal the original", testData, check);
} finally {
targetBuffer.release();
}
}
}