You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2017/12/01 21:11:54 UTC

[1/4] qpid-proton-j git commit: PROTON-1708 Optimizations for the EncoderImpl and DecoderImpl

Repository: qpid-proton-j
Updated Branches:
  refs/heads/master cb3b9f4d5 -> 2a2d3ff27


http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/PropertiesCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/PropertiesCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/PropertiesCodecTest.java
new file mode 100644
index 0000000..e6ef140
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/PropertiesCodecTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.messaging.Properties;
+import org.junit.Test;
+
+/**
+ * Test for decoder of AMQP Properties type.
+ */
+public class PropertiesCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfPropertiess() throws IOException {
+        doTestDecodePropertiesSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfPropertiess() throws IOException {
+        doTestDecodePropertiesSeries(LARGE_SIZE);
+    }
+
+    private void doTestDecodePropertiesSeries(int size) throws IOException {
+        Properties properties = new Properties();
+
+        Date timeNow = new Date(System.currentTimeMillis());
+
+        properties.setMessageId("ID:Message-1:1:1:0");
+        properties.setUserId(new Binary(new byte[1]));
+        properties.setTo("queue:work");
+        properties.setSubject("help");
+        properties.setReplyTo("queue:temp:me");
+        properties.setContentEncoding(Symbol.valueOf("text/UTF-8"));
+        properties.setContentType(Symbol.valueOf("text"));
+        properties.setCorrelationId("correlation-id");
+        properties.setAbsoluteExpiryTime(timeNow);
+        properties.setCreationTime(timeNow);
+        properties.setGroupId("group-1");
+        properties.setGroupSequence(UnsignedInteger.valueOf(1));
+        properties.setReplyToGroupId("group-1");
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(properties);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof Properties);
+
+            Properties decoded = (Properties) result;
+
+            assertNotNull(decoded.getAbsoluteExpiryTime());
+            assertEquals(timeNow, decoded.getAbsoluteExpiryTime());
+            assertEquals(Symbol.valueOf("text/UTF-8"), decoded.getContentEncoding());
+            assertEquals(Symbol.valueOf("text"), decoded.getContentType());
+            assertEquals("correlation-id", decoded.getCorrelationId());
+            assertEquals(timeNow, decoded.getCreationTime());
+            assertEquals("group-1", decoded.getGroupId());
+            assertEquals(UnsignedInteger.valueOf(1), decoded.getGroupSequence());
+            assertEquals("ID:Message-1:1:1:0", decoded.getMessageId());
+            assertEquals("queue:temp:me", decoded.getReplyTo());
+            assertEquals("group-1", decoded.getReplyToGroupId());
+            assertEquals("help", decoded.getSubject());
+            assertEquals("queue:work", decoded.getTo());
+            assertTrue(decoded.getUserId() instanceof Binary);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java
index 90cfe26..6c376d5 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java
@@ -125,6 +125,30 @@ public class StringTypeTest
         }
     }
 
+    @Test
+    public void testSkipString()
+    {
+        final DecoderImpl decoder = new DecoderImpl();
+        final EncoderImpl encoder = new EncoderImpl(decoder);
+        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
+        final ByteBuffer buffer = ByteBuffer.allocate(64);
+
+        decoder.setByteBuffer(buffer);
+        encoder.setByteBuffer(buffer);
+
+        encoder.writeString("skipped");
+        encoder.writeString("read");
+
+        buffer.clear();
+
+        TypeConstructor<?> stringType = decoder.readConstructor();
+        assertEquals(String.class, stringType.getTypeClass());
+        stringType.skipValue();
+
+        String result = decoder.readString();
+        assertEquals("read", result);
+    }
+
     // build up some test data with a set of suitable Unicode characters
     private static List<String> generateTestData()
     {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/TransferTypeTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/TransferTypeTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/TransferTypeTest.java
new file mode 100644
index 0000000..8e2d088
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/TransferTypeTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.*;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
+import org.apache.qpid.proton.amqp.transport.Transfer;
+import org.junit.Test;
+
+/**
+ * Tests for encode / decode of Transfer types
+ */
+public class TransferTypeTest extends CodecTestSupport {
+
+    @Test
+    public void testEncodeDecodeTransfers() {
+        Transfer transfer = new Transfer();
+        transfer.setHandle(UnsignedInteger.ONE);
+        transfer.setDeliveryTag(new Binary(new byte[] {0, 1}));
+        transfer.setMessageFormat(UnsignedInteger.ZERO);
+        transfer.setDeliveryId(UnsignedInteger.valueOf(127));
+        transfer.setAborted(false);
+        transfer.setBatchable(true);
+        transfer.setRcvSettleMode(ReceiverSettleMode.SECOND);
+
+        encoder.writeObject(transfer);
+        buffer.clear();
+        final Transfer outputValue = (Transfer) decoder.readObject();
+
+        assertEquals(transfer.getHandle(), outputValue.getHandle());
+        assertEquals(transfer.getMessageFormat(), outputValue.getMessageFormat());
+        assertEquals(transfer.getDeliveryTag(), outputValue.getDeliveryTag());
+        assertEquals(transfer.getDeliveryId(), outputValue.getDeliveryId());
+        assertEquals(transfer.getAborted(), outputValue.getAborted());
+        assertEquals(transfer.getBatchable(), outputValue.getBatchable());
+        assertEquals(transfer.getRcvSettleMode(), outputValue.getRcvSettleMode());
+    }
+
+    @Test
+    public void testSkipValue() {
+        Transfer transfer = new Transfer();
+        transfer.setHandle(UnsignedInteger.ONE);
+        transfer.setDeliveryTag(new Binary(new byte[] {0, 1}));
+        transfer.setMessageFormat(UnsignedInteger.ZERO);
+        transfer.setDeliveryId(UnsignedInteger.valueOf(127));
+        transfer.setAborted(false);
+        transfer.setBatchable(true);
+        transfer.setRcvSettleMode(ReceiverSettleMode.SECOND);
+
+        encoder.writeObject(transfer);
+
+        transfer.setHandle(UnsignedInteger.valueOf(2));
+
+        encoder.writeObject(transfer);
+
+        buffer.clear();
+
+        TypeConstructor<?> type = decoder.readConstructor();
+        assertEquals(Transfer.class, type.getTypeClass());
+        type.skipValue();
+
+        Transfer result = (Transfer) decoder.readObject();
+        assertEquals(UnsignedInteger.valueOf(2), result.getHandle());
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/UnknownDescribedTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/UnknownDescribedTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnknownDescribedTypeCodecTest.java
new file mode 100644
index 0000000..2aaaac6
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnknownDescribedTypeCodecTest.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.proton.amqp.DescribedType;
+import org.junit.Test;
+
+/**
+ * Tests the handling of UnknownDescribedType instances.
+ */
+public class UnknownDescribedTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeUnknownDescribedType() throws Exception {
+        encoder.writeObject(NoLocalType.NO_LOCAL);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertTrue(result instanceof DescribedType);
+        DescribedType resultTye = (DescribedType) result;
+        assertEquals(NoLocalType.NO_LOCAL.getDescriptor(), resultTye.getDescriptor());
+    }
+
+    @Test
+    public void testDecodeSmallSeriesOfUnknownDescribedTypes() throws IOException {
+        doTestDecodeUnknownDescribedTypeSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfUnknownDescribedTypes() throws IOException {
+        doTestDecodeUnknownDescribedTypeSeries(LARGE_SIZE);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testUnknownDescribedTypeInList() throws IOException {
+        List<Object> listOfUnkowns = new ArrayList<>();
+
+        listOfUnkowns.add(NoLocalType.NO_LOCAL);
+
+        encoder.writeList(listOfUnkowns);
+
+        buffer.clear();
+
+        final Object result = decoder.readObject();
+
+        assertNotNull(result);
+        assertTrue(result instanceof List);
+
+        final List<Object> decodedList = (List<Object>) result;
+        assertEquals(1, decodedList.size());
+
+        final Object listEntry = decodedList.get(0);
+        assertTrue(listEntry instanceof DescribedType);
+
+        DescribedType resultTye = (DescribedType) listEntry;
+        assertEquals(NoLocalType.NO_LOCAL.getDescriptor(), resultTye.getDescriptor());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testUnknownDescribedTypeInMap() throws IOException {
+        Map<Object, Object> mapOfUnknowns = new HashMap<>();
+
+        mapOfUnknowns.put(NoLocalType.NO_LOCAL.getDescriptor(), NoLocalType.NO_LOCAL);
+
+        encoder.writeMap(mapOfUnknowns);
+
+        buffer.clear();
+
+        final Object result = decoder.readObject();
+
+        assertNotNull(result);
+        assertTrue(result instanceof Map);
+
+        final Map<Object, Object> decodedMap = (Map<Object, Object>) result;
+        assertEquals(1, decodedMap.size());
+
+        final Object mapEntry = decodedMap.get(NoLocalType.NO_LOCAL.getDescriptor());
+        assertTrue(mapEntry instanceof DescribedType);
+
+        DescribedType resultTye = (DescribedType) mapEntry;
+        assertEquals(NoLocalType.NO_LOCAL.getDescriptor(), resultTye.getDescriptor());
+    }
+
+    private void doTestDecodeUnknownDescribedTypeSeries(int size) throws IOException {
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(NoLocalType.NO_LOCAL);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof DescribedType);
+
+            DescribedType resultTye = (DescribedType) result;
+            assertEquals(NoLocalType.NO_LOCAL.getDescriptor(), resultTye.getDescriptor());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java
index 45523e2..42b80cc 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java
@@ -22,6 +22,8 @@ package org.apache.qpid.proton.codec;
 
 import static org.junit.Assert.*;
 
+import java.nio.ByteBuffer;
+
 import org.apache.qpid.proton.amqp.UnsignedInteger;
 import org.apache.qpid.proton.codec.UnsignedIntegerType.UnsignedIntegerEncoding;
 import org.junit.Test;
@@ -63,4 +65,28 @@ public class UnsignedIntegerTypeTest
         UnsignedIntegerEncoding encoding = ult.getEncoding(UnsignedInteger.valueOf(val));
         assertEquals("incorrect encoding returned", EncodingCodes.UINT, encoding.getEncodingCode());
     }
+
+    @Test
+    public void testSkipValue()
+    {
+        final DecoderImpl decoder = new DecoderImpl();
+        final EncoderImpl encoder = new EncoderImpl(decoder);
+        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
+        final ByteBuffer buffer = ByteBuffer.allocate(64);
+
+        decoder.setByteBuffer(buffer);
+        encoder.setByteBuffer(buffer);
+
+        encoder.writeUnsignedInteger(UnsignedInteger.ZERO);
+        encoder.writeUnsignedInteger(UnsignedInteger.ONE);
+
+        buffer.clear();
+
+        TypeConstructor<?> type = decoder.readConstructor();
+        assertEquals(UnsignedInteger.class, type.getTypeClass());
+        type.skipValue();
+
+        UnsignedInteger result = decoder.readUnsignedInteger();
+        assertEquals(UnsignedInteger.ONE, result);
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java
index bcc6ff8..7b4cea3 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java
@@ -23,6 +23,7 @@ package org.apache.qpid.proton.codec;
 import static org.junit.Assert.*;
 
 import java.math.BigInteger;
+import java.nio.ByteBuffer;
 
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.codec.UnsignedLongType.UnsignedLongEncoding;
@@ -65,4 +66,28 @@ public class UnsignedLongTypeTest
         UnsignedLongEncoding encoding = ult.getEncoding(UnsignedLong.valueOf(bigInt));
         assertEquals("incorrect encoding returned", EncodingCodes.ULONG, encoding.getEncodingCode());
     }
+
+    @Test
+    public void testSkipValue()
+    {
+        final DecoderImpl decoder = new DecoderImpl();
+        final EncoderImpl encoder = new EncoderImpl(decoder);
+        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
+        final ByteBuffer buffer = ByteBuffer.allocate(64);
+
+        decoder.setByteBuffer(buffer);
+        encoder.setByteBuffer(buffer);
+
+        encoder.writeUnsignedLong(UnsignedLong.ZERO);
+        encoder.writeUnsignedLong(UnsignedLong.valueOf(1));
+
+        buffer.clear();
+
+        TypeConstructor<?> type = decoder.readConstructor();
+        assertEquals(UnsignedLong.class, type.getTypeClass());
+        type.skipValue();
+
+        UnsignedLong result = decoder.readUnsignedLong();
+        assertEquals(UnsignedLong.valueOf(1), result);
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[3/4] qpid-proton-j git commit: PROTON-1708 Optimizations for the EncoderImpl and DecoderImpl

Posted by ta...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/StringType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/StringType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/StringType.java
index a035e94..91476bc 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/StringType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/StringType.java
@@ -21,35 +21,34 @@
 package org.apache.qpid.proton.codec;
 
 import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.util.Arrays;
 import java.util.Collection;
 
 public class StringType extends AbstractPrimitiveType<String>
 {
-    private static final Charset Charset_UTF8 = Charset.forName("UTF-8");
     private static final DecoderImpl.TypeDecoder<String> _stringCreator =
-            new DecoderImpl.TypeDecoder<String>()
-            {
+        new DecoderImpl.TypeDecoder<String>()
+        {
 
-                public String decode(final ByteBuffer buf)
+            public String decode(DecoderImpl decoder, final ByteBuffer buf)
+            {
+                CharsetDecoder charsetDecoder = decoder.getCharsetDecoder();
+                try
                 {
-                    CharsetDecoder charsetDecoder = Charset_UTF8.newDecoder();
-                    try
-                    {
-                        CharBuffer charBuf = charsetDecoder.decode(buf);
-                        return charBuf.toString();
-                    }
-                    catch (CharacterCodingException e)
-                    {
-                        throw new IllegalArgumentException("Cannot parse String");
-                    }
-
+                    return decoder.getCharsetDecoder().decode(buf).toString();
+                }
+                catch (CharacterCodingException e)
+                {
+                    throw new IllegalArgumentException("Cannot parse String");
+                }
+                finally
+                {
+                    charsetDecoder.reset();
                 }
-            };
+            }
+        };
 
 
     public static interface StringEncoding extends PrimitiveTypeEncoding<String>
@@ -175,6 +174,13 @@ public class StringType extends AbstractPrimitiveType<String>
             _length = length;
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
     }
 
     private class ShortStringEncoding
@@ -233,6 +239,14 @@ public class StringType extends AbstractPrimitiveType<String>
             _value = val;
             _length = length;
         }
+
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = ((int)decoder.readRawByte()) & 0xff;
+            buffer.position(buffer.position() + size);
+        }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/SymbolType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/SymbolType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/SymbolType.java
index 4fb2038..e333e6a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/SymbolType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/SymbolType.java
@@ -39,10 +39,9 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
     private DecoderImpl.TypeDecoder<Symbol> _symbolCreator =
             new DecoderImpl.TypeDecoder<Symbol>()
             {
-
-                public Symbol decode(final ByteBuffer buf)
+                @Override
+                public Symbol decode(DecoderImpl decoder, ByteBuffer buf)
                 {
-
                     Symbol symbol = _symbolCache.get(buf);
                     if(symbol == null)
                     {
@@ -76,12 +75,27 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
         return Symbol.class;
     }
 
+    public void fastWrite(EncoderImpl encoder, Symbol symbol)
+    {
+        if (symbol.length() <= 255)
+        {
+            encoder.writeRaw(EncodingCodes.SYM8);
+            encoder.writeRaw((byte) symbol.length());
+            symbol.writeTo(encoder.getBuffer());
+        }
+        else
+        {
+            encoder.writeRaw(EncodingCodes.SYM32);
+            encoder.writeRaw(symbol.length());
+            symbol.writeTo(encoder.getBuffer());
+        }
+    }
+
     public SymbolEncoding getEncoding(final Symbol val)
     {
         return val.length() <= 255 ? _shortSymbolEncoding : _symbolEncoding;
     }
 
-
     public SymbolEncoding getCanonicalEncoding()
     {
         return _symbolEncoding;
@@ -105,13 +119,7 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
         @Override
         protected void writeEncodedValue(final Symbol val)
         {
-            final int length = val.length();
-            final EncoderImpl encoder = getEncoder();
-
-            for(int i = 0; i < length; i++)
-            {
-                encoder.writeRaw((byte)val.charAt(i));
-            }
+            val.writeTo(getEncoder().getBuffer());
         }
 
         @Override
@@ -143,8 +151,16 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
             int size = decoder.readRawInt();
             return decoder.readRaw(_symbolCreator, size);
         }
+
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
     }
-    
+
     private class ShortSymbolEncoding
             extends SmallFloatingSizePrimitiveTypeEncoding<Symbol>
             implements SymbolEncoding
@@ -158,14 +174,7 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
         @Override
         protected void writeEncodedValue(final Symbol val)
         {
-
-            final int length = val.length();
-            final EncoderImpl encoder = getEncoder();
-
-            for(int i = 0; i < length; i++)
-            {
-                encoder.writeRaw((byte)val.charAt(i));
-            }
+            val.writeTo(getEncoder().getBuffer());
         }
 
         @Override
@@ -197,5 +206,13 @@ public class SymbolType extends AbstractPrimitiveType<Symbol>
             int size = ((int)decoder.readRawByte()) & 0xff;
             return decoder.readRaw(_symbolCreator, size);
         }
+
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = ((int)decoder.readRawByte()) & 0xff;
+            buffer.position(buffer.position() + size);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/TimestampType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/TimestampType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/TimestampType.java
index 54baa25..c2efe08 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/TimestampType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/TimestampType.java
@@ -45,6 +45,11 @@ public class TimestampType extends AbstractPrimitiveType<Date>
         return _timestampEncoding;
     }
 
+    public void fastWrite(EncoderImpl encoder, long timestamp)
+    {
+        encoder.writeRaw(EncodingCodes.TIMESTAMP);
+        encoder.writeRaw(timestamp);
+    }
 
     public TimestampEncoding getCanonicalEncoding()
     {
@@ -60,7 +65,7 @@ public class TimestampType extends AbstractPrimitiveType<Date>
     {
         _timestampEncoding.write(l);
     }
-    
+
     private class TimestampEncoding extends FixedSizePrimitiveTypeEncoding<Date>
     {
 
@@ -90,12 +95,12 @@ public class TimestampType extends AbstractPrimitiveType<Date>
         {
             getEncoder().writeRaw(val.getTime());
         }
-        
+
         public void write(final long l)
         {
             writeConstructor();
             getEncoder().writeRaw(l);
-            
+
         }
 
         public boolean encodesSuperset(final TypeEncoding<Date> encoding)

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/TypeConstructor.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/TypeConstructor.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/TypeConstructor.java
index 7b3f3a0..a707209 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/TypeConstructor.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/TypeConstructor.java
@@ -24,6 +24,8 @@ public interface TypeConstructor<V>
 {
     V readValue();
 
+    void skipValue();
+
     boolean encodesJavaPrimitive();
 
     Class<V> getTypeClass();

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/UUIDType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/UUIDType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/UUIDType.java
index 20b9002..99f63f4 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/UUIDType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/UUIDType.java
@@ -45,6 +45,12 @@ public class UUIDType extends AbstractPrimitiveType<UUID>
         return _uuidEncoding;
     }
 
+    public void fastWrite(EncoderImpl encoder, UUID value)
+    {
+        encoder.writeRaw(EncodingCodes.UUID);
+        encoder.writeRaw(value.getMostSignificantBits());
+        encoder.writeRaw(value.getLeastSignificantBits());
+    }
 
     public UUIDEncoding getCanonicalEncoding()
     {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedByteType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedByteType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedByteType.java
index 781a9de..184d8be 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedByteType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedByteType.java
@@ -46,6 +46,11 @@ public class UnsignedByteType extends AbstractPrimitiveType<UnsignedByte>
         return _unsignedByteEncoding;
     }
 
+    public void fastWrite(EncoderImpl encoder, UnsignedByte value)
+    {
+        encoder.writeRaw(EncodingCodes.UBYTE);
+        encoder.writeRaw(value.byteValue());
+    }
 
     public UnsignedByteEncoding getCanonicalEncoding()
     {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedIntegerType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedIntegerType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedIntegerType.java
index 860e373..ce64484 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedIntegerType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedIntegerType.java
@@ -59,6 +59,24 @@ public class UnsignedIntegerType extends AbstractPrimitiveType<UnsignedInteger>
             : (i >= 0 && i <= 255) ? _smallUnsignedIntegerEncoding : _unsignedIntegerEncoding;
     }
 
+    public void fastWrite(EncoderImpl encoder, UnsignedInteger value)
+    {
+        int intValue = value.intValue();
+        if (intValue == 0)
+        {
+            encoder.writeRaw(EncodingCodes.UINT0);
+        }
+        else if (intValue > 0 && intValue <= 255)
+        {
+            encoder.writeRaw(EncodingCodes.SMALLUINT);
+            encoder.writeRaw((byte)intValue);
+        }
+        else
+        {
+            encoder.writeRaw(EncodingCodes.UINT);
+            encoder.writeRaw(intValue);
+        }
+    }
 
     public UnsignedIntegerEncoding getCanonicalEncoding()
     {
@@ -102,12 +120,12 @@ public class UnsignedIntegerType extends AbstractPrimitiveType<UnsignedInteger>
         {
             getEncoder().writeRaw(val.intValue());
         }
-        
+
         public void write(final int i)
         {
             writeConstructor();
             getEncoder().writeRaw(i);
-            
+
         }
 
         public boolean encodesSuperset(final TypeEncoding<UnsignedInteger> encoding)

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedLongType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedLongType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedLongType.java
index 4b7980e..715028a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedLongType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedLongType.java
@@ -35,8 +35,8 @@ public class UnsignedLongType extends AbstractPrimitiveType<UnsignedLong>
     private UnsignedLongEncoding _unsignedLongEncoding;
     private UnsignedLongEncoding _smallUnsignedLongEncoding;
     private UnsignedLongEncoding _zeroUnsignedLongEncoding;
-    
-    
+
+
     UnsignedLongType(final EncoderImpl encoder, final DecoderImpl decoder)
     {
         _unsignedLongEncoding = new AllUnsignedLongEncoding(encoder, decoder);
@@ -59,6 +59,24 @@ public class UnsignedLongType extends AbstractPrimitiveType<UnsignedLong>
             : (l >= 0 && l <= 255L) ? _smallUnsignedLongEncoding : _unsignedLongEncoding;
     }
 
+    public void fastWrite(EncoderImpl encoder, UnsignedLong value)
+    {
+        long longValue = value.longValue();
+        if (longValue == 0)
+        {
+            encoder.writeRaw(EncodingCodes.ULONG0);
+        }
+        else if (longValue > 0 && longValue <= 255)
+        {
+            encoder.writeRaw(EncodingCodes.SMALLULONG);
+            encoder.writeRaw((byte)longValue);
+        }
+        else
+        {
+            encoder.writeRaw(EncodingCodes.ULONG);
+            encoder.writeRaw(longValue);
+        }
+    }
 
     public UnsignedLongEncoding getCanonicalEncoding()
     {
@@ -157,8 +175,8 @@ public class UnsignedLongType extends AbstractPrimitiveType<UnsignedLong>
             return UnsignedLong.valueOf(((long)getDecoder().readRawByte())&0xffl);
         }
     }
-    
-    
+
+
     private class ZeroUnsignedLongEncoding
             extends FixedSizePrimitiveTypeEncoding<UnsignedLong>
             implements UnsignedLongEncoding

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedShortType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedShortType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedShortType.java
index 378c207..a30ee46 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedShortType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/UnsignedShortType.java
@@ -46,6 +46,11 @@ public class UnsignedShortType extends AbstractPrimitiveType<UnsignedShort>
         return _unsignedShortEncoder;
     }
 
+    public void fastWrite(EncoderImpl encoder, UnsignedShort value)
+    {
+        encoder.writeRaw(EncodingCodes.USHORT);
+        encoder.writeRaw(value.shortValue());
+    }
 
     public UnsignedShortEncoding getCanonicalEncoding()
     {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AcceptedType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AcceptedType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AcceptedType.java
index 2da2d2b..32db983 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AcceptedType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AcceptedType.java
@@ -41,7 +41,7 @@ public final class AcceptedType extends AbstractDescribedType<Accepted,List> imp
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000024L);
 
 
-    private AcceptedType(EncoderImpl encoder)
+    AcceptedType(EncoderImpl encoder)
     {
         super(encoder);
     }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpSequenceType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpSequenceType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpSequenceType.java
index 8844893..054d34d 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpSequenceType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpSequenceType.java
@@ -42,7 +42,7 @@ public class AmqpSequenceType extends AbstractDescribedType<AmqpSequence,List> i
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000076L);
 
-    private AmqpSequenceType(EncoderImpl encoder)
+    AmqpSequenceType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -68,7 +68,7 @@ public class AmqpSequenceType extends AbstractDescribedType<AmqpSequence,List> i
         return AmqpSequence.class;
     }
 
-      
+
 
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
@@ -80,4 +80,3 @@ public class AmqpSequenceType extends AbstractDescribedType<AmqpSequence,List> i
         encoder.register(type);
     }
 }
