Add support for byte order to LengthFieldPrepender
Motivation: While the LengthFieldBasedFrameDecoder supports a byte order the LengthFieldPrepender does not. That means that I can simply add a LengthFieldBasedFrameDecoder with ByteOrder.LITTLE_ENDIAN to my pipeline but have to write my own Encoder to write length fields in little endian byte order. Modifications: Added a constructor that takes a byte order and all other parameters. All other constructors delegate to this one with ByteOrder.BIG_ENDIAN. LengthFieldPrepender.encode() uses this byte order to write the length field. Result: LengthFieldPrepender will write the length field in the defined byte order.
This commit is contained in:
parent
6954f034fd
commit
01c3fd3ace
@ -18,7 +18,9 @@ package io.netty.handler.codec;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.internal.ObjectUtil;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* An encoder that prepends the length of the message. The length value is
|
||||
@ -49,6 +51,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
@Sharable
|
||||
public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
private final ByteOrder byteOrder;
|
||||
private final int lengthFieldLength;
|
||||
private final boolean lengthIncludesLengthFieldLength;
|
||||
private final int lengthAdjustment;
|
||||
@ -114,6 +117,28 @@ public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
* if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8
|
||||
*/
|
||||
public LengthFieldPrepender(int lengthFieldLength, int lengthAdjustment, boolean lengthIncludesLengthFieldLength) {
|
||||
this(ByteOrder.BIG_ENDIAN, lengthFieldLength, lengthAdjustment, lengthIncludesLengthFieldLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param byteOrder the {@link ByteOrder} of the length field
|
||||
* @param lengthFieldLength the length of the prepended length field.
|
||||
* Only 1, 2, 3, 4, and 8 are allowed.
|
||||
* @param lengthAdjustment the compensation value to add to the value
|
||||
* of the length field
|
||||
* @param lengthIncludesLengthFieldLength
|
||||
* if {@code true}, the length of the prepended
|
||||
* length field is added to the value of the
|
||||
* prepended length field.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code lengthFieldLength} is not 1, 2, 3, 4, or 8
|
||||
*/
|
||||
public LengthFieldPrepender(
|
||||
ByteOrder byteOrder, int lengthFieldLength,
|
||||
int lengthAdjustment, boolean lengthIncludesLengthFieldLength) {
|
||||
if (lengthFieldLength != 1 && lengthFieldLength != 2 &&
|
||||
lengthFieldLength != 3 && lengthFieldLength != 4 &&
|
||||
lengthFieldLength != 8) {
|
||||
@ -121,7 +146,9 @@ public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
"lengthFieldLength must be either 1, 2, 3, 4, or 8: " +
|
||||
lengthFieldLength);
|
||||
}
|
||||
ObjectUtil.checkNotNull(byteOrder, "byteOrder");
|
||||
|
||||
this.byteOrder = byteOrder;
|
||||
this.lengthFieldLength = lengthFieldLength;
|
||||
this.lengthIncludesLengthFieldLength = lengthIncludesLengthFieldLength;
|
||||
this.lengthAdjustment = lengthAdjustment;
|
||||
@ -173,4 +200,9 @@ public class LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
out.writeBytes(msg, msg.readerIndex(), msg.readableBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception {
|
||||
return super.allocateBuffer(ctx, msg, preferDirect).order(byteOrder);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import org.junit.Test;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class LengthFieldPrependerTest {
|
||||
@ -73,4 +75,22 @@ public class LengthFieldPrependerTest {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrependLengthInLittleEndian() throws Exception {
|
||||
final EmbeddedChannel ch = new EmbeddedChannel(new LengthFieldPrepender(ByteOrder.LITTLE_ENDIAN, 4, 0, false));
|
||||
ch.writeOutbound(msg);
|
||||
ByteBuf buf = (ByteBuf) ch.readOutbound();
|
||||
assertEquals(5, buf.readableBytes());
|
||||
byte[] writtenBytes = new byte[buf.readableBytes()];
|
||||
buf.getBytes(0, writtenBytes);
|
||||
assertEquals(1, writtenBytes[0]);
|
||||
assertEquals(0, writtenBytes[1]);
|
||||
assertEquals(0, writtenBytes[2]);
|
||||
assertEquals(0, writtenBytes[3]);
|
||||
assertEquals('A', writtenBytes[4]);
|
||||
buf.release();
|
||||
assertFalse("The channel must have been completely read", ch.finish());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user