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:
parent
ad008f6831
commit
f3f49c91fd
@ -363,11 +363,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user