diff --git a/NOTICE.txt b/NOTICE.txt index 952a6e418a..19d04a248e 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -146,7 +146,7 @@ and decompression library written by William Kinney. It can be obtained at: * HOMEPAGE: * https://code.google.com/p/jfastlz/ -This product optionally depends on 'Protocol Buffers', Google's data +This product contains a modified portion of and optionally depends on 'Protocol Buffers', Google's data interchange format, which can be obtained at: * LICENSE: diff --git a/codec/pom.xml b/codec/pom.xml index a34b251608..0579705dee 100644 --- a/codec/pom.xml +++ b/codec/pom.xml @@ -39,6 +39,11 @@ protobuf-java true + + com.google.protobuf.nano + protobuf-javanano + true + org.jboss.marshalling jboss-marshalling diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoder.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoder.java index a31e16461e..ed282467ff 100644 --- a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -33,10 +33,10 @@ import java.util.List; /** * Decodes a received {@link ByteBuf} into a * Google Protocol Buffers - * {@link Message} and {@link MessageLite}. Please note that this decoder must + * {@link Message} and {@link MessageLite}. Please note that this decoder must * be used with a proper {@link ByteToMessageDecoder} such as {@link ProtobufVarint32FrameDecoder} * or {@link LengthFieldBasedFrameDecoder} if you are using a stream-based - * transport such as TCP/IP. A typical setup for TCP/IP would be: + * transport such as TCP/IP. A typical setup for TCP/IP would be: *
  * {@link ChannelPipeline} pipeline = ...;
  *
@@ -53,7 +53,8 @@ import java.util.List;
  * and then you can use a {@code MyMessage} instead of a {@link ByteBuf}
  * as a message:
  * 
- * void channelRead({@link ChannelHandlerContext} ctx, MyMessage req) {
+ * void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
+ *     MyMessage req = (MyMessage) msg;
  *     MyMessage res = MyMessage.newBuilder().setText(
  *                               "Did you say '" + req.getText() + "'?").build();
  *     ch.write(res);
@@ -101,7 +102,8 @@ public class ProtobufDecoder extends MessageToMessageDecoder {
     }
 
     @Override
-    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) throws Exception {
+    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out)
+            throws Exception {
         final byte[] array;
         final int offset;
         final int length = msg.readableBytes();
@@ -122,9 +124,11 @@ public class ProtobufDecoder extends MessageToMessageDecoder {
             }
         } else {
             if (HAS_PARSER) {
-                out.add(prototype.getParserForType().parseFrom(array, offset, length, extensionRegistry));
+                out.add(prototype.getParserForType().parseFrom(
+                        array, offset, length, extensionRegistry));
             } else {
-                out.add(prototype.newBuilderForType().mergeFrom(array, offset, length, extensionRegistry).build());
+                out.add(prototype.newBuilderForType().mergeFrom(
+                        array, offset, length, extensionRegistry).build());
             }
         }
     }
diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoderNano.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoderNano.java
new file mode 100644
index 0000000000..c7915e4195
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufDecoderNano.java
@@ -0,0 +1,88 @@
+/*
+ * 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.handler.codec.protobuf;
+
+import com.google.protobuf.nano.MessageNano;
+
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.codec.MessageToMessageDecoder;
+import io.netty.util.internal.ObjectUtil;
+
+/**
+ * Decodes a received {@link ByteBuf} into a
+ * Google Protocol Buffers
+ * {@link MessageNano}. Please note that this decoder must
+ * be used with a proper {@link ByteToMessageDecoder} such as {@link LengthFieldBasedFrameDecoder}
+ * if you are using a stream-based transport such as TCP/IP. A typical setup for TCP/IP would be:
+ * 
+ * {@link ChannelPipeline} pipeline = ...;
+ *
+ * // Decoders
+ * pipeline.addLast("frameDecoder",
+ *                  new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
+ * pipeline.addLast("protobufDecoder",
+ *                  new {@link ProtobufDecoderNano}(MyMessage.getDefaultInstance()));
+ *
+ * // Encoder
+ * pipeline.addLast("frameEncoder", new {@link io.netty.handler.codec.LengthFieldPrepender}(4));
+ * pipeline.addLast("protobufEncoder", new {@link ProtobufEncoderNano}());
+ * 
+ * and then you can use a {@code MyMessage} instead of a {@link ByteBuf} + * as a message: + *
+ * void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
+ *     MyMessage req = (MyMessage) msg;
+ *     MyMessage res = MyMessage.newBuilder().setText(
+ *                               "Did you say '" + req.getText() + "'?").build();
+ *     ch.write(res);
+ * }
+ * 
+ */ +@Sharable +public class ProtobufDecoderNano extends MessageToMessageDecoder { + private final Class clazz; + /** + * Creates a new instance. + */ + public ProtobufDecoderNano(Class clazz) { + this.clazz = ObjectUtil.checkNotNull(clazz, "You must provide a Class"); + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) + throws Exception { + final byte[] array; + final int offset; + final int length = msg.readableBytes(); + if (msg.hasArray()) { + array = msg.array(); + offset = msg.arrayOffset() + msg.readerIndex(); + } else { + array = new byte[length]; + msg.getBytes(msg.readerIndex(), array, 0, length); + offset = 0; + } + MessageNano prototype = clazz.newInstance(); + out.add(MessageNano.mergeFrom(prototype, array, offset, length)); + } +} diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoder.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoder.java index a7e56c26bc..544ad449c9 100644 --- a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -50,7 +50,8 @@ import static io.netty.buffer.Unpooled.*; * and then you can use a {@code MyMessage} instead of a {@link ByteBuf} * as a message: *
- * void channelRead({@link ChannelHandlerContext} ctx, MyMessage req) {
+ * void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
+ *     MyMessage req = (MyMessage) msg;
  *     MyMessage res = MyMessage.newBuilder().setText(
  *                               "Did you say '" + req.getText() + "'?").build();
  *     ch.write(res);
@@ -60,8 +61,8 @@ import static io.netty.buffer.Unpooled.*;
 @Sharable
 public class ProtobufEncoder extends MessageToMessageEncoder {
     @Override
-    protected void encode(
-            ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List out) throws Exception {
+    protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List out)
+            throws Exception {
         if (msg instanceof MessageLite) {
             out.add(wrappedBuffer(((MessageLite) msg).toByteArray()));
             return;
diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoderNano.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoderNano.java
new file mode 100644
index 0000000000..a2d684eccf
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufEncoderNano.java
@@ -0,0 +1,73 @@
+/*
+ * 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.handler.codec.protobuf;
+
+import com.google.protobuf.nano.CodedOutputByteBufferNano;
+import com.google.protobuf.nano.MessageNano;
+
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.codec.LengthFieldPrepender;
+import io.netty.handler.codec.MessageToMessageEncoder;
+
+/**
+ * Encodes the requested Google
+ * Protocol Buffers {@link MessageNano} into a
+ * {@link ByteBuf}. A typical setup for TCP/IP would be:
+ * 
+ * {@link ChannelPipeline} pipeline = ...;
+ *
+ * // Decoders
+ * pipeline.addLast("frameDecoder",
+ *                  new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
+ * pipeline.addLast("protobufDecoder",
+ *                  new {@link ProtobufDecoderNano}(MyMessage.getDefaultInstance()));
+ *
+ * // Encoder
+ * pipeline.addLast("frameEncoder", new {@link LengthFieldPrepender}(4));
+ * pipeline.addLast("protobufEncoder", new {@link ProtobufEncoderNano}());
+ * 
+ * and then you can use a {@code MyMessage} instead of a {@link ByteBuf} + * as a message: + *
+ * void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
+ *     MyMessage req = (MyMessage) msg;
+ *     MyMessage res = MyMessage.newBuilder().setText(
+ *                               "Did you say '" + req.getText() + "'?").build();
+ *     ch.write(res);
+ * }
+ * 
+ */ +@ChannelHandler.Sharable +public class ProtobufEncoderNano extends MessageToMessageEncoder { + @Override + protected void encode( + ChannelHandlerContext ctx, MessageNano msg, List out) throws Exception { + final int size = msg.getSerializedSize(); + final ByteBuf buffer = ctx.alloc().heapBuffer(size, size); + final byte[] array = buffer.array(); + CodedOutputByteBufferNano cobbn = CodedOutputByteBufferNano.newInstance(array, + buffer.arrayOffset(), buffer.capacity()); + msg.writeTo(cobbn); + buffer.writerIndex(size); + out.add(buffer); + } +} diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoder.java index b1abc5b410..ec8395b5f7 100644 --- a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -15,20 +15,19 @@ */ package io.netty.handler.codec.protobuf; +import java.io.IOException; +import java.util.List; + import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; -import java.util.List; - -import com.google.protobuf.CodedInputStream; - /** * A decoder that splits the received {@link ByteBuf}s dynamically by the * value of the Google Protocol Buffers * Base - * 128 Varints integer length field in the message. For example: + * 128 Varints integer length field in the message. For example: *
  * BEFORE DECODE (302 bytes)       AFTER DECODE (300 bytes)
  * +--------+---------------+      +---------------+
@@ -37,7 +36,7 @@ import com.google.protobuf.CodedInputStream;
  * +--------+---------------+      +---------------+
  * 
* - * @see CodedInputStream + * @see {@link CodedInputStream } or {@link CodedInputByteBufferNano} */ public class ProtobufVarint32FrameDecoder extends ByteToMessageDecoder { @@ -45,33 +44,79 @@ public class ProtobufVarint32FrameDecoder extends ByteToMessageDecoder { // (just like LengthFieldBasedFrameDecoder) @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) + throws Exception { in.markReaderIndex(); - final byte[] buf = new byte[5]; - for (int i = 0; i < buf.length; i ++) { - if (!in.isReadable()) { - in.resetReaderIndex(); - return; - } - - buf[i] = in.readByte(); - if (buf[i] >= 0) { - int length = CodedInputStream.newInstance(buf, 0, i + 1).readRawVarint32(); - if (length < 0) { - throw new CorruptedFrameException("negative length: " + length); - } - - if (in.readableBytes() < length) { - in.resetReaderIndex(); - return; - } else { - out.add(in.readBytes(length)); - return; - } - } + int preIndex = in.readerIndex(); + int length = readRawVarint32(in); + if (preIndex == in.readerIndex()) { + return; + } + if (length < 0) { + throw new CorruptedFrameException("negative length: " + length); } - // Couldn't find the byte whose MSB is off. - throw new CorruptedFrameException("length wider than 32-bit"); + if (in.readableBytes() < length) { + in.resetReaderIndex(); + return; + } else { + out.add(in.readBytes(length)); + return; + } + } + + /** + * Reads variable length 32bit int from buffer + * + * @return decoded int if buffers readerIndex has been forwarded else nonsense value + * @throws IOException + */ + private static int readRawVarint32(ByteBuf buffer) throws IOException { + if (!buffer.isReadable()) { + return 0; + } + buffer.markReaderIndex(); + byte tmp = buffer.readByte(); + if (tmp >= 0) { + return tmp; + } else { + int result = tmp & 127; + if (!buffer.isReadable()) { + buffer.resetReaderIndex(); + return 0; + } + if ((tmp = buffer.readByte()) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 127) << 7; + if (!buffer.isReadable()) { + buffer.resetReaderIndex(); + return 0; + } + if ((tmp = buffer.readByte()) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 127) << 14; + if (!buffer.isReadable()) { + buffer.resetReaderIndex(); + return 0; + } + if ((tmp = buffer.readByte()) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 127) << 21; + if (!buffer.isReadable()) { + buffer.resetReaderIndex(); + return 0; + } + result |= (tmp = buffer.readByte()) << 28; + if (tmp < 0) { + throw new CorruptedFrameException("malformed varint."); + } + } + } + } + return result; + } } } diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrepender.java b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrepender.java index 9efd00ff26..572359671e 100644 --- a/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrepender.java +++ b/codec/src/main/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrepender.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -15,9 +15,9 @@ */ package io.netty.handler.codec.protobuf; -import com.google.protobuf.CodedOutputStream; +import java.io.IOException; + import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; @@ -25,16 +25,16 @@ import io.netty.handler.codec.MessageToByteEncoder; /** * An encoder that prepends the the Google Protocol Buffers * Base - * 128 Varints integer length field. For example: + * 128 Varints integer length field. For example: *
- * BEFORE DECODE (300 bytes)       AFTER DECODE (302 bytes)
+ * BEFORE ENCODE (300 bytes)       AFTER ENCODE (302 bytes)
  * +---------------+               +--------+---------------+
  * | Protobuf Data |-------------->| Length | Protobuf Data |
  * |  (300 bytes)  |               | 0xAC02 |  (300 bytes)  |
  * +---------------+               +--------+---------------+
  * 
* * - * @see CodedOutputStream + * @see {@link CodedOutputStream} or (@link CodedOutputByteBufferNano) */ @Sharable public class ProtobufVarint32LengthFieldPrepender extends MessageToByteEncoder { @@ -43,14 +43,48 @@ public class ProtobufVarint32LengthFieldPrepender extends MessageToByteEncoder>>= 7; + } + } + } + + /** + * Computes size of protobuf varint32 after encoding. + * @param value which is to be encoded. + * @return size of value encoded as protobuf varint32. + */ + static int computeRawVarint32Size(final int value) { + if ((value & (0xffffffff << 7)) == 0) { + return 1; + } + if ((value & (0xffffffff << 14)) == 0) { + return 2; + } + if ((value & (0xffffffff << 21)) == 0) { + return 3; + } + if ((value & (0xffffffff << 28)) == 0) { + return 4; + } + return 5; + } } diff --git a/codec/src/main/java/io/netty/handler/codec/protobuf/package-info.java b/codec/src/main/java/io/netty/handler/codec/protobuf/package-info.java index 6d781c5be3..a1cb539d91 100644 --- a/codec/src/main/java/io/netty/handler/codec/protobuf/package-info.java +++ b/codec/src/main/java/io/netty/handler/codec/protobuf/package-info.java @@ -17,7 +17,7 @@ /** * Encoder and decoder which transform a * Google Protocol Buffers - * {@link com.google.protobuf.Message} into a {@link io.netty.buffer.ByteBuf} - * and vice versa. + * {@link com.google.protobuf.Message} and {@link com.google.protobuf.nano.MessageNano} into a + * {@link io.netty.buffer.ByteBuf} and vice versa. */ package io.netty.handler.codec.protobuf; diff --git a/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoderTest.java index 7de7ab7f50..7fa3352e7c 100644 --- a/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32FrameDecoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -38,14 +38,15 @@ public class ProtobufVarint32FrameDecoderTest { @Test public void testTinyDecode() { byte[] b = { 4, 1, 1, 1, 1 }; - ch.writeInbound(wrappedBuffer(b, 0, 1)); + assertFalse(ch.writeInbound(wrappedBuffer(b, 0, 1))); assertThat(ch.readInbound(), is(nullValue())); - ch.writeInbound(wrappedBuffer(b, 1, 2)); + assertFalse(ch.writeInbound(wrappedBuffer(b, 1, 2))); assertThat(ch.readInbound(), is(nullValue())); - ch.writeInbound(wrappedBuffer(b, 3, b.length - 3)); + assertTrue(ch.writeInbound(wrappedBuffer(b, 3, b.length - 3))); assertThat( releaseLater((ByteBuf) ch.readInbound()), is(releaseLater(wrappedBuffer(new byte[] { 1, 1, 1, 1 })))); + assertFalse(ch.finish()); } @Test @@ -56,11 +57,14 @@ public class ProtobufVarint32FrameDecoderTest { } b[0] = -2; b[1] = 15; - ch.writeInbound(wrappedBuffer(b, 0, 127)); + assertFalse(ch.writeInbound(wrappedBuffer(b, 0, 1))); assertThat(ch.readInbound(), is(nullValue())); - ch.writeInbound(wrappedBuffer(b, 127, 600)); + assertFalse(ch.writeInbound(wrappedBuffer(b, 1, 127))); assertThat(ch.readInbound(), is(nullValue())); - ch.writeInbound(wrappedBuffer(b, 727, b.length - 727)); + assertFalse(ch.writeInbound(wrappedBuffer(b, 127, 600))); + assertThat(ch.readInbound(), is(nullValue())); + assertTrue(ch.writeInbound(wrappedBuffer(b, 727, b.length - 727))); assertThat(releaseLater((ByteBuf) ch.readInbound()), is(releaseLater(wrappedBuffer(b, 2, b.length - 2)))); + assertFalse(ch.finish()); } } diff --git a/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrependerTest.java b/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrependerTest.java index d234a081e8..1fe9e86b2d 100644 --- a/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrependerTest.java +++ b/codec/src/test/java/io/netty/handler/codec/protobuf/ProtobufVarint32LengthFieldPrependerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Netty Project + * 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 @@ -34,11 +34,115 @@ public class ProtobufVarint32LengthFieldPrependerTest { ch = new EmbeddedChannel(new ProtobufVarint32LengthFieldPrepender()); } + @Test + public void testSize1Varint() { + final int size = 1; + final int num = 10; + assertThat(ProtobufVarint32LengthFieldPrepender.computeRawVarint32Size(num), is(size)); + final byte[] buf = new byte[size + num]; + //0000 1010 + buf[0] = 0x0A; + for (int i = size; i < num + size; ++i) { + buf[i] = 1; + } + assertTrue(ch.writeOutbound(wrappedBuffer(buf, size, buf.length - size))); + assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(buf)))); + assertFalse(ch.finish()); + } + + @Test + public void testSize2Varint() { + final int size = 2; + final int num = 266; + assertThat(ProtobufVarint32LengthFieldPrepender.computeRawVarint32Size(num), is(size)); + final byte[] buf = new byte[size + num]; + /** + * 8 A 0 2 + * 1000 1010 0000 0010 + * 0000 1010 0000 0010 + * 0000 0010 0000 1010 + * 000 0010 000 1010 + * + * 0000 0001 0000 1010 + * 0 1 0 A + * 266 + */ + + buf[0] = (byte) (0x8A & 0xFF); + buf[1] = 0x02; + for (int i = size; i < num + size; ++i) { + buf[i] = 1; + } + assertTrue(ch.writeOutbound(wrappedBuffer(buf, size, buf.length - size))); + assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(buf)))); + assertFalse(ch.finish()); + } + + @Test + public void testSize3Varint() { + final int size = 3; + final int num = 0x4000; + assertThat(ProtobufVarint32LengthFieldPrepender.computeRawVarint32Size(num), is(size)); + final byte[] buf = new byte[size + num]; + /** + * 8 0 8 0 0 1 + * 1000 0000 1000 0000 0000 0001 + * 0000 0000 0000 0000 0000 0001 + * 0000 0001 0000 0000 0000 0000 + * 000 0001 000 0000 000 0000 + * + * 0 0000 0100 0000 0000 0000 + * 0 0 4 0 0 0 + * + */ + + buf[0] = (byte) (0x80 & 0xFF); + buf[1] = (byte) (0x80 & 0xFF); + buf[2] = 0x01; + for (int i = size; i < num + size; ++i) { + buf[i] = 1; + } + assertTrue(ch.writeOutbound(wrappedBuffer(buf, size, buf.length - size))); + assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(buf)))); + assertFalse(ch.finish()); + } + + @Test + public void testSize4Varint() { + final int size = 4; + final int num = 0x200000; + assertThat(ProtobufVarint32LengthFieldPrepender.computeRawVarint32Size(num), is(size)); + final byte[] buf = new byte[size + num]; + /** + * 8 0 8 0 8 0 0 1 + * 1000 0000 1000 0000 1000 0000 0000 0001 + * 0000 0000 0000 0000 0000 0000 0000 0001 + * 0000 0001 0000 0000 0000 0000 0000 0000 + * 000 0001 000 0000 000 0000 000 0000 + * + * 0000 0010 0000 0000 0000 0000 0000 + * 0 2 0 0 0 0 0 + * + */ + + buf[0] = (byte) (0x80 & 0xFF); + buf[1] = (byte) (0x80 & 0xFF); + buf[2] = (byte) (0x80 & 0xFF); + buf[3] = 0x01; + for (int i = size; i < num + size; ++i) { + buf[i] = 1; + } + assertTrue(ch.writeOutbound(wrappedBuffer(buf, size, buf.length - size))); + assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(buf)))); + assertFalse(ch.finish()); + } + @Test public void testTinyEncode() { byte[] b = { 4, 1, 1, 1, 1 }; - ch.writeOutbound(wrappedBuffer(b, 1, b.length - 1)); + assertTrue(ch.writeOutbound(wrappedBuffer(b, 1, b.length - 1))); assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(b)))); + assertFalse(ch.finish()); } @Test @@ -49,7 +153,8 @@ public class ProtobufVarint32LengthFieldPrependerTest { } b[0] = -2; b[1] = 15; - ch.writeOutbound(wrappedBuffer(b, 2, b.length - 2)); + assertTrue(ch.writeOutbound(wrappedBuffer(b, 2, b.length - 2))); assertThat(releaseLater((ByteBuf) ch.readOutbound()), is(releaseLater(wrappedBuffer(b)))); + assertFalse(ch.finish()); } } diff --git a/license/LICENSE.protobuf.txt b/license/LICENSE.protobuf.txt index 705db579c9..0ab3bdb01a 100644 --- a/license/LICENSE.protobuf.txt +++ b/license/LICENSE.protobuf.txt @@ -1,5 +1,6 @@ -Copyright 2008, Google Inc. -All rights reserved. +Protocol Buffers - Google's data interchange format +Copyright 2013 Google Inc. All rights reserved. +https://developers.google.com/protocol-buffers/ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/pom.xml b/pom.xml index 6ec2f3c729..c8c131060b 100644 --- a/pom.xml +++ b/pom.xml @@ -288,6 +288,11 @@ protobuf-java 2.5.0 + + com.google.protobuf.nano + protobuf-javanano + 3.0.0-alpha-4 +