-  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpValueType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpValueType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpValueType.java
index d2dc8e1..9af847a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpValueType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/AmqpValueType.java
@@ -42,7 +42,7 @@ public class AmqpValueType extends AbstractDescribedType<AmqpValue,Object> imple
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000077L);
 
-    private AmqpValueType(EncoderImpl encoder)
+    AmqpValueType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -68,7 +68,7 @@ public class AmqpValueType extends AbstractDescribedType<AmqpValue,Object> imple
         return AmqpValue.class;
     }
 
-      
+
 
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
@@ -80,4 +80,3 @@ public class AmqpValueType extends AbstractDescribedType<AmqpValue,Object> imple
         encoder.register(type);
     }
 }
-  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/DataType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/DataType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/DataType.java
index d7435c2..9ab06c0 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/DataType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/DataType.java
@@ -43,7 +43,7 @@ public class DataType extends AbstractDescribedType<Data,Binary> implements Desc
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000075L);
 
-    private DataType(EncoderImpl encoder)
+    DataType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -69,7 +69,7 @@ public class DataType extends AbstractDescribedType<Data,Binary> implements Desc
         return Data.class;
     }
 
-      
+
 
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
@@ -81,4 +81,3 @@ public class DataType extends AbstractDescribedType<Data,Binary> implements Desc
         encoder.register(type);
     }
 }
-  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAcceptedType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAcceptedType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAcceptedType.java
new file mode 100644
index 0000000..3624836
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAcceptedType.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Accepted;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathAcceptedType implements AMQPType<Accepted>, FastPathDescribedTypeConstructor<Accepted> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000024L), Symbol.valueOf("amqp:accepted:list"),
+    };
+
+    private final AcceptedType acceptedType;
+
+    public FastPathAcceptedType(EncoderImpl encoder) {
+        this.acceptedType = new AcceptedType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return acceptedType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return acceptedType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Accepted> getTypeClass() {
+        return Accepted.class;
+    }
+
+    @Override
+    public TypeEncoding<Accepted> getEncoding(Accepted accepted) {
+        return acceptedType.getEncoding(accepted);
+    }
+
+    @Override
+    public TypeEncoding<Accepted> getCanonicalEncoding() {
+        return acceptedType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Accepted>> getAllEncodings() {
+        return acceptedType.getAllEncodings();
+    }
+
+    @Override
+    public Accepted readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                break;
+            case EncodingCodes.LIST8:
+                decoder.getByteBuffer().get();
+                decoder.getByteBuffer().get();
+                break;
+            case EncodingCodes.LIST32:
+                decoder.getByteBuffer().getInt();
+                decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Accepted type encoding: " + typeCode);
+        }
+
+        return Accepted.getInstance();
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(Accepted accepted) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(acceptedType.getDescriptor());
+        buffer.put(EncodingCodes.LIST0);
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathAcceptedType type = new FastPathAcceptedType(encoder);
+        for(Object descriptor : DESCRIPTORS) {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpSequenceType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpSequenceType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpSequenceType.java
new file mode 100644
index 0000000..611ec10
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpSequenceType.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathAmqpSequenceType implements AMQPType<AmqpSequence>, FastPathDescribedTypeConstructor<AmqpSequence> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000076L), Symbol.valueOf("amqp:amqp-sequence:list"),
+    };
+
+    private final AmqpSequenceType sequenceType;
+
+    public FastPathAmqpSequenceType(EncoderImpl encoder) {
+        this.sequenceType = new AmqpSequenceType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return sequenceType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return sequenceType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<AmqpSequence> getTypeClass() {
+        return AmqpSequence.class;
+    }
+
+    @Override
+    public TypeEncoding<AmqpSequence> getEncoding(AmqpSequence val) {
+        return sequenceType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<AmqpSequence> getCanonicalEncoding() {
+        return sequenceType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<AmqpSequence>> getAllEncodings() {
+        return sequenceType.getAllEncodings();
+    }
+
+    @Override
+    public AmqpSequence readValue() {
+        return new AmqpSequence(getDecoder().readList());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(AmqpSequence sequence) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(sequenceType.getDescriptor());
+        getEncoder().writeObject(sequence.getValue());
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathAmqpSequenceType type = new FastPathAmqpSequenceType(encoder);
+        for (Object descriptor : DESCRIPTORS) {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpValueType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpValueType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpValueType.java
new file mode 100644
index 0000000..7120481
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathAmqpValueType.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.AmqpValue;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathAmqpValueType implements AMQPType<AmqpValue>, FastPathDescribedTypeConstructor<AmqpValue> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000077L), Symbol.valueOf("amqp:amqp-value:*"),
+    };
+
+    private final AmqpValueType valueType;
+
+    public FastPathAmqpValueType(EncoderImpl encoder) {
+        this.valueType = new AmqpValueType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return valueType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return valueType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<AmqpValue> getTypeClass() {
+        return AmqpValue.class;
+    }
+
+    @Override
+    public TypeEncoding<AmqpValue> getEncoding(AmqpValue value) {
+        return valueType.getEncoding(value);
+    }
+
+    @Override
+    public TypeEncoding<AmqpValue> getCanonicalEncoding() {
+        return valueType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<AmqpValue>> getAllEncodings() {
+        return valueType.getAllEncodings();
+    }
+
+    @Override
+    public AmqpValue readValue() {
+        return new AmqpValue(getDecoder().readObject());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(AmqpValue value) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(valueType.getDescriptor());
+        getEncoder().writeObject(value.getValue());
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathAmqpValueType type = new FastPathAmqpValueType(encoder);
+        for(Object descriptor : DESCRIPTORS) {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
new file mode 100644
index 0000000..4eed5e7
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathApplicationPropertiesType.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathApplicationPropertiesType implements AMQPType<ApplicationProperties>, FastPathDescribedTypeConstructor<ApplicationProperties> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000074L), Symbol.valueOf("amqp:application-properties:map"),
+    };
+
+    private final ApplicationPropertiesType propertiesType;
+
+    public FastPathApplicationPropertiesType(EncoderImpl encoder) {
+        this.propertiesType = new ApplicationPropertiesType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return propertiesType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return propertiesType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<ApplicationProperties> getTypeClass() {
+        return ApplicationProperties.class;
+    }
+
+    @Override
+    public TypeEncoding<ApplicationProperties> getEncoding(ApplicationProperties val) {
+        return propertiesType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<ApplicationProperties> getCanonicalEncoding() {
+        return propertiesType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<ApplicationProperties>> getAllEncodings() {
+        return propertiesType.getAllEncodings();
+    }
+
+    @Override
+    public ApplicationProperties readValue() {
+        return new ApplicationProperties(getDecoder().readMap());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(ApplicationProperties val) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(propertiesType.getDescriptor());
+
+        MapType mapType = (MapType) getEncoder().getType(val.getValue());
+
+        mapType.setKeyEncoding(getEncoder().getTypeFromClass(String.class));
+        mapType.write(val.getValue());
+        mapType.setKeyEncoding(null);
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathApplicationPropertiesType type = new FastPathApplicationPropertiesType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
new file mode 100644
index 0000000..75a7543
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDataType.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Data;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathDataType implements AMQPType<Data>, FastPathDescribedTypeConstructor<Data> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000075L), Symbol.valueOf("amqp:data:binary"),
+    };
+
+    private final DataType dataType;
+
+    public FastPathDataType(EncoderImpl encoder) {
+        this.dataType = new DataType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return dataType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return dataType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Data> getTypeClass() {
+        return dataType.getTypeClass();
+    }
+
+    @Override
+    public TypeEncoding<Data> getEncoding(Data val) {
+        return dataType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<Data> getCanonicalEncoding() {
+        return dataType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Data>> getAllEncodings() {
+        return dataType.getAllEncodings();
+    }
+
+    @Override
+    public Data readValue() {
+        return new Data(getDecoder().readBinary());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(Data data) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(dataType.getDescriptor());
+        getEncoder().writeBinary(data.getValue());
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathDataType type = new FastPathDataType(encoder);
+        for(Object descriptor : DESCRIPTORS) {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
new file mode 100644
index 0000000..4252393
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathDeliveryAnnotationsType.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.DeliveryAnnotations;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathDeliveryAnnotationsType implements AMQPType<DeliveryAnnotations>, FastPathDescribedTypeConstructor<DeliveryAnnotations> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000071L), Symbol.valueOf("amqp:delivery-annotations:map"),
+    };
+
+    private final DeliveryAnnotationsType annotationsType;
+
+    public FastPathDeliveryAnnotationsType(EncoderImpl encoder) {
+        this.annotationsType = new DeliveryAnnotationsType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return annotationsType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return annotationsType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<DeliveryAnnotations> getTypeClass() {
+        return DeliveryAnnotations.class;
+    }
+
+    @Override
+    public TypeEncoding<DeliveryAnnotations> getEncoding(DeliveryAnnotations val) {
+        return annotationsType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<DeliveryAnnotations> getCanonicalEncoding() {
+        return annotationsType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<DeliveryAnnotations>> getAllEncodings() {
+        return annotationsType.getAllEncodings();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public DeliveryAnnotations readValue() {
+        return new DeliveryAnnotations(getDecoder().readMap());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(DeliveryAnnotations val) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(annotationsType.getDescriptor());
+
+        MapType mapType = (MapType) getEncoder().getType(val.getValue());
+
+        mapType.setKeyEncoding(getEncoder().getTypeFromClass(Symbol.class));
+        mapType.write(val.getValue());
+        mapType.setKeyEncoding(null);
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathDeliveryAnnotationsType type = new FastPathDeliveryAnnotationsType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathFooterType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathFooterType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathFooterType.java
new file mode 100644
index 0000000..d1b0d40
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathFooterType.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Footer;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathFooterType implements AMQPType<Footer>, FastPathDescribedTypeConstructor<Footer> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000078L), Symbol.valueOf("amqp:footer:map"),
+    };
+
+    private final FooterType footerType;
+
+    public FastPathFooterType(EncoderImpl encoder) {
+        this.footerType = new FooterType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return footerType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return footerType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Footer> getTypeClass() {
+        return Footer.class;
+    }
+
+    @Override
+    public TypeEncoding<Footer> getEncoding(Footer val) {
+        return footerType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<Footer> getCanonicalEncoding() {
+        return footerType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Footer>> getAllEncodings() {
+        return footerType.getAllEncodings();
+    }
+
+    @Override
+    public Footer readValue() {
+        return new Footer(getDecoder().readMap());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(Footer val) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(footerType.getDescriptor());
+
+        MapType mapType = (MapType) getEncoder().getType(val.getValue());
+
+        mapType.write(val.getValue());
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathFooterType type = new FastPathFooterType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathHeaderType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathHeaderType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathHeaderType.java
new file mode 100644
index 0000000..11c5223
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathHeaderType.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Header;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathHeaderType implements AMQPType<Header>, FastPathDescribedTypeConstructor<Header> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000070L), Symbol.valueOf("amqp:header:list"),
+    };
+
+    private final HeaderType headerType;
+
+    public FastPathHeaderType(EncoderImpl encoder) {
+        this.headerType = new HeaderType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return headerType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return headerType.getDecoder();
+    }
+
+    @Override
+    public Header readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        @SuppressWarnings("unused")
+        int size = 0;
+        int count = 0;
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                break;
+            case EncodingCodes.LIST8:
+                size = ((int)decoder.getByteBuffer().get()) & 0xff;
+                count = ((int)decoder.getByteBuffer().get()) & 0xff;
+                break;
+            case EncodingCodes.LIST32:
+                size = decoder.getByteBuffer().getInt();
+                count = decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Transfer encoding: " + typeCode);
+        }
+
+        Header header = new Header();
+
+        for (int index = 0; index < count; ++index) {
+            switch (index) {
+                case 0:
+                    header.setDurable(decoder.readBoolean());
+                    break;
+                case 1:
+                    header.setPriority(decoder.readUnsignedByte());
+                    break;
+                case 2:
+                    header.setTtl(decoder.readUnsignedInteger());
+                    break;
+                case 3:
+                    header.setFirstAcquirer(decoder.readBoolean());
+                    break;
+                case 4:
+                    header.setDeliveryCount(decoder.readUnsignedInteger());
+                    break;
+                default:
+                    throw new IllegalStateException("To many entries in Header encoding");
+            }
+        }
+
+        return header;
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Header> getTypeClass() {
+        return Header.class;
+    }
+
+    @Override
+    public TypeEncoding<Header> getEncoding(Header header) {
+        return headerType.getEncoding(header);
+    }
+
+    @Override
+    public TypeEncoding<Header> getCanonicalEncoding() {
+        return headerType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Header>> getAllEncodings() {
+        return headerType.getAllEncodings();
+    }
+
+    @Override
+    public void write(Header value) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        int count = getElementCount(value);
+        byte encodingCode = deduceEncodingCode(value, count);
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(headerType.getDescriptor());
+
+        // Optimized step, no other data to be written.
+        if (count == 0 || encodingCode == EncodingCodes.LIST0) {
+            buffer.put(EncodingCodes.LIST0);
+            return;
+        }
+
+        final int fieldWidth;
+
+        if (encodingCode == EncodingCodes.LIST8) {
+            fieldWidth = 1;
+            buffer.put(EncodingCodes.LIST8);
+        } else {
+            fieldWidth = 4;
+            buffer.put(EncodingCodes.LIST32);
+        }
+
+        int startIndex = buffer.position();
+
+        // Reserve space for the size and write the count of list elements.
+        if (fieldWidth == 1) {
+            buffer.put((byte) 0);
+            buffer.put((byte) count);
+        } else {
+            buffer.putInt(0);
+            buffer.putInt(count);
+        }
+
+        // Write the list elements and then compute total size written.
+        for (int i = 0; i < count; ++i) {
+            writeElement(value, i);
+        }
+
+        // Move back and write the size
+        int endIndex = buffer.position();
+        int writeSize = endIndex - startIndex - fieldWidth;
+
+        buffer.position(startIndex);
+        if (fieldWidth == 1) {
+            buffer.put((byte) writeSize);
+        } else {
+            buffer.putInt(writeSize);
+        }
+        buffer.position(endIndex);
+    }
+
+    private void writeElement(Header header, int index) {
+        switch (index) {
+            case 0:
+                getEncoder().writeBoolean(header.getDurable());
+                break;
+            case 1:
+                getEncoder().writeUnsignedByte(header.getPriority());
+                break;
+            case 2:
+                getEncoder().writeUnsignedInteger(header.getTtl());
+                break;
+            case 3:
+                getEncoder().writeBoolean(header.getFirstAcquirer());
+                break;
+            case 4:
+                getEncoder().writeUnsignedInteger(header.getDeliveryCount());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown Header value index: " + index);
+        }
+    }
+
+    private int getElementCount(Header header) {
+        if (header.getDeliveryCount() != null) {
+            return 5;
+        } else if (header.getFirstAcquirer() != null) {
+            return 4;
+        } else if (header.getTtl() != null) {
+            return 3;
+        } else if (header.getPriority() != null) {
+            return 2;
+        } else if (header.getDurable() != null) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
+    private byte deduceEncodingCode(Header value, int elementCount) {
+        if (elementCount == 0) {
+            return EncodingCodes.LIST0;
+        } else {
+            return EncodingCodes.LIST8;
+        }
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathHeaderType type = new FastPathHeaderType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
new file mode 100644
index 0000000..6d32004
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathMessageAnnotationsType.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.MapType;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathMessageAnnotationsType implements AMQPType<MessageAnnotations>, FastPathDescribedTypeConstructor<MessageAnnotations> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000072L), Symbol.valueOf("amqp:message-annotations:map"),
+    };
+
+    private final MessageAnnotationsType annotationsType;
+
+    public FastPathMessageAnnotationsType(EncoderImpl encoder) {
+        this.annotationsType = new MessageAnnotationsType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return annotationsType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return annotationsType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<MessageAnnotations> getTypeClass() {
+        return MessageAnnotations.class;
+    }
+
+    @Override
+    public TypeEncoding<MessageAnnotations> getEncoding(MessageAnnotations val) {
+        return annotationsType.getEncoding(val);
+    }
+
+    @Override
+    public TypeEncoding<MessageAnnotations> getCanonicalEncoding() {
+        return annotationsType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<MessageAnnotations>> getAllEncodings() {
+        return annotationsType.getAllEncodings();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public MessageAnnotations readValue() {
+        return new MessageAnnotations(getDecoder().readMap());
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(MessageAnnotations val) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(annotationsType.getDescriptor());
+
+        MapType mapType = (MapType) getEncoder().getType(val.getValue());
+
+        mapType.setKeyEncoding(getEncoder().getTypeFromClass(Symbol.class));
+        mapType.write(val.getValue());
+        mapType.setKeyEncoding(null);
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathMessageAnnotationsType type = new FastPathMessageAnnotationsType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathPropertiesType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathPropertiesType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathPropertiesType.java
new file mode 100644
index 0000000..d689747
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FastPathPropertiesType.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.messaging;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Properties;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathPropertiesType implements AMQPType<Properties>, FastPathDescribedTypeConstructor<Properties> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000073L), Symbol.valueOf("amqp:properties:list"),
+    };
+
+    private final PropertiesType propertiesType;
+
+    public FastPathPropertiesType(EncoderImpl encoder) {
+        this.propertiesType = new PropertiesType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return propertiesType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return propertiesType.getDecoder();
+    }
+
+    @Override
+    public Properties readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        @SuppressWarnings("unused")
+        int size = 0;
+        int count = 0;
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                break;
+            case EncodingCodes.LIST8:
+                size = ((int)decoder.getByteBuffer().get()) & 0xff;
+                count = ((int)decoder.getByteBuffer().get()) & 0xff;
+                break;
+            case EncodingCodes.LIST32:
+                size = decoder.getByteBuffer().getInt();
+                count = decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Transfer encoding: " + typeCode);
+        }
+
+        Properties properties = new Properties();
+
+        for (int index = 0; index < count; ++index) {
+            switch (index) {
+                case 0:
+                    properties.setMessageId(decoder.readObject());
+                    break;
+                case 1:
+                    properties.setUserId(decoder.readBinary());
+                    break;
+                case 2:
+                    properties.setTo(decoder.readString());
+                    break;
+                case 3:
+                    properties.setSubject(decoder.readString());
+                    break;
+                case 4:
+                    properties.setReplyTo(decoder.readString());
+                    break;
+                case 5:
+                    properties.setCorrelationId(decoder.readObject());
+                    break;
+                case 6:
+                    properties.setContentType(decoder.readSymbol());
+                    break;
+                case 7:
+                    properties.setContentEncoding(decoder.readSymbol());
+                    break;
+                case 8:
+                    properties.setAbsoluteExpiryTime(decoder.readTimestamp());
+                    break;
+                case 9:
+                    properties.setCreationTime(decoder.readTimestamp());
+                    break;
+                case 10:
+                    properties.setGroupId(decoder.readString());
+                    break;
+                case 11:
+                    properties.setGroupSequence(decoder.readUnsignedInteger());
+                    break;
+                case 12:
+                    properties.setReplyToGroupId(decoder.readString());
+                    break;
+                default:
+                    throw new IllegalStateException("To many entries in Properties encoding");
+            }
+        }
+
+        return properties;
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Properties> getTypeClass() {
+        return Properties.class;
+    }
+
+    @Override
+    public TypeEncoding<Properties> getEncoding(Properties properties) {
+        return propertiesType.getEncoding(properties);
+    }
+
+    @Override
+    public TypeEncoding<Properties> getCanonicalEncoding() {
+        return propertiesType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Properties>> getAllEncodings() {
+        return propertiesType.getAllEncodings();
+    }
+
+    @Override
+    public void write(Properties value) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        int count = getElementCount(value);
+        byte encodingCode = deduceEncodingCode(value, count);
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(propertiesType.getDescriptor());
+
+        // Optimized step, no other data to be written.
+        if (count == 0 || encodingCode == EncodingCodes.LIST0) {
+            buffer.put(EncodingCodes.LIST0);
+            return;
+        }
+
+        final int fieldWidth;
+
+        if (encodingCode == EncodingCodes.LIST8) {
+            fieldWidth = 1;
+            buffer.put(EncodingCodes.LIST8);
+        } else {
+            fieldWidth = 4;
+            buffer.put(EncodingCodes.LIST32);
+        }
+
+        int startIndex = buffer.position();
+
+        // Reserve space for the size and write the count of list elements.
+        if (fieldWidth == 1) {
+            buffer.put((byte) 0);
+            buffer.put((byte) count);
+        } else {
+            buffer.putInt(0);
+            buffer.putInt(count);
+        }
+
+        // Write the list elements and then compute total size written.
+        for (int i = 0; i < count; ++i) {
+            writeElement(value, i);
+        }
+
+        // Move back and write the size
+        int endIndex = buffer.position();
+        int writeSize = endIndex - startIndex - fieldWidth;
+
+        buffer.position(startIndex);
+        if (fieldWidth == 1) {
+            buffer.put((byte) writeSize);
+        } else {
+            buffer.putInt(writeSize);
+        }
+        buffer.position(endIndex);
+    }
+
+    private byte deduceEncodingCode(Properties value, int elementCount) {
+        if (elementCount == 0) {
+            return EncodingCodes.LIST0;
+        } else {
+            return EncodingCodes.LIST32;
+        }
+    }
+
+    private void writeElement(Properties properties, int index) {
+        switch (index) {
+            case 0:
+                getEncoder().writeObject(properties.getMessageId());
+                break;
+            case 1:
+                getEncoder().writeBinary(properties.getUserId());
+                break;
+            case 2:
+                getEncoder().writeString(properties.getTo());
+                break;
+            case 3:
+                getEncoder().writeString(properties.getSubject());
+                break;
+            case 4:
+                getEncoder().writeString(properties.getReplyTo());
+                break;
+            case 5:
+                getEncoder().writeObject(properties.getCorrelationId());
+                break;
+            case 6:
+                getEncoder().writeSymbol(properties.getContentType());
+                break;
+            case 7:
+                getEncoder().writeSymbol(properties.getContentEncoding());
+                break;
+            case 8:
+                getEncoder().writeTimestamp(properties.getAbsoluteExpiryTime());
+                break;
+            case 9:
+                getEncoder().writeTimestamp(properties.getCreationTime());
+                break;
+            case 10:
+                getEncoder().writeString(properties.getGroupId());
+                break;
+            case 11:
+                getEncoder().writeUnsignedInteger(properties.getGroupSequence());
+                break;
+            case 12:
+                getEncoder().writeString(properties.getReplyToGroupId());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown Properties value index: " + index);
+        }
+    }
+
+    private int getElementCount(Properties properties) {
+        if (properties.getReplyToGroupId() != null) {
+            return 13;
+        } else if (properties.getGroupSequence() != null) {
+            return 12;
+        } else if (properties.getGroupId() != null) {
+            return 11;
+        } else if (properties.getCreationTime() != null) {
+            return 10;
+        } else if (properties.getAbsoluteExpiryTime() != null) {
+            return 9;
+        } else if (properties.getContentEncoding() != null) {
+            return 8;
+        } else if (properties.getContentType() != null) {
+            return 7;
+        } else if (properties.getCorrelationId() != null) {
+            return 6;
+        } else if (properties.getReplyTo() != null) {
+            return 5;
+        } else if (properties.getSubject() != null) {
+            return 4;
+        } else if (properties.getTo() != null) {
+            return 3;
+        } else if (properties.getUserId() != null) {
+            return 2;
+        } else if (properties.getMessageId() != null) {
+            return 1;
+        }
+
+        return 0;
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathPropertiesType type = new FastPathPropertiesType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java
index b7f5a43..310bce1 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java
@@ -35,7 +35,6 @@ import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DescribedTypeConstructor;
 import org.apache.qpid.proton.codec.EncoderImpl;
 
-
 public class HeaderType extends AbstractDescribedType<Header,List> implements DescribedTypeConstructor<Header>
 {
     private static final Object[] DESCRIPTORS =
@@ -154,5 +153,4 @@ public class HeaderType extends AbstractDescribedType<Header,List> implements De
         }
         encoder.register(type);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java
index 818aaa8..98c4431 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java
@@ -36,7 +36,6 @@ import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DescribedTypeConstructor;
 import org.apache.qpid.proton.codec.EncoderImpl;
 
-
 public class PropertiesType  extends AbstractDescribedType<Properties,List> implements DescribedTypeConstructor<Properties>
 {
     private static final Object[] DESCRIPTORS =
@@ -46,7 +45,7 @@ public class PropertiesType  extends AbstractDescribedType<Properties,List> impl
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000073L);
 
-    private PropertiesType(EncoderImpl encoder)
+    PropertiesType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -190,8 +189,6 @@ public class PropertiesType  extends AbstractDescribedType<Properties,List> impl
             return Properties.class;
         }
 
-
-
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
         PropertiesType type = new PropertiesType(encoder);
@@ -201,5 +198,4 @@ public class PropertiesType  extends AbstractDescribedType<Properties,List> impl
         }
         encoder.register(type);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java
index b833613..44a6202 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java
@@ -47,7 +47,7 @@ public final class DispositionType extends AbstractDescribedType<Disposition,Lis
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000015L);
 
-    private DispositionType(EncoderImpl encoder)
+    DispositionType(EncoderImpl encoder)
     {
         super(encoder);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[2/4] qpid-proton-j git commit: PROTON-1708 Optimizations for the EncoderImpl and DecoderImpl

Posted by ta...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathDispositionType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathDispositionType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathDispositionType.java
new file mode 100644
index 0000000..01e18e7
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathDispositionType.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.transport;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.messaging.Accepted;
+import org.apache.qpid.proton.amqp.messaging.Released;
+import org.apache.qpid.proton.amqp.transport.DeliveryState;
+import org.apache.qpid.proton.amqp.transport.Disposition;
+import org.apache.qpid.proton.amqp.transport.Role;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathDispositionType implements AMQPType<Disposition>, FastPathDescribedTypeConstructor<Disposition> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000015L), Symbol.valueOf("amqp:disposition:list"),
+    };
+
+    private final DispositionType dispositionType;
+
+    public FastPathDispositionType(EncoderImpl encoder) {
+        this.dispositionType = new DispositionType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return dispositionType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return dispositionType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Disposition> getTypeClass() {
+        return Disposition.class;
+    }
+
+    @Override
+    public TypeEncoding<Disposition> getEncoding(Disposition disposition) {
+        return dispositionType.getEncoding(disposition);
+    }
+
+    @Override
+    public TypeEncoding<Disposition> getCanonicalEncoding() {
+        return dispositionType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Disposition>> getAllEncodings() {
+        return dispositionType.getAllEncodings();
+    }
+
+    @Override
+    public Disposition readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        @SuppressWarnings("unused")
+        int size = 0;
+        int count = 0;
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                // TODO - Technically invalid however old decoder also allowed this.
+                break;
+            case EncodingCodes.LIST8:
+                size = ((int)decoder.getByteBuffer().get()) & 0xff;
+                count = ((int)decoder.getByteBuffer().get()) & 0xff;
+                break;
+            case EncodingCodes.LIST32:
+                size = decoder.getByteBuffer().getInt();
+                count = decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Disposition encoding: " + typeCode);
+        }
+
+        Disposition disposition = new Disposition();
+
+        for (int index = 0; index < count; ++index) {
+            switch (index) {
+                case 0:
+                    disposition.setRole(Boolean.TRUE.equals(decoder.readBoolean()) ? Role.RECEIVER : Role.SENDER);
+                    break;
+                case 1:
+                    disposition.setFirst(decoder.readUnsignedInteger());
+                    break;
+                case 2:
+                    disposition.setLast(decoder.readUnsignedInteger());
+                    break;
+                case 3:
+                    disposition.setSettled(decoder.readBoolean(false));
+                    break;
+                case 4:
+                    disposition.setState((DeliveryState) decoder.readObject());
+                    break;
+                case 5:
+                    disposition.setBatchable(decoder.readBoolean(false));
+                    break;
+                default:
+                    throw new IllegalStateException("To many entries in Disposition encoding");
+            }
+        }
+
+        return disposition;
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(Disposition disposition) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        int count = getElementCount(disposition);
+        byte encodingCode = deduceEncodingCode(disposition, count);
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(dispositionType.getDescriptor());
+
+        final int fieldWidth;
+
+        if (encodingCode == EncodingCodes.LIST8) {
+            fieldWidth = 1;
+            buffer.put(EncodingCodes.LIST8);
+        } else {
+            fieldWidth = 4;
+            buffer.put(EncodingCodes.LIST32);
+        }
+
+        int startIndex = buffer.position();
+
+        // Reserve space for the size and write the count of list elements.
+        if (fieldWidth == 1) {
+            buffer.put((byte) 0);
+            buffer.put((byte) count);
+        } else {
+            buffer.putInt(0);
+            buffer.putInt(count);
+        }
+
+        // Write the list elements and then compute total size written.
+        for (int i = 0; i < count; ++i) {
+            writeElement(disposition, i);
+        }
+
+        // Move back and write the size
+        int endIndex = buffer.position();
+        int writeSize = endIndex - startIndex - fieldWidth;
+
+        buffer.position(startIndex);
+        if (fieldWidth == 1) {
+            buffer.put((byte) writeSize);
+        } else {
+            buffer.putInt(writeSize);
+        }
+        buffer.position(endIndex);
+    }
+
+    private void writeElement(Disposition disposition, int index) {
+        switch (index) {
+            case 0:
+                getEncoder().writeBoolean(disposition.getRole().getValue());
+                break;
+            case 1:
+                getEncoder().writeUnsignedInteger(disposition.getFirst());
+                break;
+            case 2:
+                getEncoder().writeUnsignedInteger(disposition.getLast());
+                break;
+            case 3:
+                getEncoder().writeBoolean(disposition.getSettled());
+                break;
+            case 4:
+                getEncoder().writeObject(disposition.getState());
+                break;
+            case 5:
+                getEncoder().writeBoolean(disposition.getBatchable());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown Disposition value index: " + index);
+        }
+    }
+
+    private int getElementCount(Disposition disposition) {
+        if (disposition.getBatchable()) {
+            return 6;
+        } else if (disposition.getState() != null) {
+            return 5;
+        } else if (disposition.getSettled()) {
+            return 4;
+        } else if (disposition.getLast() != null) {
+            return 3;
+        } else {
+            return 2;
+        }
+    }
+
+    private byte deduceEncodingCode(Disposition value, int elementCount) {
+        if (value.getState() == null) {
+            return EncodingCodes.LIST8;
+        } else if (value.getState() == Accepted.getInstance() || value.getState() == Released.getInstance()) {
+            return EncodingCodes.LIST8;
+        } else {
+            return EncodingCodes.LIST32;
+        }
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathDispositionType type = new FastPathDispositionType(encoder);
+        for(Object descriptor : DESCRIPTORS) {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathFlowType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathFlowType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathFlowType.java
new file mode 100644
index 0000000..78abc5c
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathFlowType.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.transport;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.transport.Flow;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+public class FastPathFlowType implements AMQPType<Flow>, FastPathDescribedTypeConstructor<Flow> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000013L), Symbol.valueOf("amqp:flow:list"),
+    };
+
+    private final FlowType flowType;
+
+    public FastPathFlowType(EncoderImpl encoder) {
+        this.flowType = new FlowType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return flowType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return flowType.getDecoder();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Flow> getTypeClass() {
+        return Flow.class;
+    }
+
+    @Override
+    public TypeEncoding<Flow> getEncoding(Flow flow) {
+        return flowType.getEncoding(flow);
+    }
+
+    @Override
+    public TypeEncoding<Flow> getCanonicalEncoding() {
+        return flowType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Flow>> getAllEncodings() {
+        return flowType.getAllEncodings();
+    }
+
+    @Override
+    public Flow readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        @SuppressWarnings("unused")
+        int size = 0;
+        int count = 0;
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                // TODO - Technically invalid however old decoder also allowed this.
+                break;
+            case EncodingCodes.LIST8:
+                size = ((int)decoder.getByteBuffer().get()) & 0xff;
+                count = ((int)decoder.getByteBuffer().get()) & 0xff;
+                break;
+            case EncodingCodes.LIST32:
+                size = decoder.getByteBuffer().getInt();
+                count = decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Flow encoding: " + typeCode);
+        }
+
+        Flow flow = new Flow();
+
+        for (int index = 0; index < count; ++index) {
+            switch (index) {
+                case 0:
+                    flow.setNextIncomingId(decoder.readUnsignedInteger());
+                    break;
+                case 1:
+                    flow.setIncomingWindow(decoder.readUnsignedInteger());
+                    break;
+                case 2:
+                    flow.setNextOutgoingId(decoder.readUnsignedInteger());
+                    break;
+                case 3:
+                    flow.setOutgoingWindow(decoder.readUnsignedInteger());
+                    break;
+                case 4:
+                    flow.setHandle(decoder.readUnsignedInteger());
+                    break;
+                case 5:
+                    flow.setDeliveryCount(decoder.readUnsignedInteger());
+                    break;
+                case 6:
+                    flow.setLinkCredit(decoder.readUnsignedInteger());
+                    break;
+                case 7:
+                    flow.setAvailable(decoder.readUnsignedInteger());
+                    break;
+                case 8:
+                    flow.setDrain(decoder.readBoolean(false));
+                    break;
+                case 9:
+                    flow.setEcho(decoder.readBoolean(false));
+                    break;
+                case 10:
+                    flow.setProperties(decoder.readMap());
+                    break;
+                default:
+                    throw new IllegalStateException("To many entries in Flow encoding");
+            }
+        }
+
+        return flow;
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public void write(Flow flow) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        int count = getElementCount(flow);
+        byte encodingCode = deduceEncodingCode(flow, count);
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(flowType.getDescriptor());
+
+        final int fieldWidth;
+
+        if (encodingCode == EncodingCodes.LIST8) {
+            fieldWidth = 1;
+            buffer.put(EncodingCodes.LIST8);
+        } else {
+            fieldWidth = 4;
+            buffer.put(EncodingCodes.LIST32);
+        }
+
+        int startIndex = buffer.position();
+
+        // Reserve space for the size and write the count of list elements.
+        if (fieldWidth == 1) {
+            buffer.put((byte) 0);
+            buffer.put((byte) count);
+        } else {
+            buffer.putInt(0);
+            buffer.putInt(count);
+        }
+
+        // Write the list elements and then compute total size written.
+        for (int i = 0; i < count; ++i) {
+            writeElement(flow, i);
+        }
+
+        // Move back and write the size
+        int endIndex = buffer.position();
+        int writeSize = endIndex - startIndex - fieldWidth;
+
+        buffer.position(startIndex);
+        if (fieldWidth == 1) {
+            buffer.put((byte) writeSize);
+        } else {
+            buffer.putInt(writeSize);
+        }
+        buffer.position(endIndex);
+    }
+
+    private void writeElement(Flow flow, int index) {
+        switch (index) {
+            case 0:
+                getEncoder().writeUnsignedInteger(flow.getNextIncomingId());
+                break;
+            case 1:
+                getEncoder().writeUnsignedInteger(flow.getIncomingWindow());
+                break;
+            case 2:
+                getEncoder().writeUnsignedInteger(flow.getNextOutgoingId());
+                break;
+            case 3:
+                getEncoder().writeUnsignedInteger(flow.getOutgoingWindow());
+                break;
+            case 4:
+                getEncoder().writeUnsignedInteger(flow.getHandle());
+                break;
+            case 5:
+                getEncoder().writeUnsignedInteger(flow.getDeliveryCount());
+                break;
+            case 6:
+                getEncoder().writeUnsignedInteger(flow.getLinkCredit());
+                break;
+            case 7:
+                getEncoder().writeUnsignedInteger(flow.getAvailable());
+                break;
+            case 8:
+                getEncoder().writeBoolean(flow.getDrain());
+                break;
+            case 9:
+                getEncoder().writeBoolean(flow.getEcho());
+                break;
+            case 10:
+                getEncoder().writeMap(flow.getProperties());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown Flow value index: " + index);
+        }
+    }
+
+    private int getElementCount(Flow flow) {
+        if (flow.getProperties() != null) {
+            return 11;
+        } else if (flow.getEcho()) {
+            return 10;
+        } else if (flow.getDrain()) {
+            return 9;
+        } else if (flow.getAvailable() != null) {
+            return 8;
+        } else if (flow.getLinkCredit() != null) {
+            return 7;
+        } else if (flow.getDeliveryCount() != null) {
+            return 6;
+        } else if (flow.getHandle() != null) {
+            return 5;
+        } else {
+            return 4;
+        }
+    }
+
+    private byte deduceEncodingCode(Flow value, int elementCount) {
+        if (value.getProperties() == null) {
+            return EncodingCodes.LIST8;
+        } else {
+            return EncodingCodes.LIST32;
+        }
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathFlowType type = new FastPathFlowType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathTransferType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathTransferType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathTransferType.java
new file mode 100644
index 0000000..685890a
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FastPathTransferType.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec.transport;
+
+import java.util.Collection;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedByte;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+import org.apache.qpid.proton.amqp.transport.DeliveryState;
+import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
+import org.apache.qpid.proton.amqp.transport.Transfer;
+import org.apache.qpid.proton.codec.AMQPType;
+import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
+import org.apache.qpid.proton.codec.DecodeException;
+import org.apache.qpid.proton.codec.Decoder;
+import org.apache.qpid.proton.codec.DecoderImpl;
+import org.apache.qpid.proton.codec.EncoderImpl;
+import org.apache.qpid.proton.codec.EncodingCodes;
+import org.apache.qpid.proton.codec.TypeEncoding;
+import org.apache.qpid.proton.codec.WritableBuffer;
+
+/**
+ * Fast TrasnferType encoder
+ */
+public class FastPathTransferType implements AMQPType<Transfer>, FastPathDescribedTypeConstructor<Transfer> {
+
+    private static final Object[] DESCRIPTORS =
+    {
+        UnsignedLong.valueOf(0x0000000000000014L), Symbol.valueOf("amqp:transfer:list"),
+    };
+
+    private final TransferType transferType;
+
+    public FastPathTransferType(EncoderImpl encoder) {
+        this.transferType = new TransferType(encoder);
+    }
+
+    public EncoderImpl getEncoder() {
+        return transferType.getEncoder();
+    }
+
+    public DecoderImpl getDecoder() {
+        return transferType.getDecoder();
+    }
+
+    @Override
+    public Transfer readValue() {
+        DecoderImpl decoder = getDecoder();
+        byte typeCode = decoder.getByteBuffer().get();
+
+        @SuppressWarnings("unused")
+        int size = 0;
+        int count = 0;
+
+        switch (typeCode) {
+            case EncodingCodes.LIST0:
+                // TODO - Technically invalid however old decoder also allowed this.
+                break;
+            case EncodingCodes.LIST8:
+                size = ((int)decoder.getByteBuffer().get()) & 0xff;
+                count = ((int)decoder.getByteBuffer().get()) & 0xff;
+                break;
+            case EncodingCodes.LIST32:
+                size = decoder.getByteBuffer().getInt();
+                count = decoder.getByteBuffer().getInt();
+                break;
+            default:
+                throw new DecodeException("Incorrect type found in Transfer encoding: " + typeCode);
+        }
+
+        Transfer transfer = new Transfer();
+
+        for (int index = 0; index < count; ++index) {
+            switch (index) {
+                case 0:
+                    transfer.setHandle(decoder.readUnsignedInteger());
+                    break;
+                case 1:
+                    transfer.setDeliveryId(decoder.readUnsignedInteger());
+                    break;
+                case 2:
+                    transfer.setDeliveryTag(decoder.readBinary());
+                    break;
+                case 3:
+                    transfer.setMessageFormat(decoder.readUnsignedInteger());
+                    break;
+                case 4:
+                    transfer.setSettled(decoder.readBoolean());
+                    break;
+                case 5:
+                    transfer.setMore(decoder.readBoolean(false));
+                    break;
+                case 6:
+                    UnsignedByte rcvSettleMode = decoder.readUnsignedByte();
+                    transfer.setRcvSettleMode(rcvSettleMode == null ? null : ReceiverSettleMode.values()[rcvSettleMode.intValue()]);
+                    break;
+                case 7:
+                    transfer.setState((DeliveryState) decoder.readObject());
+                    break;
+                case 8:
+                    transfer.setResume(decoder.readBoolean(false));
+                    break;
+                case 9:
+                    transfer.setAborted(decoder.readBoolean(false));
+                    break;
+                case 10:
+                    transfer.setBatchable(decoder.readBoolean(false));
+                    break;
+                default:
+                    throw new IllegalStateException("To many entries in Transfer encoding");
+            }
+        }
+
+        return transfer;
+    }
+
+    @Override
+    public void skipValue() {
+        getDecoder().readConstructor().skipValue();
+    }
+
+    @Override
+    public boolean encodesJavaPrimitive() {
+        return false;
+    }
+
+    @Override
+    public Class<Transfer> getTypeClass() {
+        return Transfer.class;
+    }
+
+    @Override
+    public TypeEncoding<Transfer> getEncoding(Transfer transfer) {
+        return transferType.getEncoding(transfer);
+    }
+
+    @Override
+    public TypeEncoding<Transfer> getCanonicalEncoding() {
+        return transferType.getCanonicalEncoding();
+    }
+
+    @Override
+    public Collection<? extends TypeEncoding<Transfer>> getAllEncodings() {
+        return transferType.getAllEncodings();
+    }
+
+    @Override
+    public void write(Transfer value) {
+        WritableBuffer buffer = getEncoder().getBuffer();
+        int count = getElementCount(value);
+        byte encodingCode = deduceEncodingCode(value, count);
+
+        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
+        getEncoder().writeUnsignedLong(transferType.getDescriptor());
+
+        final int fieldWidth;
+
+        if (encodingCode == EncodingCodes.LIST8) {
+            fieldWidth = 1;
+            buffer.put(EncodingCodes.LIST8);
+        } else {
+            fieldWidth = 4;
+            buffer.put(EncodingCodes.LIST32);
+        }
+
+        int startIndex = buffer.position();
+
+        // Reserve space for the size and write the count of list elements.
+        if (fieldWidth == 1) {
+            buffer.put((byte) 0);
+            buffer.put((byte) count);
+        } else {
+            buffer.putInt(0);
+            buffer.putInt(count);
+        }
+
+        // Write the list elements and then compute total size written.
+        for (int i = 0; i < count; ++i) {
+            writeElement(value, i);
+        }
+
+        // Move back and write the size
+        int endIndex = buffer.position();
+        int writeSize = endIndex - startIndex - fieldWidth;
+
+        buffer.position(startIndex);
+        if (fieldWidth == 1) {
+            buffer.put((byte) writeSize);
+        } else {
+            buffer.putInt(writeSize);
+        }
+        buffer.position(endIndex);
+    }
+
+    private void writeElement(Transfer transfer, int index) {
+        switch (index) {
+            case 0:
+                getEncoder().writeUnsignedInteger(transfer.getHandle());
+                break;
+            case 1:
+                getEncoder().writeUnsignedInteger(transfer.getDeliveryId());
+                break;
+            case 2:
+                getEncoder().writeBinary(transfer.getDeliveryTag());
+                break;
+            case 3:
+                getEncoder().writeUnsignedInteger(transfer.getMessageFormat());
+                break;
+            case 4:
+                getEncoder().writeBoolean(transfer.getSettled());
+                break;
+            case 5:
+                getEncoder().writeBoolean(transfer.getMore());
+                break;
+            case 6:
+                ReceiverSettleMode rcvSettleMode = transfer.getRcvSettleMode();
+                getEncoder().writeObject(rcvSettleMode == null ? null : rcvSettleMode.getValue());
+                break;
+            case 7:
+                getEncoder().writeObject(transfer.getState());
+                break;
+            case 8:
+                getEncoder().writeBoolean(transfer.getResume());
+                break;
+            case 9:
+                getEncoder().writeBoolean(transfer.getAborted());
+                break;
+            case 10:
+                getEncoder().writeBoolean(transfer.getBatchable());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown Transfer value index: " + index);
+        }
+    }
+
+    private byte deduceEncodingCode(Transfer value, int elementCount) {
+        if (value.getState() != null) {
+            return EncodingCodes.LIST32;
+        } else if (value.getDeliveryTag() != null && value.getDeliveryTag().getLength() > 200) {
+            return EncodingCodes.LIST32;
+        } else {
+            return EncodingCodes.LIST8;
+        }
+    }
+
+    private int getElementCount(Transfer transfer) {
+        if (transfer.getBatchable()) {
+            return 11;
+        } else if (transfer.getAborted()) {
+            return 10;
+        } else if (transfer.getResume()) {
+            return 9;
+        } else if (transfer.getState() != null) {
+            return 8;
+        } else if (transfer.getRcvSettleMode() != null) {
+            return 7;
+        } else if (transfer.getMore()) {
+            return 6;
+        } else if (transfer.getSettled() != null) {
+            return 5;
+        } else if (transfer.getMessageFormat() != null) {
+            return 4;
+        } else if (transfer.getDeliveryTag() != null) {
+            return 3;
+        } else if (transfer.getDeliveryId() != null) {
+            return 2;
+        } else {
+            return 1;
+        }
+    }
+
+    public static void register(Decoder decoder, EncoderImpl encoder) {
+        FastPathTransferType type = new FastPathTransferType(encoder);
+        for(Object descriptor : DESCRIPTORS)
+        {
+            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
+        }
+        encoder.register(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java
index f9e91dc..499a397 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java
@@ -36,7 +36,6 @@ import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DescribedTypeConstructor;
 import org.apache.qpid.proton.codec.EncoderImpl;
 
-
 public final class FlowType extends AbstractDescribedType<Flow,List> implements DescribedTypeConstructor<Flow>
 {
     private static final Object[] DESCRIPTORS =
@@ -46,7 +45,7 @@ public final class FlowType extends AbstractDescribedType<Flow,List> implements
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000013L);
 
-    private FlowType(EncoderImpl encoder)
+    FlowType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -176,7 +175,6 @@ public final class FlowType extends AbstractDescribedType<Flow,List> implements
         return Flow.class;
     }
 
-
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
         FlowType type = new FlowType(encoder);
@@ -186,6 +184,4 @@ public final class FlowType extends AbstractDescribedType<Flow,List> implements
         }
         encoder.register(type);
     }
-
 }
-  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java
index 4ddbd49..6d18a07 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java
@@ -39,7 +39,6 @@ import org.apache.qpid.proton.codec.Decoder;
 import org.apache.qpid.proton.codec.DescribedTypeConstructor;
 import org.apache.qpid.proton.codec.EncoderImpl;
 
-
 public final class TransferType extends AbstractDescribedType<Transfer,List> implements DescribedTypeConstructor<Transfer>
 {
     private static final Object[] DESCRIPTORS =
@@ -49,7 +48,7 @@ public final class TransferType extends AbstractDescribedType<Transfer,List> imp
 
     private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000014L);
 
-    private TransferType(EncoderImpl encoder)
+    TransferType(EncoderImpl encoder)
     {
         super(encoder);
     }
@@ -190,9 +189,6 @@ public final class TransferType extends AbstractDescribedType<Transfer,List> imp
             return Transfer.class;
         }
 
-
-
-
     public static void register(Decoder decoder, EncoderImpl encoder)
     {
         TransferType type = new TransferType(encoder);
@@ -202,6 +198,4 @@ public final class TransferType extends AbstractDescribedType<Transfer,List> imp
         }
         encoder.register(type);
     }
-
 }
-  
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/AmqpValueTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/AmqpValueTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/AmqpValueTypeCodecTest.java
new file mode 100644
index 0000000..f2154e3
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/AmqpValueTypeCodecTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.apache.qpid.proton.amqp.messaging.AmqpValue;
+import org.junit.Test;
+
+/**
+ * Test for decoder of the AmqpValue type.
+ */
+public class AmqpValueTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeAmqpValueString() throws IOException {
+        doTestDecodeAmqpValueSeries(1, new AmqpValue("test"));
+    }
+
+    @Test
+    public void testDecodeAmqpValueNull() throws IOException {
+        doTestDecodeAmqpValueSeries(1, new AmqpValue(null));
+    }
+
+    @Test
+    public void testDecodeAmqpValueUUID() throws IOException {
+        doTestDecodeAmqpValueSeries(1, new AmqpValue(UUID.randomUUID()));
+    }
+
+    @Test
+    public void testDecodeSmallSeriesOfAmqpValue() throws IOException {
+        doTestDecodeAmqpValueSeries(SMALL_SIZE, new AmqpValue("test"));
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfAmqpValue() throws IOException {
+        doTestDecodeAmqpValueSeries(LARGE_SIZE, new AmqpValue("test"));
+    }
+
+    private void doTestDecodeAmqpValueSeries(int size, AmqpValue value) throws IOException {
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(value);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof AmqpValue);
+
+            AmqpValue decoded = (AmqpValue) result;
+
+            assertEquals(value.getValue(), decoded.getValue());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesCodecTest.java
new file mode 100644
index 0000000..66f15bd
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesCodecTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
+import org.junit.Test;
+
+public class ApplicationPropertiesCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfApplicationProperties() throws IOException {
+        doTestDecodeHeaderSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfApplicationProperties() throws IOException {
+        doTestDecodeHeaderSeries(LARGE_SIZE);
+    }
+
+    private void doTestDecodeHeaderSeries(int size) throws IOException {
+
+        Map<String, Object> propertiesMap = new LinkedHashMap<>();
+        ApplicationProperties properties = new ApplicationProperties(propertiesMap);
+
+        propertiesMap.put("key-1", "1");
+        propertiesMap.put("key-2", "2");
+        propertiesMap.put("key-3", "3");
+        propertiesMap.put("key-4", "4");
+        propertiesMap.put("key-5", "5");
+        propertiesMap.put("key-6", "6");
+        propertiesMap.put("key-7", "7");
+        propertiesMap.put("key-8", "8");
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(properties);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof ApplicationProperties);
+
+            ApplicationProperties decoded = (ApplicationProperties) result;
+
+            assertEquals(8, decoded.getValue().size());
+            assertTrue(decoded.getValue().equals(propertiesMap));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesTypeTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesTypeTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesTypeTest.java
new file mode 100644
index 0000000..6f11956
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/ApplicationPropertiesTypeTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
+import org.junit.Test;
+
+public class ApplicationPropertiesTypeTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfApplicationProperties() throws IOException {
+        doTestDecodeHeaderSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfApplicationProperties() throws IOException {
+        doTestDecodeHeaderSeries(LARGE_SIZE);
+    }
+
+    private void doTestDecodeHeaderSeries(int size) throws IOException {
+
+        Map<String, Object> propertiesMap = new LinkedHashMap<>();
+        ApplicationProperties properties = new ApplicationProperties(propertiesMap);
+
+        long currentTime = System.currentTimeMillis();
+
+        propertiesMap.put("long-1", currentTime);
+        propertiesMap.put("date-1", new Date(currentTime));
+        propertiesMap.put("long-2", currentTime + 100);
+        propertiesMap.put("date-2", new Date(currentTime + 100));
+        propertiesMap.put("key-1", "1");
+        propertiesMap.put("key-2", "2");
+        propertiesMap.put("key-3", "3");
+        propertiesMap.put("key-4", "4");
+        propertiesMap.put("key-5", "5");
+        propertiesMap.put("key-6", "6");
+        propertiesMap.put("key-7", "7");
+        propertiesMap.put("key-8", "8");
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(properties);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof ApplicationProperties);
+
+            ApplicationProperties decoded = (ApplicationProperties) result;
+
+            assertEquals(properties.getValue().size(), decoded.getValue().size());
+            assertTrue(decoded.getValue().equals(propertiesMap));
+
+            assertEquals(currentTime, decoded.getValue().get("long-1"));
+            assertEquals(new Date(currentTime), decoded.getValue().get("date-1"));
+            assertEquals(currentTime + 100, decoded.getValue().get("long-2"));
+            assertEquals(new Date(currentTime + 100), decoded.getValue().get("date-2"));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
new file mode 100644
index 0000000..2411b7e
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.junit.Test;
+
+/**
+ * Test decoding of AMQP Array types
+ */
+public class ArrayTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_ARRAY_SIZE = 2048;
+    private final int SMALL_ARRAY_SIZE = 32;
+
+    @Test
+    public void testArrayOfPrimitiveBooleanObjects() throws IOException {
+        final int size = 10;
+
+        boolean[] source = new boolean[size];
+        for (int i = 0; i < size; ++i) {
+            source[i] = i % 2 == 0;
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject(buffer);
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+        assertTrue(result.getClass().getComponentType().isPrimitive());
+
+        boolean[] array = (boolean[]) result;
+        assertEquals(size, array.length);
+
+        for (int i = 0; i < size; ++i) {
+            assertEquals(source[i], array[i]);
+        }
+    }
+
+    @Test
+    public void testZeroSizedArrayOfPrimitiveBooleanObjects() throws IOException {
+        boolean[] source = new boolean[0];
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+        assertTrue(result.getClass().getComponentType().isPrimitive());
+
+        boolean[] array = (boolean[]) result;
+        assertEquals(source.length, array.length);
+    }
+
+    @Test
+    public void testArrayOfBooleanObjects() throws IOException {
+        final int size = 10;
+
+        Boolean[] source = new Boolean[size];
+        for (int i = 0; i < size; ++i) {
+            source[i] = i % 2 == 0;
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+        assertTrue(result.getClass().getComponentType().isPrimitive());
+
+        boolean[] array = (boolean[]) result;
+        assertEquals(size, array.length);
+
+        for (int i = 0; i < size; ++i) {
+            assertEquals(source[i], array[i]);
+        }
+    }
+
+    @Test
+    public void testZeroSizedArrayOfBooleanObjects() throws IOException {
+        Boolean[] source = new Boolean[0];
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+        assertTrue(result.getClass().getComponentType().isPrimitive());
+
+        boolean[] array = (boolean[]) result;
+        assertEquals(source.length, array.length);
+    }
+
+    @Test
+    public void testDecodeSmallBooleanArray() throws IOException {
+        doTestDecodeBooleanArrayType(SMALL_ARRAY_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeBooleanArray() throws IOException {
+        doTestDecodeBooleanArrayType(LARGE_ARRAY_SIZE);
+    }
+
+    private void doTestDecodeBooleanArrayType(int size) throws IOException {
+        boolean[] source = new boolean[size];
+        for (int i = 0; i < size; ++i) {
+            source[i] = i % 2 == 0;
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+        assertTrue(result.getClass().getComponentType().isPrimitive());
+
+        boolean[] array = (boolean[]) result;
+        assertEquals(size, array.length);
+
+        for (int i = 0; i < size; ++i) {
+            assertEquals(source[i], array[i]);
+        }
+    }
+
+    @Test
+    public void testDecodeSmallSymbolArray() throws IOException {
+        doTestDecodeSymbolArrayType(SMALL_ARRAY_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSymbolArray() throws IOException {
+        doTestDecodeSymbolArrayType(LARGE_ARRAY_SIZE);
+    }
+
+    private void doTestDecodeSymbolArrayType(int size) throws IOException {
+        Symbol[] source = new Symbol[size];
+        for (int i = 0; i < size; ++i) {
+            source[i] = Symbol.valueOf("test->" + i);
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+
+        Symbol[] array = (Symbol[]) result;
+        assertEquals(size, array.length);
+
+        for (int i = 0; i < size; ++i) {
+            assertEquals(source[i], array[i]);
+        }
+    }
+
+    @Test
+    public void testDecodeSmallUUIDArray() throws IOException {
+        doTestDecodeUUDIArrayType(SMALL_ARRAY_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeUUDIArray() throws IOException {
+        doTestDecodeUUDIArrayType(LARGE_ARRAY_SIZE);
+    }
+
+    private void doTestDecodeUUDIArrayType(int size) throws IOException {
+        UUID[] source = new UUID[size];
+        for (int i = 0; i < size; ++i) {
+            source[i] = UUID.randomUUID();
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+
+        UUID[] array = (UUID[]) result;
+        assertEquals(size, array.length);
+
+        for (int i = 0; i < size; ++i) {
+            assertEquals(source[i], array[i]);
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testArrayOfListsOfUUIDs() throws IOException {
+        ArrayList<UUID>[] source = new ArrayList[2];
+        for (int i = 0; i < source.length; ++i) {
+            source[i] = new ArrayList<UUID>(3);
+            source[i].add(UUID.randomUUID());
+            source[i].add(UUID.randomUUID());
+            source[i].add(UUID.randomUUID());
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+
+        List[] list = (List[]) result;
+        assertEquals(source.length, list.length);
+
+        for (int i = 0; i < list.length; ++i) {
+            assertEquals(source[i], list[i]);
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testArrayOfMApsOfStringToUUIDs() throws IOException {
+        Map<String, UUID>[] source = new LinkedHashMap[2];
+        for (int i = 0; i < source.length; ++i) {
+            source[i] = new LinkedHashMap<String, UUID>();
+            source[i].put("1", UUID.randomUUID());
+            source[i].put("2", UUID.randomUUID());
+            source[i].put("3", UUID.randomUUID());
+        }
+
+        encoder.writeArray(source);
+
+        buffer.clear();
+
+        Object result = decoder.readObject();
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+
+        Map[] map = (Map[]) result;
+        assertEquals(source.length, map.length);
+
+        for (int i = 0; i < map.length; ++i) {
+            assertEquals(source[i], map[i]);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/Benchmark.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/Benchmark.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/Benchmark.java
new file mode 100644
index 0000000..529a808
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/Benchmark.java
@@ -0,0 +1,420 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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 org.apache.qpid.proton.codec;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedByte;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.UnsignedShort;
+import org.apache.qpid.proton.amqp.messaging.Accepted;
+import org.apache.qpid.proton.amqp.messaging.Data;
+import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
+import org.apache.qpid.proton.amqp.messaging.Header;
+import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
+import org.apache.qpid.proton.amqp.messaging.Properties;
+import org.apache.qpid.proton.amqp.transport.Disposition;
+import org.apache.qpid.proton.amqp.transport.Flow;
+import org.apache.qpid.proton.amqp.transport.Role;
+import org.apache.qpid.proton.amqp.transport.Transfer;
+
+public class Benchmark implements Runnable {
+
+    private static final int ITERATIONS = 10 * 1024 * 1024;
+
+    private ByteBuffer byteBuf = ByteBuffer.allocate(8192);
+    private BenchmarkResult resultSet = new BenchmarkResult();
+    private boolean warming = true;
+
+    private final DecoderImpl decoder = new DecoderImpl();
+    private final EncoderImpl encoder = new EncoderImpl(decoder);
+
+    public static final void main(String[] args) throws IOException, InterruptedException {
+        System.out.println("Current PID: " + ManagementFactory.getRuntimeMXBean().getName());
+        Benchmark benchmark = new Benchmark();
+        benchmark.run();
+    }
+
+    @Override
+    public void run() {
+        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
+
+        encoder.setByteBuffer(byteBuf);
+        decoder.setByteBuffer(byteBuf);
+
+        try {
+            doBenchmarks();
+            warming = false;
+            doBenchmarks();
+        } catch (IOException e) {
+            System.out.println("Unexpected error: " + e.getMessage());
+        }
+    }
+
+    private void time(String message, BenchmarkResult resultSet) {
+        if (!warming) {
+            System.out.println("Benchamrk of type: " + message + ": ");
+            System.out.println("    Encode time = " + resultSet.getEncodeTimeMills());
+            System.out.println("    Decode time = " + resultSet.getDecodeTimeMills());
+        }
+    }
+
+    private final void doBenchmarks() throws IOException {
+        benchmarkListOfInts();
+        benchmarkUUIDs();
+        benchmarkHeader();
+        benchmarkProperties();
+        benchmarkMessageAnnotations();
+        benchmarkApplicationProperties();
+        benchmarkSymbols();
+        benchmarkTransfer();
+        benchmarkFlow();
+        benchmarkDisposition();
+        benchmarkString();
+        benchmarkData();
+        warming = false;
+    }
+
+    private void benchmarkListOfInts() throws IOException {
+        ArrayList<Object> list = new ArrayList<>(10);
+        for (int j = 0; j < 10; j++) {
+            list.add(0);
+        }
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeList(list);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readList();
+        }
+        resultSet.decodesComplete();
+
+        time("List<Integer>", resultSet);
+    }
+
+    private void benchmarkUUIDs() throws IOException {
+        UUID uuid = UUID.randomUUID();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeUUID(uuid);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readUUID();
+        }
+        resultSet.decodesComplete();
+
+        time("UUID", resultSet);
+    }
+
+    private void benchmarkHeader() throws IOException {
+        Header header = new Header();
+        header.setDurable(true);
+        header.setFirstAcquirer(true);
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(header);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Header", resultSet);
+    }
+
+    private void benchmarkTransfer() throws IOException {
+        Transfer transfer = new Transfer();
+        transfer.setDeliveryTag(new Binary(new byte[] {1, 2, 3}));
+        transfer.setHandle(UnsignedInteger.valueOf(10));
+        transfer.setMessageFormat(UnsignedInteger.ZERO);
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(transfer);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Transfer", resultSet);
+    }
+
+    private void benchmarkFlow() throws IOException {
+        Flow flow = new Flow();
+        flow.setNextIncomingId(UnsignedInteger.valueOf(1));
+        flow.setIncomingWindow(UnsignedInteger.valueOf(2047));
+        flow.setNextOutgoingId(UnsignedInteger.valueOf(1));
+        flow.setOutgoingWindow(UnsignedInteger.MAX_VALUE);
+        flow.setHandle(UnsignedInteger.ZERO);
+        flow.setDeliveryCount(UnsignedInteger.valueOf(10));
+        flow.setLinkCredit(UnsignedInteger.valueOf(1000));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(flow);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Flow", resultSet);
+    }
+
+    private void benchmarkProperties() throws IOException {
+        Properties properties = new Properties();
+        properties.setTo("queue:1");
+        properties.setMessageId("ID:Message:1");
+        properties.setCreationTime(new Date(System.currentTimeMillis()));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(properties);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Properties", resultSet);
+    }
+
+    private void benchmarkMessageAnnotations() throws IOException {
+        MessageAnnotations annotations = new MessageAnnotations(new HashMap<Symbol, Object>());
+        annotations.getValue().put(Symbol.valueOf("test1"), UnsignedByte.valueOf((byte) 128));
+        annotations.getValue().put(Symbol.valueOf("test2"), UnsignedShort.valueOf((short) 128));
+        annotations.getValue().put(Symbol.valueOf("test3"), UnsignedInteger.valueOf((byte) 128));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(annotations);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("MessageAnnotations", resultSet);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void benchmarkApplicationProperties() throws IOException {
+        ApplicationProperties properties = new ApplicationProperties(new HashMap<String, Object>());
+        properties.getValue().put("test1", UnsignedByte.valueOf((byte) 128));
+        properties.getValue().put("test2", UnsignedShort.valueOf((short) 128));
+        properties.getValue().put("test3", UnsignedInteger.valueOf((byte) 128));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(properties);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("ApplicationProperties", resultSet);
+    }
+
+    private void benchmarkSymbols() throws IOException {
+        Symbol symbol1 = Symbol.valueOf("Symbol-1");
+        Symbol symbol2 = Symbol.valueOf("Symbol-2");
+        Symbol symbol3 = Symbol.valueOf("Symbol-3");
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeSymbol(symbol1);
+            encoder.writeSymbol(symbol2);
+            encoder.writeSymbol(symbol3);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readSymbol();
+            decoder.readSymbol();
+            decoder.readSymbol();
+        }
+        resultSet.decodesComplete();
+
+        time("Symbol", resultSet);
+    }
+
+    private void benchmarkDisposition() throws IOException {
+        Disposition disposition = new Disposition();
+        disposition.setRole(Role.RECEIVER);
+        disposition.setSettled(true);
+        disposition.setState(Accepted.getInstance());
+        disposition.setFirst(UnsignedInteger.valueOf(2));
+        disposition.setLast(UnsignedInteger.valueOf(2));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(disposition);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Disposition", resultSet);
+    }
+
+    private void benchmarkString() throws IOException {
+        String string1 = new String("String-1");
+        String string2 = new String("String-2");
+        String string3 = new String("String-3");
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeString(string1);
+            encoder.writeString(string2);
+            encoder.writeString(string3);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readString();
+            decoder.readString();
+            decoder.readString();
+        }
+        resultSet.decodesComplete();
+
+        time("String", resultSet);
+    }
+
+    private void benchmarkData() throws IOException {
+        Data data1 = new Data(new Binary(new byte[] {1, 2, 3}));
+        Data data2 = new Data(new Binary(new byte[] {4, 5, 6}));
+        Data data3 = new Data(new Binary(new byte[] {7, 8, 9}));
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.clear();
+            encoder.writeObject(data1);
+            encoder.writeObject(data2);
+            encoder.writeObject(data3);
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            byteBuf.flip();
+            decoder.readObject();
+            decoder.readObject();
+            decoder.readObject();
+        }
+        resultSet.decodesComplete();
+
+        time("Data", resultSet);
+    }
+
+    private static class BenchmarkResult {
+
+        private long startTime;
+
+        private long encodeTime;
+        private long decodeTime;
+
+        public void start() {
+            startTime = System.nanoTime();
+        }
+
+        public void encodesComplete() {
+            encodeTime = System.nanoTime() - startTime;
+        }
+
+        public void decodesComplete() {
+            decodeTime = System.nanoTime() - startTime;
+        }
+
+        public long getEncodeTimeMills() {
+            return TimeUnit.NANOSECONDS.toMillis(encodeTime);
+        }
+
+        public long getDecodeTimeMills() {
+            return TimeUnit.NANOSECONDS.toMillis(decodeTime);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/CodecTestSupport.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/CodecTestSupport.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/CodecTestSupport.java
new file mode 100644
index 0000000..bb33697
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/CodecTestSupport.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import java.nio.ByteBuffer;
+
+import org.junit.Before;
+
+/**
+ * Support class for tests of the type decoders
+ */
+public class CodecTestSupport {
+
+    public static final int DEFAULT_MAX_BUFFER = 256 * 1024;
+
+    final DecoderImpl decoder = new DecoderImpl();
+    final EncoderImpl encoder = new EncoderImpl(decoder);
+
+    ByteBuffer buffer;
+
+    @Before
+    public void setUp() {
+        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
+
+        buffer = ByteBuffer.allocate(getMaxBufferSize());
+
+        encoder.setByteBuffer(buffer);
+        decoder.setByteBuffer(buffer);
+    }
+
+    public int getMaxBufferSize() {
+        return DEFAULT_MAX_BUFFER;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/HeaderTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/HeaderTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/HeaderTypeCodecTest.java
new file mode 100644
index 0000000..3b5d93c
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/HeaderTypeCodecTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.qpid.proton.amqp.UnsignedByte;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.messaging.Header;
+import org.junit.Test;
+
+/**
+ * Test for decoder of AMQP Header type.
+ */
+public class HeaderTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024 * 10;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeHeader() throws IOException {
+        doTestDecodeHeaderSeries(1);
+    }
+
+    @Test
+    public void testDecodeSmallSeriesOfHeaders() throws IOException {
+        doTestDecodeHeaderSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfHeaders() throws IOException {
+        doTestDecodeHeaderSeries(LARGE_SIZE);
+    }
+
+    private void doTestDecodeHeaderSeries(int size) throws IOException {
+        Header header = new Header();
+
+        header.setDurable(Boolean.TRUE);
+        header.setPriority(UnsignedByte.valueOf((byte) 3));
+        header.setDeliveryCount(UnsignedInteger.valueOf(10));
+        header.setFirstAcquirer(Boolean.FALSE);
+        header.setTtl(UnsignedInteger.valueOf(500));
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(header);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof Header);
+
+            Header decoded = (Header) result;
+
+            assertEquals(3, decoded.getPriority().intValue());
+            assertTrue(decoded.getDurable().booleanValue());
+        }
+    }
+
+    @Test
+    public void testSkipHeader() throws IOException {
+        Header header1 = new Header();
+        Header header2 = new Header();
+
+        header1.setDurable(Boolean.FALSE);
+        header2.setDurable(Boolean.TRUE);
+
+        encoder.writeObject(header1);
+        encoder.writeObject(header2);
+
+        buffer.clear();
+
+        TypeConstructor<?> headerType = decoder.readConstructor();
+        assertEquals(Header.class, headerType.getTypeClass());
+        headerType.skipValue();
+
+        final Object result = decoder.readObject();
+
+        assertNotNull(result);
+        assertTrue(result instanceof Header);
+
+        Header decoded = (Header) result;
+        assertTrue(decoded.getDurable().booleanValue());
+    }
+
+    @Test
+    public void testDecodeHeaderArray() throws IOException {
+        Header header = new Header();
+
+        header.setDurable(Boolean.TRUE);
+        header.setPriority(UnsignedByte.valueOf((byte) 3));
+        header.setDeliveryCount(UnsignedInteger.valueOf(10));
+        header.setFirstAcquirer(Boolean.FALSE);
+        header.setTtl(UnsignedInteger.valueOf(500));
+
+        Header[] source = new Header[32];
+
+        for (int i = 0; i < source.length; ++i) {
+            source[i] = header;
+        }
+
+        encoder.writeObject(source);
+
+        buffer.clear();
+
+        final Object result = decoder.readObject();
+
+        assertNotNull(result);
+        assertTrue(result.getClass().isArray());
+
+        final Object[] resultArray = (Object[]) result;
+
+        for (int i = 0; i < source.length; ++i) {
+
+            assertTrue(resultArray[i] instanceof Header);
+
+            Header decoded = (Header) resultArray[i];
+
+            assertEquals(3, decoded.getPriority().intValue());
+            assertTrue(decoded.getDurable().booleanValue());
+            assertEquals(header.getDeliveryCount(), decoded.getDeliveryCount());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/ListTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/ListTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/ListTypeCodecTest.java
new file mode 100644
index 0000000..6b5ad5d
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/ListTypeCodecTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.junit.Test;
+
+/**
+ * Test for the Proton List encoder / decoder
+ */
+public class ListTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfLists() throws IOException {
+        doTestDecodeListSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfLists() throws IOException {
+        doTestDecodeListSeries(LARGE_SIZE);
+    }
+
+    @Test
+    public void testDecodeSmallSeriesOfSymbolLists() throws IOException {
+        doTestDecodeSymbolListSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfSymbolLists() throws IOException {
+        doTestDecodeSymbolListSeries(LARGE_SIZE);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void doTestDecodeSymbolListSeries(int size) throws IOException {
+        List<Object> list = new ArrayList<>();
+
+        for (int i = 0; i < 50; ++i) {
+            list.add(Symbol.valueOf(String.valueOf(i)));
+        }
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(list);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof List);
+
+            List<Object> resultList = (List<Object>) result;
+
+            assertEquals(list.size(), resultList.size());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void doTestDecodeListSeries(int size) throws IOException {
+        List<Object> list = new ArrayList<>();
+
+        Date timeNow = new Date(System.currentTimeMillis());
+
+        list.add("ID:Message-1:1:1:0");
+        list.add(new Binary(new byte[1]));
+        list.add("queue:work");
+        list.add(Symbol.valueOf("text/UTF-8"));
+        list.add(Symbol.valueOf("text"));
+        list.add(timeNow);
+        list.add(UnsignedInteger.valueOf(1));
+        list.add(UUID.randomUUID());
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(list);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof List);
+
+            List<Object> resultList = (List<Object>) result;
+
+            assertEquals(list.size(), resultList.size());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/MapTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/MapTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/MapTypeCodecTest.java
new file mode 100644
index 0000000..32a0119
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/MapTypeCodecTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.qpid.proton.amqp.Binary;
+import org.junit.Test;
+
+public class MapTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfMaps() throws IOException {
+        doTestDecodeMapSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfMaps() throws IOException {
+        doTestDecodeMapSeries(LARGE_SIZE);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void doTestDecodeMapSeries(int size) throws IOException {
+
+        String myBoolKey = "myBool";
+        boolean myBool = true;
+        String myByteKey = "myByte";
+        byte myByte = 4;
+        String myBytesKey = "myBytes";
+        byte[] myBytes = myBytesKey.getBytes();
+        String myCharKey = "myChar";
+        char myChar = 'd';
+        String myDoubleKey = "myDouble";
+        double myDouble = 1234567890123456789.1234;
+        String myFloatKey = "myFloat";
+        float myFloat = 1.1F;
+        String myIntKey = "myInt";
+        int myInt = Integer.MAX_VALUE;
+        String myLongKey = "myLong";
+        long myLong = Long.MAX_VALUE;
+        String myShortKey = "myShort";
+        short myShort = 25;
+        String myStringKey = "myString";
+        String myString = myStringKey;
+
+        Map<String, Object> map = new LinkedHashMap<String, Object>();
+        map.put(myBoolKey, myBool);
+        map.put(myByteKey, myByte);
+        map.put(myBytesKey, new Binary(myBytes));
+        map.put(myCharKey, myChar);
+        map.put(myDoubleKey, myDouble);
+        map.put(myFloatKey, myFloat);
+        map.put(myIntKey, myInt);
+        map.put(myLongKey, myLong);
+        map.put(myShortKey, myShort);
+        map.put(myStringKey, myString);
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(map);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof Map);
+
+            Map<String, Object> resultMap = (Map<String, Object>) result;
+
+            assertEquals(map.size(), resultMap.size());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/MessageAnnotationsTypeCodecTest.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/MessageAnnotationsTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/MessageAnnotationsTypeCodecTest.java
new file mode 100644
index 0000000..d1f6ba7
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/MessageAnnotationsTypeCodecTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.UnsignedByte;
+import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.UnsignedShort;
+import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
+import org.junit.Test;
+
+public class MessageAnnotationsTypeCodecTest extends CodecTestSupport {
+
+    private final int LARGE_SIZE = 1024;
+    private final int SMALL_SIZE = 32;
+
+    @Test
+    public void testDecodeSmallSeriesOfMessageAnnotations() throws IOException {
+        doTestDecodeMessageAnnotationsSeries(SMALL_SIZE);
+    }
+
+    @Test
+    public void testDecodeLargeSeriesOfMessageAnnotations() throws IOException {
+        doTestDecodeMessageAnnotationsSeries(LARGE_SIZE);
+    }
+
+    @Test
+    public void testDecodeLMessageAnnotations() throws IOException {
+        doTestDecodeMessageAnnotationsSeries(1);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private void doTestDecodeMessageAnnotationsSeries(int size) throws IOException {
+
+        final Symbol SYMBOL_1 = Symbol.valueOf("test1");
+        final Symbol SYMBOL_2 = Symbol.valueOf("test2");
+        final Symbol SYMBOL_3 = Symbol.valueOf("test3");
+
+        MessageAnnotations annotations = new MessageAnnotations(new HashMap());
+        annotations.getValue().put(SYMBOL_1, UnsignedByte.valueOf((byte) 128));
+        annotations.getValue().put(SYMBOL_2, UnsignedShort.valueOf((short) 128));
+        annotations.getValue().put(SYMBOL_3, UnsignedInteger.valueOf(128));
+
+        for (int i = 0; i < size; ++i) {
+            encoder.writeObject(annotations);
+        }
+
+        buffer.clear();
+
+        for (int i = 0; i < size; ++i) {
+            final Object result = decoder.readObject();
+
+            assertNotNull(result);
+            assertTrue(result instanceof MessageAnnotations);
+
+            MessageAnnotations readAnnotations = (MessageAnnotations) result;
+
+            Map<Symbol, Object> resultMap = readAnnotations.getValue();
+
+            assertEquals(annotations.getValue().size(), resultMap.size());
+            assertEquals(resultMap.get(SYMBOL_1), UnsignedByte.valueOf((byte) 128));
+            assertEquals(resultMap.get(SYMBOL_2), UnsignedShort.valueOf((short) 128));
+            assertEquals(resultMap.get(SYMBOL_3), UnsignedInteger.valueOf(128));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/test/java/org/apache/qpid/proton/codec/NoLocalType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/NoLocalType.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/NoLocalType.java
new file mode 100644
index 0000000..4ec6724
--- /dev/null
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/NoLocalType.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+import org.apache.qpid.proton.amqp.DescribedType;
+import org.apache.qpid.proton.amqp.UnsignedLong;
+
+/**
+ * A Described Type wrapper for JMS no local option for MessageConsumer.
+ */
+public class NoLocalType implements DescribedType {
+
+    public static final NoLocalType NO_LOCAL = new NoLocalType();
+
+    public static final UnsignedLong DESCRIPTOR_CODE = UnsignedLong.valueOf(0x0000468C00000003L);
+
+    private final String noLocal;
+
+    public NoLocalType() {
+        this.noLocal = "NoLocalFilter{}";
+    }
+
+    @Override
+    public Object getDescriptor() {
+        return DESCRIPTOR_CODE;
+    }
+
+    @Override
+    public String getDescribed() {
+        return this.noLocal;
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[4/4] qpid-proton-j git commit: PROTON-1708 Optimizations for the EncoderImpl and DecoderImpl

Posted by ta...@apache.org.
PROTON-1708 Optimizations for the EncoderImpl and DecoderImpl

Provides several performance enhancements for the AMQP codec EncoderImpl
and DecoderImpl classes.

* Reduce instanceof and other type checks fro known types or by looking
ahead in the working buffer
* Reduce the number of throw away objects created during encode and
decode phase such as dynamic type constructor and char decoders etc.
* Provide fast write paths for both primitive types and known Described
types that are most often used
* Provide fast write path for most primitive write operations and for
Described types that are most often used
* Ensure the hot path for most read and write operations can be inlined
for the most common types. 
* Adds some look ahead methods for users of the decoder that allow for
skipping types that aren't needed 
* Allow Map types to be given fixed Type handlers for the Map keys for
those AMQP Map types whose Key types are specified to avoid the overhead
of looking them up on each Key read / write. 

Project: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/commit/2a2d3ff2
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/tree/2a2d3ff2
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton-j/diff/2a2d3ff2

Branch: refs/heads/master
Commit: 2a2d3ff27bd606af3e3c3c93705efff65c7a6302
Parents: cb3b9f4
Author: Timothy Bish <ta...@gmail.com>
Authored: Fri Dec 1 16:11:34 2017 -0500
Committer: Timothy Bish <ta...@gmail.com>
Committed: Fri Dec 1 16:11:34 2017 -0500

----------------------------------------------------------------------
 .../org/apache/qpid/proton/amqp/Symbol.java     |  15 +
 .../qpid/proton/codec/AMQPDefinedTypes.java     |  30 +-
 .../proton/codec/AbstractDescribedType.java     |  12 +-
 .../org/apache/qpid/proton/codec/ArrayType.java |  21 +-
 .../apache/qpid/proton/codec/BinaryType.java    |  33 +-
 .../org/apache/qpid/proton/codec/Decoder.java   |   1 +
 .../apache/qpid/proton/codec/DecoderImpl.java   | 577 +++++++++++--------
 .../proton/codec/DynamicTypeConstructor.java    |   5 +
 .../apache/qpid/proton/codec/EncoderImpl.java   | 196 ++++---
 .../codec/FastPathDescribedTypeConstructor.java |  28 +
 .../codec/FixedSizePrimitiveTypeEncoding.java   |   5 +
 .../org/apache/qpid/proton/codec/ListType.java  | 157 ++++-
 .../org/apache/qpid/proton/codec/MapType.java   | 246 ++++++--
 .../apache/qpid/proton/codec/StringType.java    |  50 +-
 .../apache/qpid/proton/codec/SymbolType.java    |  57 +-
 .../apache/qpid/proton/codec/TimestampType.java |  11 +-
 .../qpid/proton/codec/TypeConstructor.java      |   2 +
 .../org/apache/qpid/proton/codec/UUIDType.java  |   6 +
 .../qpid/proton/codec/UnsignedByteType.java     |   5 +
 .../qpid/proton/codec/UnsignedIntegerType.java  |  22 +-
 .../qpid/proton/codec/UnsignedLongType.java     |  26 +-
 .../qpid/proton/codec/UnsignedShortType.java    |   5 +
 .../proton/codec/messaging/AcceptedType.java    |   2 +-
 .../codec/messaging/AmqpSequenceType.java       |   5 +-
 .../proton/codec/messaging/AmqpValueType.java   |   5 +-
 .../qpid/proton/codec/messaging/DataType.java   |   5 +-
 .../codec/messaging/FastPathAcceptedType.java   | 123 ++++
 .../messaging/FastPathAmqpSequenceType.java     | 104 ++++
 .../codec/messaging/FastPathAmqpValueType.java  | 104 ++++
 .../FastPathApplicationPropertiesType.java      | 112 ++++
 .../codec/messaging/FastPathDataType.java       | 104 ++++
 .../FastPathDeliveryAnnotationsType.java        | 113 ++++
 .../codec/messaging/FastPathFooterType.java     | 110 ++++
 .../codec/messaging/FastPathHeaderType.java     | 244 ++++++++
 .../FastPathMessageAnnotationsType.java         | 113 ++++
 .../codec/messaging/FastPathPropertiesType.java | 308 ++++++++++
 .../qpid/proton/codec/messaging/HeaderType.java |   2 -
 .../proton/codec/messaging/PropertiesType.java  |   6 +-
 .../proton/codec/transport/DispositionType.java |   2 +-
 .../transport/FastPathDispositionType.java      | 248 ++++++++
 .../codec/transport/FastPathFlowType.java       | 279 +++++++++
 .../codec/transport/FastPathTransferType.java   | 295 ++++++++++
 .../qpid/proton/codec/transport/FlowType.java   |   6 +-
 .../proton/codec/transport/TransferType.java    |   8 +-
 .../proton/codec/AmqpValueTypeCodecTest.java    |  81 +++
 .../codec/ApplicationPropertiesCodecTest.java   |  77 +++
 .../codec/ApplicationPropertiesTypeTest.java    |  89 +++
 .../qpid/proton/codec/ArrayTypeCodecTest.java   | 277 +++++++++
 .../org/apache/qpid/proton/codec/Benchmark.java | 420 ++++++++++++++
 .../qpid/proton/codec/CodecTestSupport.java     |  48 ++
 .../qpid/proton/codec/HeaderTypeCodecTest.java  | 145 +++++
 .../qpid/proton/codec/ListTypeCodecTest.java    | 120 ++++
 .../qpid/proton/codec/MapTypeCodecTest.java     |  98 ++++
 .../codec/MessageAnnotationsTypeCodecTest.java  |  88 +++
 .../apache/qpid/proton/codec/NoLocalType.java   |  46 ++
 .../qpid/proton/codec/PropertiesCodecTest.java  |  99 ++++
 .../qpid/proton/codec/StringTypeTest.java       |  24 +
 .../qpid/proton/codec/TransferTypeTest.java     |  82 +++
 .../codec/UnknownDescribedTypeCodecTest.java    | 131 +++++
 .../proton/codec/UnsignedIntegerTypeTest.java   |  26 +
 .../qpid/proton/codec/UnsignedLongTypeTest.java |  25 +
 61 files changed, 5199 insertions(+), 485 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/amqp/Symbol.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/amqp/Symbol.java b/proton-j/src/main/java/org/apache/qpid/proton/amqp/Symbol.java
index 17e6177..4e3d476 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/amqp/Symbol.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/amqp/Symbol.java
@@ -21,16 +21,23 @@
 
 package org.apache.qpid.proton.amqp;
 
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.qpid.proton.codec.WritableBuffer;
+
 public final class Symbol implements Comparable<Symbol>, CharSequence
 {
     private final String _underlying;
+    private final byte[] _underlyingBytes;
+
     private static final ConcurrentHashMap<String, Symbol> _symbols = new ConcurrentHashMap<String, Symbol>(2048);
 
     private Symbol(String underlying)
     {
         _underlying = underlying;
+        _underlyingBytes = underlying.getBytes(StandardCharsets.US_ASCII);
     }
 
     public int length()
@@ -90,5 +97,13 @@ public final class Symbol implements Comparable<Symbol>, CharSequence
         return symbol;
     }
 
+    public void writeTo(WritableBuffer buffer)
+    {
+        buffer.put(_underlyingBytes, 0, _underlyingBytes.length);
+    }
 
+    public void writeTo(ByteBuffer buffer)
+    {
+        buffer.put(_underlyingBytes, 0, _underlyingBytes.length);
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/AMQPDefinedTypes.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/AMQPDefinedTypes.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/AMQPDefinedTypes.java
index 2e2f9e0..79dea5d 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/AMQPDefinedTypes.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/AMQPDefinedTypes.java
@@ -23,15 +23,6 @@
 
 package org.apache.qpid.proton.codec;
 
-import org.apache.qpid.proton.amqp.transport.Attach;
-import org.apache.qpid.proton.amqp.transport.Begin;
-import org.apache.qpid.proton.amqp.transport.Close;
-import org.apache.qpid.proton.amqp.transport.Detach;
-import org.apache.qpid.proton.amqp.transport.Disposition;
-import org.apache.qpid.proton.amqp.transport.End;
-import org.apache.qpid.proton.amqp.transport.Flow;
-import org.apache.qpid.proton.amqp.transport.Open;
-import org.apache.qpid.proton.amqp.transport.Transfer;
 import org.apache.qpid.proton.codec.messaging.*;
 import org.apache.qpid.proton.codec.security.*;
 import org.apache.qpid.proton.codec.transaction.*;
@@ -47,7 +38,6 @@ public class AMQPDefinedTypes
         registerSecurityTypes(decoder, encoder);
     }
 
-
     public static void registerTransportTypes(Decoder decoder, EncoderImpl encoder)
     {
         OpenType.register(decoder, encoder);
@@ -60,21 +50,25 @@ public class AMQPDefinedTypes
         EndType.register(decoder, encoder);
         CloseType.register(decoder, encoder);
         ErrorConditionType.register(decoder, encoder);
+
+        FastPathFlowType.register(decoder, encoder);
+        FastPathTransferType.register(decoder, encoder);
+        FastPathDispositionType.register(decoder, encoder);
     }
 
     public static void registerMessagingTypes(Decoder decoder, EncoderImpl encoder)
     {
         HeaderType.register(decoder, encoder);
+        AcceptedType.register(decoder , encoder);
+        PropertiesType.register( decoder, encoder );
         DeliveryAnnotationsType.register(decoder, encoder);
         MessageAnnotationsType.register(decoder, encoder);
-        PropertiesType.register( decoder, encoder );
         ApplicationPropertiesType.register(decoder, encoder);
         DataType.register(decoder, encoder);
         AmqpSequenceType.register(decoder, encoder);
         AmqpValueType.register(decoder, encoder);
         FooterType.register(decoder, encoder);
         ReceivedType.register(decoder, encoder);
-        AcceptedType.register(decoder , encoder);
         RejectedType.register(decoder, encoder);
         ReleasedType.register(decoder, encoder);
         ModifiedType.register(decoder, encoder);
@@ -84,6 +78,17 @@ public class AMQPDefinedTypes
         DeleteOnNoLinksType.register(decoder, encoder);
         DeleteOnNoMessagesType.register(decoder, encoder);
         DeleteOnNoLinksOrMessagesType.register(decoder, encoder);
+
+        FastPathHeaderType.register(decoder, encoder);
+        FastPathAcceptedType.register(decoder , encoder);
+        FastPathPropertiesType.register( decoder, encoder );
+        FastPathDeliveryAnnotationsType.register(decoder, encoder);
+        FastPathMessageAnnotationsType.register(decoder, encoder);
+        FastPathApplicationPropertiesType.register(decoder, encoder);
+        FastPathDataType.register(decoder, encoder);
+        FastPathAmqpSequenceType.register(decoder, encoder);
+        FastPathAmqpValueType.register(decoder, encoder);
+        FastPathFooterType.register(decoder, encoder);
     }
 
     public static void registerTransactionTypes(Decoder decoder, EncoderImpl encoder)
@@ -103,5 +108,4 @@ public class AMQPDefinedTypes
         SaslResponseType.register(decoder, encoder);
         SaslOutcomeType.register(decoder, encoder);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/AbstractDescribedType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/AbstractDescribedType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/AbstractDescribedType.java
index d31ac40..2f34fd5 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/AbstractDescribedType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/AbstractDescribedType.java
@@ -28,17 +28,27 @@ import org.apache.qpid.proton.amqp.UnsignedLong;
 
 abstract public class AbstractDescribedType<T,M> implements AMQPType<T>
 {
-
+    private final DecoderImpl _decoder;
     private final EncoderImpl _encoder;
     private final Map<TypeEncoding<M>, TypeEncoding<T>> _encodings = new HashMap<TypeEncoding<M>, TypeEncoding<T>>();
 
     public AbstractDescribedType(EncoderImpl encoder)
     {
         _encoder = encoder;
+        _decoder = encoder.getDecoder();
     }
 
     abstract protected UnsignedLong getDescriptor();
 
+    public EncoderImpl getEncoder()
+    {
+        return _encoder;
+    }
+
+    public DecoderImpl getDecoder()
+    {
+        return _decoder;
+    }
 
     public TypeEncoding<T> getEncoding(final T val)
     {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
index 45b8dd5..32d6f85 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
@@ -21,6 +21,7 @@
 package org.apache.qpid.proton.codec;
 
 import java.lang.reflect.Array;
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -631,8 +632,13 @@ public class ArrayType implements PrimitiveType<Object[]>
             return decodeArrayAsObject(decoder, count);
         }
 
-
-
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
     }
 
 
@@ -891,6 +897,13 @@ public class ArrayType implements PrimitiveType<Object[]>
             return decodeArrayAsObject(decoder, count);
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = ((int)decoder.readRawByte()) & 0xFF;
+            buffer.position(buffer.position() + size);
+        }
     }
 
     private BooleanType.BooleanEncoding getUnderlyingEncoding(final boolean[] a)
@@ -969,7 +982,7 @@ public class ArrayType implements PrimitiveType<Object[]>
 
     private static Object[] decodeArray(final DecoderImpl decoder, final int count)
     {
-        TypeConstructor constructor = decoder.readConstructor();
+        TypeConstructor constructor = decoder.readConstructor(true);
         return decodeNonPrimitive(decoder, constructor, count);
     }
 
@@ -1009,7 +1022,7 @@ public class ArrayType implements PrimitiveType<Object[]>
 
     private static Object decodeArrayAsObject(final DecoderImpl decoder, final int count)
     {
-        TypeConstructor constructor = decoder.readConstructor();
+        TypeConstructor constructor = decoder.readConstructor(true);
         if(constructor.encodesJavaPrimitive())
         {
             if (count > decoder.getByteBufferRemaining()) {

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/BinaryType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/BinaryType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/BinaryType.java
index 88c204f..1d739b8 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/BinaryType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/BinaryType.java
@@ -22,6 +22,7 @@ package org.apache.qpid.proton.codec;
 
 import org.apache.qpid.proton.amqp.Binary;
 
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -53,7 +54,6 @@ public class BinaryType extends AbstractPrimitiveType<Binary>
         return val.getLength() <= 255 ? _shortBinaryEncoding : _binaryEncoding;
     }
 
-
     public BinaryEncoding getCanonicalEncoding()
     {
         return _binaryEncoding;
@@ -64,6 +64,22 @@ public class BinaryType extends AbstractPrimitiveType<Binary>
         return Arrays.asList(_shortBinaryEncoding, _binaryEncoding);
     }
 
+    public void fastWrite(EncoderImpl encoder, Binary binary)
+    {
+        if (binary.getLength() <= 255)
+        {
+            encoder.writeRaw(EncodingCodes.VBIN8);
+            encoder.writeRaw((byte) binary.getLength());
+            encoder.writeRaw(binary.getArray(), binary.getArrayOffset(), binary.getLength());
+        }
+        else
+        {
+            encoder.writeRaw(EncodingCodes.VBIN32);
+            encoder.writeRaw(binary.getLength());
+            encoder.writeRaw(binary.getArray(), binary.getArrayOffset(), binary.getLength());
+        }
+    }
+
     private class LongBinaryEncoding
             extends LargeFloatingSizePrimitiveTypeEncoding<Binary>
             implements BinaryEncoding
@@ -115,6 +131,14 @@ public class BinaryType extends AbstractPrimitiveType<Binary>
             decoder.readRaw(data, 0, size);
             return new Binary(data);
         }
+
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
     }
 
     private class ShortBinaryEncoding
@@ -163,5 +187,12 @@ public class BinaryType extends AbstractPrimitiveType<Binary>
             getDecoder().readRaw(data, 0, size);
             return new Binary(data);
         }
+
+        public void skipValue()
+        {
+            ByteBuffer buffer = getDecoder().getByteBuffer();
+            int size = ((int)getDecoder().readRawByte()) & 0xff;
+            buffer.position(buffer.position() + size);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/Decoder.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/Decoder.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/Decoder.java
index 6053479..b1f47e0 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/Decoder.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/Decoder.java
@@ -145,5 +145,6 @@ public interface Decoder
 
     void register(final Object descriptor, final DescribedTypeConstructor dtc);
 
+    void register(final Object descriptor, final FastPathDescribedTypeConstructor<?> dtc);
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/DecoderImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/DecoderImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/DecoderImpl.java
index dd68f6a..1763129 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/DecoderImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/DecoderImpl.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.codec;
 
+import org.apache.qpid.proton.ProtonException;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Decimal128;
 import org.apache.qpid.proton.amqp.Decimal32;
@@ -31,48 +32,97 @@ import org.apache.qpid.proton.amqp.UnsignedInteger;
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.UnsignedShort;
 
+import java.io.IOException;
 import java.lang.reflect.Array;
 import java.nio.ByteBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.StandardCharsets;
 import java.util.*;
 
 public class DecoderImpl implements ByteBufferDecoder
 {
-
     private ByteBuffer _buffer;
-    private PrimitiveTypeEncoding[] _constructors = new PrimitiveTypeEncoding[256];
-    private Map<Object, DescribedTypeConstructor> _dynamicTypeConstructors =
+
+    private final CharsetDecoder _charsetDecoder = StandardCharsets.UTF_8.newDecoder();
+
+    private final PrimitiveTypeEncoding[] _constructors = new PrimitiveTypeEncoding[256];
+    private final Map<Object, DescribedTypeConstructor> _dynamicTypeConstructors =
             new HashMap<Object, DescribedTypeConstructor>();
 
+    private final Map<Object, FastPathDescribedTypeConstructor<?>> _fastPathTypeConstructors =
+        new HashMap<Object, FastPathDescribedTypeConstructor<?>>();
 
     public DecoderImpl()
     {
     }
 
-
     DecoderImpl(final ByteBuffer buffer)
     {
         _buffer = buffer;
     }
 
-    TypeConstructor readConstructor()
+    public TypeConstructor<?> peekConstructor()
+    {
+        _buffer.mark();
+        try
+        {
+            return readConstructor();
+        }
+        finally
+        {
+            _buffer.reset();
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public TypeConstructor readConstructor()
+    {
+        return readConstructor(false);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public TypeConstructor readConstructor(boolean excludeFastPathConstructors)
     {
         int code = ((int)readRawByte()) & 0xff;
         if(code == EncodingCodes.DESCRIBED_TYPE_INDICATOR)
         {
-            final Object descriptor = readObject();
-            TypeConstructor nestedEncoding = readConstructor();
-            DescribedTypeConstructor dtc = _dynamicTypeConstructors.get(descriptor);
+            final byte encoding = _buffer.get(_buffer.position());
+            final Object descriptor;
+
+            if (EncodingCodes.SMALLULONG == encoding || EncodingCodes.ULONG == encoding)
+            {
+                descriptor = readUnsignedLong();
+            }
+            else if (EncodingCodes.SYM8 == encoding || EncodingCodes.SYM32 == encoding)
+            {
+                descriptor = readSymbol();
+            }
+            else
+            {
+                descriptor = readObject();
+            }
+
+            if (!excludeFastPathConstructors)
+            {
+                TypeConstructor<?> fastPathTypeConstructor = _fastPathTypeConstructors.get(descriptor);
+                if (fastPathTypeConstructor != null)
+                {
+                    return fastPathTypeConstructor;
+                }
+            }
+
+            TypeConstructor<?> nestedEncoding = readConstructor();
+            DescribedTypeConstructor<?> dtc = _dynamicTypeConstructors.get(descriptor);
             if(dtc == null)
             {
                 dtc = new DescribedTypeConstructor()
                 {
-
                     public DescribedType newInstance(final Object described)
                     {
                         return new UnknownDescribedType(descriptor, described);
                     }
 
-                    public Class getTypeClass()
+                    public Class<?> getTypeClass()
                     {
                         return UnknownDescribedType.class;
                     }
@@ -87,8 +137,15 @@ public class DecoderImpl implements ByteBufferDecoder
         }
     }
 
+    public void register(final Object descriptor, final FastPathDescribedTypeConstructor<?> btc)
+    {
+        _fastPathTypeConstructors.put(descriptor, btc);
+    }
+
     public void register(final Object descriptor, final DescribedTypeConstructor dtc)
     {
+        // Allow external type constructors to replace the built-in instances.
+        _fastPathTypeConstructors.remove(descriptor);
         _dynamicTypeConstructors.put(descriptor, dtc);
     }
 
@@ -108,37 +165,39 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Boolean readBoolean(final Boolean defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof Boolean)
+        byte encodingCode = _buffer.get();
+
+        switch (encodingCode)
         {
-            return (Boolean) val;
+            case EncodingCodes.BOOLEAN_TRUE:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN_TRUE & 0xff].readValue();
+            case EncodingCodes.BOOLEAN_FALSE:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN_FALSE & 0xff].readValue();
+            case EncodingCodes.BOOLEAN:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected boolean type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Boolean.class);
     }
 
     public boolean readBoolean(final boolean defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
-        if(constructor instanceof BooleanType.BooleanEncoding)
-        {
-            return ((BooleanType.BooleanEncoding)constructor).readPrimitiveValue();
-        }
-        else
+        byte encodingCode = _buffer.get();
+
+        switch (encodingCode)
         {
-            Object val = constructor.readValue();
-            if(val == null)
-            {
+            case EncodingCodes.BOOLEAN_TRUE:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN_TRUE & 0xff].readValue();
+            case EncodingCodes.BOOLEAN_FALSE:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN_FALSE & 0xff].readValue();
+            case EncodingCodes.BOOLEAN:
+                return (Boolean) _constructors[EncodingCodes.BOOLEAN & 0xff].readValue();
+            case EncodingCodes.NULL:
                 return defaultVal;
-            }
-            else
-            {
-                throw unexpectedType(val, Boolean.class);
-            }
+            default:
+                throw new DecodeException("Expected boolean type but found encoding: " + encodingCode);
         }
     }
 
@@ -149,17 +208,16 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Byte readByte(final Byte defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof Byte)
-        {
-            return (Byte) val;
+        byte encodingCode = _buffer.get();
+
+        switch (encodingCode) {
+            case EncodingCodes.BYTE:
+                return (Byte) _constructors[EncodingCodes.BYTE & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected byte type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Byte.class);
     }
 
     public byte readByte(final byte defaultVal)
@@ -190,18 +248,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Short readShort(final Short defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof Short)
+        byte encodingCode = _buffer.get();
+
+        switch (encodingCode)
         {
-            return (Short) val;
+            case EncodingCodes.SHORT:
+                return (Short) _constructors[EncodingCodes.SHORT & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected Short type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Short.class);
-
     }
 
     public short readShort(final short defaultVal)
@@ -233,18 +290,19 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Integer readInteger(final Integer defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof Integer)
+        byte encodingCode = _buffer.get();
+
+        switch (encodingCode)
         {
-            return (Integer) val;
+            case EncodingCodes.SMALLINT:
+                return (Integer) _constructors[EncodingCodes.SMALLINT & 0xff].readValue();
+            case EncodingCodes.INT:
+                return (Integer) _constructors[EncodingCodes.INT & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected Integer type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Integer.class);
-
     }
 
     public int readInteger(final int defaultVal)
@@ -276,19 +334,19 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Long readLong(final Long defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof Long)
+        switch (encodingCode)
         {
-            return (Long) val;
+            case EncodingCodes.SMALLLONG:
+                return (Long) _constructors[EncodingCodes.SMALLLONG & 0xff].readValue();
+            case EncodingCodes.LONG:
+                return (Long) _constructors[EncodingCodes.LONG & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected Long type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Long.class);
-
     }
 
     public long readLong(final long defaultVal)
@@ -320,19 +378,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public UnsignedByte readUnsignedByte(final UnsignedByte defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof UnsignedByte)
+        switch (encodingCode)
         {
-            return (UnsignedByte) val;
+            case EncodingCodes.UBYTE:
+                return (UnsignedByte) _constructors[EncodingCodes.UBYTE & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected unsigned byte type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, UnsignedByte.class);
-
     }
 
     public UnsignedShort readUnsignedShort()
@@ -342,19 +398,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public UnsignedShort readUnsignedShort(final UnsignedShort defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultVal;
-        }
-        else if(val instanceof UnsignedShort)
+        switch (encodingCode)
         {
-            return (UnsignedShort) val;
+            case EncodingCodes.USHORT:
+                return (UnsignedShort) _constructors[EncodingCodes.USHORT & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected UnsignedShort type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, UnsignedShort.class);
-
     }
 
     public UnsignedInteger readUnsignedInteger()
@@ -364,19 +418,21 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public UnsignedInteger readUnsignedInteger(final UnsignedInteger defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof UnsignedInteger)
-        {
-            return (UnsignedInteger) val;
+            case EncodingCodes.UINT0:
+                return (UnsignedInteger) _constructors[EncodingCodes.UINT0 & 0xff].readValue();
+            case EncodingCodes.SMALLUINT:
+                return (UnsignedInteger) _constructors[EncodingCodes.SMALLUINT & 0xff].readValue();
+            case EncodingCodes.UINT:
+                return (UnsignedInteger) _constructors[EncodingCodes.UINT & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected UnsignedInteger type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, UnsignedInteger.class);
-
     }
 
     public UnsignedLong readUnsignedLong()
@@ -386,19 +442,21 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public UnsignedLong readUnsignedLong(final UnsignedLong defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof UnsignedLong)
-        {
-            return (UnsignedLong) val;
+            case EncodingCodes.ULONG0:
+                return (UnsignedLong) _constructors[EncodingCodes.ULONG0 & 0xff].readValue();
+            case EncodingCodes.SMALLULONG:
+                return (UnsignedLong) _constructors[EncodingCodes.SMALLULONG & 0xff].readValue();
+            case EncodingCodes.ULONG:
+                return (UnsignedLong) _constructors[EncodingCodes.ULONG & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected UnsignedLong type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, UnsignedLong.class);
-
     }
 
     public Character readCharacter()
@@ -408,40 +466,31 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Character readCharacter(final Character defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof Character)
-        {
-            return (Character) val;
+            case EncodingCodes.CHAR:
+                return (Character) _constructors[EncodingCodes.CHAR & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new DecodeException("Expected Character type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Character.class);
-
     }
 
     public char readCharacter(final char defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        if(constructor instanceof CharacterType.CharacterEncoding)
-        {
-            return ((CharacterType.CharacterEncoding)constructor).readPrimitiveValue();
-        }
-        else
+        switch (encodingCode)
         {
-            Object val = constructor.readValue();
-            if(val == null)
-            {
+            case EncodingCodes.CHAR:
+                return (Character) _constructors[EncodingCodes.CHAR & 0xff].readValue();
+            case EncodingCodes.NULL:
                 return defaultVal;
-            }
-            else
-            {
-                throw unexpectedType(val, Character.class);
-            }
+            default:
+                throw new DecodeException("Expected Character type but found encoding: " + encodingCode);
         }
     }
 
@@ -452,19 +501,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Float readFloat(final Float defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof Float)
-        {
-            return (Float) val;
+            case EncodingCodes.FLOAT:
+                return (Float) _constructors[EncodingCodes.FLOAT & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new ProtonException("Expected Float type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Float.class);
-
     }
 
     public float readFloat(final float defaultVal)
@@ -496,19 +543,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Double readDouble(final Double defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof Double)
-        {
-            return (Double) val;
+            case EncodingCodes.DOUBLE:
+                return (Double) _constructors[EncodingCodes.DOUBLE & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new ProtonException("Expected Double type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Double.class);
-
     }
 
     public double readDouble(final double defaultVal)
@@ -540,19 +585,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public UUID readUUID(final UUID defaultVal)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultVal;
-        }
-        else if(val instanceof UUID)
-        {
-            return (UUID) val;
+            case EncodingCodes.UUID:
+                return (UUID) _constructors[EncodingCodes.UUID & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultVal;
+            default:
+                throw new ProtonException("Expected UUID type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, UUID.class);
-
     }
 
     public Decimal32 readDecimal32()
@@ -562,19 +605,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Decimal32 readDecimal32(final Decimal32 defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultValue;
-        }
-        else if(val instanceof Decimal32)
+        switch (encodingCode)
         {
-            return (Decimal32) val;
+            case EncodingCodes.DECIMAL32:
+                return (Decimal32) _constructors[EncodingCodes.DECIMAL32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Decimal32 type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Decimal32.class);
-
     }
 
     public Decimal64 readDecimal64()
@@ -584,18 +625,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Decimal64 readDecimal64(final Decimal64 defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultValue;
+            case EncodingCodes.DECIMAL64:
+                return (Decimal64) _constructors[EncodingCodes.DECIMAL64 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Decimal64 type but found encoding: " + encodingCode);
         }
-        else if(val instanceof Decimal64)
-        {
-            return (Decimal64) val;
-        }
-        throw unexpectedType(val, Decimal64.class);
     }
 
     public Decimal128 readDecimal128()
@@ -605,18 +645,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Decimal128 readDecimal128(final Decimal128 defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultValue;
-        }
-        else if(val instanceof Decimal128)
+        switch (encodingCode)
         {
-            return (Decimal128) val;
+            case EncodingCodes.DECIMAL128:
+                return (Decimal128) _constructors[EncodingCodes.DECIMAL128 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Decimal128 type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Decimal128.class);
     }
 
     public Date readTimestamp()
@@ -626,18 +665,17 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Date readTimestamp(final Date defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultValue;
+            case EncodingCodes.TIMESTAMP:
+                return (Date) _constructors[EncodingCodes.TIMESTAMP & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Timestamp type but found encoding: " + encodingCode);
         }
-        else if(val instanceof Date)
-        {
-            return (Date) val;
-        }
-        throw unexpectedType(val, Date.class);
     }
 
     public Binary readBinary()
@@ -647,18 +685,19 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Binary readBinary(final Binary defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultValue;
+            case EncodingCodes.VBIN8:
+                return (Binary) _constructors[EncodingCodes.VBIN8 & 0xff].readValue();
+            case EncodingCodes.VBIN32:
+                return (Binary) _constructors[EncodingCodes.VBIN32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Binary type but found encoding: " + encodingCode);
         }
-        else if(val instanceof Binary)
-        {
-            return (Binary) val;
-        }
-        throw unexpectedType(val, Binary.class);
     }
 
     public Symbol readSymbol()
@@ -668,18 +707,19 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Symbol readSymbol(final Symbol defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return defaultValue;
-        }
-        else if(val instanceof Symbol)
+        switch (encodingCode)
         {
-            return (Symbol) val;
+            case EncodingCodes.SYM8:
+                return (Symbol) _constructors[EncodingCodes.SYM8 & 0xff].readValue();
+            case EncodingCodes.SYM32:
+                return (Symbol) _constructors[EncodingCodes.SYM32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected Symbol type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Symbol.class);
     }
 
     public String readString()
@@ -689,34 +729,39 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public String readString(final String defaultValue)
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
+        switch (encodingCode)
         {
-            return defaultValue;
+            case EncodingCodes.STR8:
+                return (String) _constructors[EncodingCodes.STR8 & 0xff].readValue();
+            case EncodingCodes.STR32:
+                return (String) _constructors[EncodingCodes.STR32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return defaultValue;
+            default:
+                throw new ProtonException("Expected String type but found encoding: " + encodingCode);
         }
-        else if(val instanceof String)
-        {
-            return (String) val;
-        }
-        throw unexpectedType(val, String.class);
     }
 
+    @SuppressWarnings("rawtypes")
     public List readList()
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return null;
-        }
-        else if(val instanceof List)
+        switch (encodingCode)
         {
-            return (List) val;
+            case EncodingCodes.LIST0:
+                return (List) _constructors[EncodingCodes.LIST0 & 0xff].readValue();
+            case EncodingCodes.LIST8:
+                return (List) _constructors[EncodingCodes.LIST8 & 0xff].readValue();
+            case EncodingCodes.LIST32:
+                return (List) _constructors[EncodingCodes.LIST32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return null;
+            default:
+                throw new ProtonException("Expected List type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, List.class);
     }
 
     public <T> void readList(final ListProcessor<T> processor)
@@ -724,20 +769,22 @@ public class DecoderImpl implements ByteBufferDecoder
         //TODO.
     }
 
+    @SuppressWarnings("rawtypes")
     public Map readMap()
     {
+        byte encodingCode = _buffer.get();
 
-        TypeConstructor constructor = readConstructor();
-        Object val = constructor.readValue();
-        if(val == null)
-        {
-            return null;
-        }
-        else if(val instanceof Map)
+        switch (encodingCode)
         {
-            return (Map) val;
+            case EncodingCodes.MAP8:
+                return (Map) _constructors[EncodingCodes.MAP8 & 0xff].readValue();
+            case EncodingCodes.MAP32:
+                return (Map) _constructors[EncodingCodes.MAP32 & 0xff].readValue();
+            case EncodingCodes.NULL:
+                return null;
+            default:
+                throw new ProtonException("Expected Map type but found encoding: " + encodingCode);
         }
-        throw unexpectedType(val, Map.class);
     }
 
     public <T> T[] readArray(final Class<T> clazz)
@@ -877,14 +924,26 @@ public class DecoderImpl implements ByteBufferDecoder
 
     public Object readObject()
     {
+        boolean arrayType = false;
+        byte code = _buffer.get(_buffer.position());
+        switch (code)
+        {
+            case EncodingCodes.ARRAY8:
+            case EncodingCodes.ARRAY32:
+                arrayType = true;
+        }
+
         TypeConstructor constructor = readConstructor();
         if(constructor== null)
         {
             throw new DecodeException("Unknown constructor");
         }
-        return constructor instanceof ArrayType.ArrayEncoding
-               ? ((ArrayType.ArrayEncoding)constructor).readValueArray()
-               : constructor.readValue();
+
+        if (arrayType) {
+            return ((ArrayType.ArrayEncoding)constructor).readValueArray();
+        } else {
+            return constructor.readValue();
+        }
     }
 
     public Object readObject(final Object defaultValue)
@@ -942,7 +1001,7 @@ public class DecoderImpl implements ByteBufferDecoder
 
     <V> V readRaw(TypeDecoder<V> decoder, int size)
     {
-        V decode = decoder.decode((ByteBuffer) _buffer.slice().limit(size));
+        V decode = decoder.decode(this, (ByteBuffer) _buffer.slice().limit(size));
         _buffer.position(_buffer.position()+size);
         return decode;
     }
@@ -952,9 +1011,19 @@ public class DecoderImpl implements ByteBufferDecoder
         _buffer = buffer;
     }
 
+    public ByteBuffer getByteBuffer()
+    {
+        return _buffer;
+    }
+
+    CharsetDecoder getCharsetDecoder()
+    {
+        return _charsetDecoder;
+    }
+
     interface TypeDecoder<V>
     {
-        V decode(ByteBuffer buf);
+        V decode(DecoderImpl decoder, ByteBuffer buf);
     }
 
     private static class UnknownDescribedType implements DescribedType

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/DynamicTypeConstructor.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/DynamicTypeConstructor.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/DynamicTypeConstructor.java
index 0cee927..2f8b9f9 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/DynamicTypeConstructor.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/DynamicTypeConstructor.java
@@ -53,6 +53,11 @@ public class DynamicTypeConstructor implements TypeConstructor
         return false;
     }
 
+    public void skipValue()
+    {
+        _underlyingEncoding.skipValue();
+    }
+
     public Class getTypeClass()
     {
         return _describedTypeConstructor.getTypeClass();

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/EncoderImpl.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/EncoderImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/EncoderImpl.java
index 97e1005..7bef1ae 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/EncoderImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/EncoderImpl.java
@@ -42,9 +42,9 @@ public final class EncoderImpl implements ByteBufferEncoder
 {
     private static final byte DESCRIBED_TYPE_OP = (byte)0;
 
-
     private WritableBuffer _buffer;
 
+    private final DecoderImpl _decoder;
     private final Map<Class, AMQPType> _typeRegistry = new HashMap<Class, AMQPType>();
     private Map<Object, AMQPType> _describedDescriptorRegistry = new HashMap<Object, AMQPType>();
     private Map<Class, AMQPType>  _describedTypesClassRegistry = new HashMap<Class, AMQPType>();
@@ -88,7 +88,7 @@ public final class EncoderImpl implements ByteBufferEncoder
 
     public EncoderImpl(DecoderImpl decoder)
     {
-
+        _decoder                = decoder;
         _nullType               = new NullType(this, decoder);
         _booleanType            = new BooleanType(this, decoder);
         _byteType               = new ByteType(this, decoder);
@@ -143,36 +143,32 @@ public final class EncoderImpl implements ByteBufferEncoder
         _buffer = buf;
     }
 
+    public WritableBuffer getBuffer()
+    {
+        return _buffer;
+    }
+
+    public DecoderImpl getDecoder()
+    {
+        return _decoder;
+    }
 
     @Override
     public AMQPType getType(final Object element)
     {
-        if(element instanceof DescribedType)
-        {
-            AMQPType amqpType;
-
-            Object descriptor = ((DescribedType)element).getDescriptor();
-            amqpType = _describedDescriptorRegistry.get(descriptor);
-            if(amqpType == null)
-            {
-                amqpType = new DynamicDescribedType(this, descriptor);
-                _describedDescriptorRegistry.put(descriptor, amqpType);
-            }
-            return amqpType;
-
-        }
-        else
-        {
-            return getTypeFromClass(element == null ? Void.class : element.getClass());
-        }
+        return getTypeFromClass(element == null ? Void.class : element.getClass(), element);
     }
 
     public AMQPType getTypeFromClass(final Class clazz)
     {
+        return getTypeFromClass(clazz, null);
+    }
+
+    private AMQPType getTypeFromClass(final Class clazz, Object instance)
+    {
         AMQPType amqpType = _typeRegistry.get(clazz);
         if(amqpType == null)
         {
-
             if(clazz.isArray())
             {
                 amqpType = _arrayType;
@@ -190,10 +186,21 @@ public final class EncoderImpl implements ByteBufferEncoder
                 else if(DescribedType.class.isAssignableFrom(clazz))
                 {
                     amqpType = _describedTypesClassRegistry.get(clazz);
+                    if(amqpType == null && instance != null)
+                    {
+                        Object descriptor = ((DescribedType) instance).getDescriptor();
+                        amqpType = _describedDescriptorRegistry.get(descriptor);
+                        if(amqpType == null)
+                        {
+                            amqpType = new DynamicDescribedType(this, descriptor);
+                            _describedDescriptorRegistry.put(descriptor, amqpType);
+                        }
+                    }
                 }
             }
             _typeRegistry.put(clazz, amqpType);
         }
+
         return amqpType;
     }
 
@@ -221,12 +228,19 @@ public final class EncoderImpl implements ByteBufferEncoder
 
     public void writeNull()
     {
-        _nullType.write();
+        _buffer.put(EncodingCodes.NULL);
     }
 
     public void writeBoolean(final boolean bool)
     {
-        _booleanType.writeValue(bool);
+        if (bool)
+        {
+            _buffer.put(EncodingCodes.BOOLEAN_TRUE);
+        }
+        else
+        {
+            _buffer.put(EncodingCodes.BOOLEAN_FALSE);
+        }
     }
 
     public void writeBoolean(final Boolean bool)
@@ -235,9 +249,13 @@ public final class EncoderImpl implements ByteBufferEncoder
         {
             writeNull();
         }
+        else if (Boolean.TRUE.equals(bool))
+        {
+            _buffer.put(EncodingCodes.BOOLEAN_TRUE);
+        }
         else
         {
-            _booleanType.write(bool);
+            _buffer.put(EncodingCodes.BOOLEAN_FALSE);
         }
     }
 
@@ -249,7 +267,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _unsignedByteType.write(ubyte);
+            _unsignedByteType.fastWrite(this, ubyte);
         }
     }
 
@@ -261,7 +279,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _unsignedShortType.write(ushort);
+            _unsignedShortType.fastWrite(this, ushort);
         }
     }
 
@@ -273,7 +291,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _unsignedIntegerType.write(uint);
+            _unsignedIntegerType.fastWrite(this, uint);
         }
     }
 
@@ -285,7 +303,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _unsignedLongType.write(ulong);
+            _unsignedLongType.fastWrite(this, ulong);
         }
     }
 
@@ -446,9 +464,9 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
     }
 
-    public void writeTimestamp(final long d)
+    public void writeTimestamp(final long timestamp)
     {
-        _timestampType.write(d);
+        _timestampType.fastWrite(this, timestamp);
     }
 
     public void writeTimestamp(final Date d)
@@ -459,7 +477,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            writeTimestamp(d.getTime());
+            _timestampType.fastWrite(this, d.getTime());
         }
     }
 
@@ -471,7 +489,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _uuidType.write(uuid);
+            _uuidType.fastWrite(this, uuid);
         }
 
     }
@@ -484,7 +502,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _binaryType.write(b);
+            _binaryType.fastWrite(this, b);
         }
     }
 
@@ -508,7 +526,7 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
         else
         {
-            _symbolType.write(s);
+            _symbolType.fastWrite(this, s);
         }
 
     }
@@ -662,56 +680,19 @@ public final class EncoderImpl implements ByteBufferEncoder
 
     public void writeObject(final Object o)
     {
-        AMQPType type = _typeRegistry.get(o == null ? Void.class : o.getClass());
+        if (o == null)
+        {
+            getBuffer().put(EncodingCodes.NULL);
+            return;
+        }
+
+        AMQPType type = _typeRegistry.get(o.getClass());
 
         if(type == null)
         {
             if(o.getClass().isArray())
             {
-                Class<?> componentType = o.getClass().getComponentType();
-                if(componentType.isPrimitive())
-                {
-                    if(componentType == Boolean.TYPE)
-                    {
-                        writeArray((boolean[])o);
-                    }
-                    else if(componentType == Byte.TYPE)
-                    {
-                        writeArray((byte[])o);
-                    }
-                    else if(componentType == Short.TYPE)
-                    {
-                        writeArray((short[])o);
-                    }
-                    else if(componentType == Integer.TYPE)
-                    {
-                        writeArray((int[])o);
-                    }
-                    else if(componentType == Long.TYPE)
-                    {
-                        writeArray((long[])o);
-                    }
-                    else if(componentType == Float.TYPE)
-                    {
-                        writeArray((float[])o);
-                    }
-                    else if(componentType == Double.TYPE)
-                    {
-                        writeArray((double[])o);
-                    }
-                    else if(componentType == Character.TYPE)
-                    {
-                        writeArray((char[])o);
-                    }
-                    else
-                    {
-                        throw new IllegalArgumentException("Cannot write arrays of type " + componentType.getName());
-                    }
-                }
-                else
-                {
-                    writeArray((Object[]) o);
-                }
+                writeArrayType(o);
             }
             else if(o instanceof List)
             {
@@ -727,9 +708,8 @@ public final class EncoderImpl implements ByteBufferEncoder
             }
             else
             {
-                throw new IllegalArgumentException("Do not know how to write Objects of class " + o.getClass()
-                                                                                                       .getName());
-
+                throw new IllegalArgumentException(
+                    "Do not know how to write Objects of class " + o.getClass().getName());
             }
         }
         else
@@ -738,6 +718,53 @@ public final class EncoderImpl implements ByteBufferEncoder
         }
     }
 
+    private void writeArrayType(Object array) {
+        Class<?> componentType = array.getClass().getComponentType();
+        if(componentType.isPrimitive())
+        {
+            if(componentType == Boolean.TYPE)
+            {
+                writeArray((boolean[])array);
+            }
+            else if(componentType == Byte.TYPE)
+            {
+                writeArray((byte[])array);
+            }
+            else if(componentType == Short.TYPE)
+            {
+                writeArray((short[])array);
+            }
+            else if(componentType == Integer.TYPE)
+            {
+                writeArray((int[])array);
+            }
+            else if(componentType == Long.TYPE)
+            {
+                writeArray((long[])array);
+            }
+            else if(componentType == Float.TYPE)
+            {
+                writeArray((float[])array);
+            }
+            else if(componentType == Double.TYPE)
+            {
+                writeArray((double[])array);
+            }
+            else if(componentType == Character.TYPE)
+            {
+                writeArray((char[])array);
+            }
+            else
+            {
+                throw new IllegalArgumentException("Cannot write arrays of type " + componentType.getName());
+            }
+        }
+        else
+        {
+            writeArray((Object[]) array);
+        }
+    }
+
     public void writeRaw(final byte b)
     {
         _buffer.put(b);
@@ -814,4 +841,9 @@ public final class EncoderImpl implements ByteBufferEncoder
             }
         }
     }
+
+    AMQPType getNullTypeEncoder()
+    {
+        return _nullType;
+    }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/FastPathDescribedTypeConstructor.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/FastPathDescribedTypeConstructor.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/FastPathDescribedTypeConstructor.java
new file mode 100644
index 0000000..13b3c80
--- /dev/null
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/FastPathDescribedTypeConstructor.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.qpid.proton.codec;
+
+/**
+ * Marker interface that indicates the TypeConstructor can decode known Proton-J types
+ * using a fast path read / write operation.  These types may result in an encode that
+ * does not always write the smallest form of the given type to save time.
+ *
+ * @param <V> The type that this constructor handles
+ */
+public interface FastPathDescribedTypeConstructor<V> extends TypeConstructor<V> {
+
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/FixedSizePrimitiveTypeEncoding.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/FixedSizePrimitiveTypeEncoding.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/FixedSizePrimitiveTypeEncoding.java
index 2762064..7c055ae 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/FixedSizePrimitiveTypeEncoding.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/FixedSizePrimitiveTypeEncoding.java
@@ -38,5 +38,10 @@ abstract class FixedSizePrimitiveTypeEncoding<T> extends AbstractPrimitiveTypeEn
         return getFixedSize();
     }
 
+    public final void skipValue()
+    {
+        getDecoder().getByteBuffer().position(getDecoder().getByteBuffer().position() + getFixedSize());
+    }
+
     protected abstract int getFixedSize();
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/ListType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/ListType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/ListType.java
index 185373f..67e9d6e 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/ListType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/ListType.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.codec;
 
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -55,10 +56,9 @@ public class ListType extends AbstractPrimitiveType<List>
 
     public ListEncoding getEncoding(final List val)
     {
-
         int calculatedSize = calculateSize(val, _encoder);
-        ListEncoding encoding = val.isEmpty() 
-                                    ? _zeroListEncoding 
+        ListEncoding encoding = val.isEmpty()
+                                    ? _zeroListEncoding
                                     : (val.size() > 255 || calculatedSize >= 254)
                                         ? _listEncoding
                                         : _shortListEncoding;
@@ -86,7 +86,6 @@ public class ListType extends AbstractPrimitiveType<List>
         return len;
     }
 
-
     public ListEncoding getCanonicalEncoding()
     {
         return _listEncoding;
@@ -152,6 +151,8 @@ public class ListType extends AbstractPrimitiveType<List>
         public List readValue()
         {
             DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+
             int size = decoder.readRawInt();
             // todo - limit the decoder with size
             int count = decoder.readRawInt();
@@ -160,14 +161,78 @@ public class ListType extends AbstractPrimitiveType<List>
                 throw new IllegalArgumentException("List element count "+count+" is specified to be greater than the amount of data available ("+
                                                    decoder.getByteBufferRemaining()+")");
             }
-            List list = new ArrayList(count);
-            for(int i = 0; i < count; i++)
+
+            TypeConstructor<?> typeConstructor = null;
+
+            List<Object> list = new ArrayList<>(count);
+            for (int i = 0; i < count; i++)
             {
-                list.add(decoder.readObject());
+                boolean arrayType = false;
+                byte code = buffer.get(buffer.position());
+                switch (code)
+                {
+                    case EncodingCodes.ARRAY8:
+                    case EncodingCodes.ARRAY32:
+                        arrayType = true;
+                }
+
+                // Whenever we can just reuse the previously used TypeDecoder instead
+                // of spending time looking up the same one again.
+                if (typeConstructor == null)
+                {
+                    typeConstructor = getDecoder().readConstructor();
+                }
+                else
+                {
+                    buffer.mark();
+
+                    byte encodingCode = buffer.get();
+                    if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(typeConstructor instanceof PrimitiveTypeEncoding<?>))
+                    {
+                        buffer.reset();
+                        typeConstructor = getDecoder().readConstructor();
+                    }
+                    else
+                    {
+                        PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) typeConstructor;
+                        if (encodingCode != primitiveConstructor.getEncodingCode())
+                        {
+                            buffer.reset();
+                            typeConstructor = getDecoder().readConstructor();
+                        }
+                    }
+                }
+
+                if(typeConstructor == null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                final Object value;
+
+                if (arrayType)
+                {
+                    value = ((ArrayType.ArrayEncoding) typeConstructor).readValueArray();
+                }
+                else
+                {
+                    value = typeConstructor.readValue();
+                }
+
+                list.add(value);
             }
+
             return list;
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
+
         public void setValue(final List value, final int length)
         {
             _value = value;
@@ -229,19 +294,84 @@ public class ListType extends AbstractPrimitiveType<List>
 
         public List readValue()
         {
-
             DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+
             int size = ((int)decoder.readRawByte()) & 0xff;
             // todo - limit the decoder with size
             int count = ((int)decoder.readRawByte()) & 0xff;
-            List list = new ArrayList(count);
-            for(int i = 0; i < count; i++)
+
+            TypeConstructor<?> typeConstructor = null;
+
+            List<Object> list = new ArrayList<>(count);
+            for (int i = 0; i < count; i++)
             {
-                list.add(decoder.readObject());
+                boolean arrayType = false;
+                byte code = buffer.get(buffer.position());
+                switch (code)
+                {
+                    case EncodingCodes.ARRAY8:
+                    case EncodingCodes.ARRAY32:
+                        arrayType = true;
+                }
+
+                // Whenever we can just reuse the previously used TypeDecoder instead
+                // of spending time looking up the same one again.
+                if (typeConstructor == null)
+                {
+                    typeConstructor = getDecoder().readConstructor();
+                }
+                else
+                {
+                    buffer.mark();
+
+                    byte encodingCode = buffer.get();
+                    if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(typeConstructor instanceof PrimitiveTypeEncoding<?>))
+                    {
+                        buffer.reset();
+                        typeConstructor = getDecoder().readConstructor();
+                    }
+                    else
+                    {
+                        PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) typeConstructor;
+                        if (encodingCode != primitiveConstructor.getEncodingCode())
+                        {
+                            buffer.reset();
+                            typeConstructor = getDecoder().readConstructor();
+                        }
+                    }
+                }
+
+                if (typeConstructor == null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                final Object value;
+
+                if (arrayType)
+                {
+                    value = ((ArrayType.ArrayEncoding) typeConstructor).readValueArray();
+                }
+                else
+                {
+                    value = typeConstructor.readValue();
+                }
+
+                list.add(value);
             }
+
             return list;
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = ((int)decoder.readRawByte()) & 0xff;
+            buffer.position(buffer.position() + size);
+        }
+
         public void setValue(final List value, final int length)
         {
             _value = value;
@@ -249,7 +379,7 @@ public class ListType extends AbstractPrimitiveType<List>
         }
     }
 
-    
+
     private class ZeroListEncoding
             extends FixedSizePrimitiveTypeEncoding<List>
             implements ListEncoding
@@ -271,7 +401,6 @@ public class ListType extends AbstractPrimitiveType<List>
             return 0;
         }
 
-
         public ListType getType()
         {
            return ListType.this;
@@ -294,7 +423,5 @@ public class ListType extends AbstractPrimitiveType<List>
         {
             return Collections.EMPTY_LIST;
         }
-
-
     }
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/2a2d3ff2/proton-j/src/main/java/org/apache/qpid/proton/codec/MapType.java
----------------------------------------------------------------------
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/MapType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/MapType.java
index 5c8a7c7..eba075a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/MapType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/MapType.java
@@ -20,7 +20,13 @@
  */
 package org.apache.qpid.proton.codec;
 
-import java.util.*;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class MapType extends AbstractPrimitiveType<Map>
 {
@@ -28,6 +34,8 @@ public class MapType extends AbstractPrimitiveType<Map>
     private final MapEncoding _shortMapEncoding;
     private EncoderImpl _encoder;
 
+    private AMQPType fixedKeyType;
+
     private static interface MapEncoding extends PrimitiveTypeEncoding<Map>
     {
         void setValue(Map value, int length);
@@ -42,15 +50,21 @@ public class MapType extends AbstractPrimitiveType<Map>
         decoder.register(this);
     }
 
+    @Override
     public Class<Map> getTypeClass()
     {
         return Map.class;
     }
 
-    public MapEncoding getEncoding(final Map val)
+    public void setKeyEncoding(AMQPType<?> keyType)
     {
+        this.fixedKeyType = keyType;
+    }
 
-        int calculatedSize = calculateSize(val, _encoder);
+    @Override
+    public MapEncoding getEncoding(final Map val)
+    {
+        int calculatedSize = calculateSize(val, _encoder, fixedKeyType);
         MapEncoding encoding = (val.size() > 127 || calculatedSize >= 254)
                                     ? _mapEncoding
                                     : _shortMapEncoding;
@@ -59,29 +73,78 @@ public class MapType extends AbstractPrimitiveType<Map>
         return encoding;
     }
 
-    private static int calculateSize(final Map val, EncoderImpl encoder)
+    private static int calculateSize(final Map map, EncoderImpl encoder, AMQPType<?> fixedKeyType)
     {
         int len = 0;
-        Iterator<Map.Entry> iter = val.entrySet().iterator();
+        Iterator<Map.Entry> iter = map.entrySet().iterator();
 
-        while(iter.hasNext())
+        while (iter.hasNext())
         {
             Map.Entry element = iter.next();
-            TypeEncoding elementEncoding = encoder.getType(element.getKey()).getEncoding(element.getKey());
+
+            AMQPType keyType = fixedKeyType;
+            if (fixedKeyType == null)
+            {
+                keyType = encoder.getType(element.getKey());
+            }
+
+            TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
             len += elementEncoding.getConstructorSize()+elementEncoding.getValueSize(element.getKey());
             elementEncoding = encoder.getType(element.getValue()).getEncoding(element.getValue());
             len += elementEncoding.getConstructorSize()+elementEncoding.getValueSize(element.getValue());
-
         }
         return len;
     }
 
+    private AMQPType<?> getKeyEncoding(EncoderImpl encoder, Object key)
+    {
+        if (fixedKeyType != null)
+        {
+            return fixedKeyType;
+        }
+        else
+        {
+            return encoder.getType(key);
+        }
+    }
 
+    private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ByteBuffer buffer, TypeConstructor<?> previousConstructor)
+    {
+        if (previousConstructor == null)
+        {
+            return decoder.readConstructor();
+        }
+        else
+        {
+            buffer.mark();
+
+            byte encodingCode = buffer.get();
+            if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>))
+            {
+                buffer.reset();
+                return decoder.readConstructor();
+            }
+            else
+            {
+                PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
+                if (encodingCode != primitiveConstructor.getEncodingCode())
+                {
+                    buffer.reset();
+                    return decoder.readConstructor();
+                }
+            }
+        }
+
+        return previousConstructor;
+    }
+
+    @Override
     public MapEncoding getCanonicalEncoding()
     {
         return _mapEncoding;
     }
 
+    @Override
     public Collection<MapEncoding> getAllEncodings()
     {
         return Arrays.asList(_shortMapEncoding, _mapEncoding);
@@ -101,17 +164,23 @@ public class MapType extends AbstractPrimitiveType<Map>
         }
 
         @Override
-        protected void writeEncodedValue(final Map val)
+        protected void writeEncodedValue(final Map map)
         {
-            getEncoder().writeRaw(2 * val.size());
-            
+            getEncoder().writeRaw(2 * map.size());
 
-            Iterator<Map.Entry> iter = val.entrySet().iterator();
+            Iterator<Map.Entry> iter = map.entrySet().iterator();
 
-            while(iter.hasNext())
+            while (iter.hasNext())
             {
                 Map.Entry element = iter.next();
-                TypeEncoding elementEncoding = getEncoder().getType(element.getKey()).getEncoding(element.getKey());
+
+                AMQPType keyType = fixedKeyType;
+                if (keyType == null)
+                {
+                    keyType = getEncoder().getType(element.getKey());
+                }
+
+                TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
                 elementEncoding.writeConstructor();
                 elementEncoding.writeValue(element.getKey());
                 elementEncoding = getEncoder().getType(element.getValue()).getEncoding(element.getValue());
@@ -123,30 +192,33 @@ public class MapType extends AbstractPrimitiveType<Map>
         @Override
         protected int getEncodedValueSize(final Map val)
         {
-            return 4 + ((val == _value) ? _length : calculateSize(val, getEncoder()));
+            return 4 + ((val == _value) ? _length : calculateSize(val, getEncoder(), fixedKeyType));
         }
 
-
         @Override
         public byte getEncodingCode()
         {
             return EncodingCodes.MAP32;
         }
 
+        @Override
         public MapType getType()
         {
             return MapType.this;
         }
 
+        @Override
         public boolean encodesSuperset(final TypeEncoding<Map> encoding)
         {
             return (getType() == encoding.getType());
         }
 
+        @Override
         public Map readValue()
         {
-
             DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+
             int size = decoder.readRawInt();
             // todo - limit the decoder with size
             int count = decoder.readRawInt();
@@ -154,17 +226,62 @@ public class MapType extends AbstractPrimitiveType<Map>
                 throw new IllegalArgumentException("Map element count "+count+" is specified to be greater than the amount of data available ("+
                                                    decoder.getByteBufferRemaining()+")");
             }
-            Map map = new LinkedHashMap(count);
-            for(int i = 0; i < count; i++)
+
+            TypeConstructor<?> keyConstructor = null;
+            TypeConstructor<?> valueConstructor = null;
+
+            Map<Object, Object> map = new LinkedHashMap<>(count);
+            for(int i = 0; i < count / 2; i++)
             {
-                Object key = decoder.readObject();
-                i++;
-                Object value = decoder.readObject();
+                keyConstructor = findNextDecoder(decoder, buffer, keyConstructor);
+                if(keyConstructor == null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                Object key = keyConstructor.readValue();
+
+                boolean arrayType = false;
+                byte code = buffer.get(buffer.position());
+                switch (code)
+                {
+                    case EncodingCodes.ARRAY8:
+                    case EncodingCodes.ARRAY32:
+                        arrayType = true;
+                }
+
+                valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
+                if (valueConstructor == null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                final Object value;
+
+                if (arrayType)
+                {
+                    value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
+                }
+                else
+                {
+                    value = valueConstructor.readValue();
+                }
+
                 map.put(key, value);
             }
+
             return map;
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = decoder.readRawInt();
+            buffer.position(buffer.position() + size);
+        }
+
+        @Override
         public void setValue(final Map value, final int length)
         {
             _value = value;
@@ -186,17 +303,22 @@ public class MapType extends AbstractPrimitiveType<Map>
         }
 
         @Override
-        protected void writeEncodedValue(final Map val)
+        protected void writeEncodedValue(final Map map)
         {
-            getEncoder().writeRaw((byte)(2*val.size()));
-                
+            getEncoder().writeRaw((byte)(2 * map.size()));
 
-            Iterator<Map.Entry> iter = val.entrySet().iterator();
-
-            while(iter.hasNext())
+            Iterator<Map.Entry> iter = map.entrySet().iterator();
+            while (iter.hasNext())
             {
                 Map.Entry element = iter.next();
-                TypeEncoding elementEncoding = getEncoder().getType(element.getKey()).getEncoding(element.getKey());
+
+                AMQPType keyType = fixedKeyType;
+                if (keyType == null)
+                {
+                    keyType = getEncoder().getType(element.getKey());
+                }
+
+                TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
                 elementEncoding.writeConstructor();
                 elementEncoding.writeValue(element.getKey());
                 elementEncoding = getEncoder().getType(element.getValue()).getEncoding(element.getValue());
@@ -208,44 +330,92 @@ public class MapType extends AbstractPrimitiveType<Map>
         @Override
         protected int getEncodedValueSize(final Map val)
         {
-            return 1 + ((val == _value) ? _length : calculateSize(val, getEncoder()));
+            return 1 + ((val == _value) ? _length : calculateSize(val, getEncoder(), fixedKeyType));
         }
 
-
         @Override
         public byte getEncodingCode()
         {
             return EncodingCodes.MAP8;
         }
 
+        @Override
         public MapType getType()
         {
             return MapType.this;
         }
 
+        @Override
         public boolean encodesSuperset(final TypeEncoding<Map> encoder)
         {
             return encoder == this;
         }
 
+        @Override
         public Map readValue()
         {
             DecoderImpl decoder = getDecoder();
-            int size = ((int)decoder.readRawByte()) & 0xff;
+            ByteBuffer buffer = decoder.getByteBuffer();
+
+            int size = (decoder.readRawByte()) & 0xff;
             // todo - limit the decoder with size
-            int count = ((int)decoder.readRawByte()) & 0xff;
+            int count = (decoder.readRawByte()) & 0xff;
+
+            TypeConstructor<?> keyConstructor = null;
+            TypeConstructor<?> valueConstructor = null;
 
-            Map map = new LinkedHashMap(count);
-            for(int i = 0; i < count; i++)
+            Map<Object, Object> map = new LinkedHashMap<>(count);
+            for(int i = 0; i < count / 2; i++)
             {
-                Object key = decoder.readObject();
-                i++;
-                Object value = decoder.readObject();
+                keyConstructor = findNextDecoder(decoder, buffer, keyConstructor);
+                if(keyConstructor == null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                Object key = keyConstructor.readValue();
+
+                boolean arrayType = false;
+                byte code = buffer.get(buffer.position());
+                switch (code)
+                {
+                    case EncodingCodes.ARRAY8:
+                    case EncodingCodes.ARRAY32:
+                        arrayType = true;
+                }
+
+                valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
+                if(valueConstructor== null)
+                {
+                    throw new DecodeException("Unknown constructor");
+                }
+
+                final Object value;
+
+                if (arrayType)
+                {
+                    value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
+                }
+                else
+                {
+                    value = valueConstructor.readValue();
+                }
+
                 map.put(key, value);
             }
+
             return map;
         }
 
+        public void skipValue()
+        {
+            DecoderImpl decoder = getDecoder();
+            ByteBuffer buffer = decoder.getByteBuffer();
+            int size = ((int)decoder.readRawByte()) & 0xff;
+            buffer.position(buffer.position() + size);
+        }
+
+        @Override
         public void setValue(final Map value, final int length)
         {
             _value = value;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org