PROTON-1963 Optimize hot path for encoder and decoder classes

Optimize the hot paths in the encoder and decoder to deal directly with
the primitive types and allow inlining of the normal encodings lookup
path.  Also cleans up some type encoding to use the read with defaults
methods.
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 2d4989b..a85b0ff 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,18 @@
  */
 package org.apache.qpid.proton.codec;
 
+import java.lang.reflect.Array;
+import java.nio.ByteBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
 import org.apache.qpid.proton.ProtonException;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Decimal128;
@@ -32,12 +44,6 @@
 import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.UnsignedShort;
 
-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 ReadableBuffer _buffer;
@@ -90,11 +96,11 @@
 
             if (EncodingCodes.SMALLULONG == encoding || EncodingCodes.ULONG == encoding)
             {
-                descriptor = readUnsignedLong();
+                descriptor = readUnsignedLong(null);
             }
             else if (EncodingCodes.SYM8 == encoding || EncodingCodes.SYM32 == encoding)
             {
-                descriptor = readSymbol();
+                descriptor = readSymbol(null);
             }
             else
             {
@@ -110,17 +116,19 @@
                 }
             }
 
-            TypeConstructor<?> nestedEncoding = readConstructor();
+            TypeConstructor<?> nestedEncoding = readConstructor(false);
             DescribedTypeConstructor<?> dtc = _dynamicTypeConstructors.get(descriptor);
             if(dtc == null)
             {
                 dtc = new DescribedTypeConstructor()
                 {
+                    @Override
                     public DescribedType newInstance(final Object described)
                     {
                         return new UnknownDescribedType(descriptor, described);
                     }
 
+                    @Override
                     public Class<?> getTypeClass()
                     {
                         return UnknownDescribedType.class;
@@ -136,11 +144,13 @@
         }
     }
 
+    @Override
     public void register(final Object descriptor, final FastPathDescribedTypeConstructor<?> btc)
     {
         _fastPathTypeConstructors.put(descriptor, btc);
     }
 
+    @Override
     public void register(final Object descriptor, final DescribedTypeConstructor dtc)
     {
         // Allow external type constructors to replace the built-in instances.
@@ -157,11 +167,13 @@
     }
 
 
+    @Override
     public Boolean readBoolean()
     {
         return readBoolean(null);
     }
 
+    @Override
     public Boolean readBoolean(final Boolean defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -173,7 +185,7 @@
             case EncodingCodes.BOOLEAN_FALSE:
                 return Boolean.FALSE;
             case EncodingCodes.BOOLEAN:
-                return (Boolean) _constructors[EncodingCodes.BOOLEAN & 0xff].readValue();
+                return readRawByte() == 0 ? Boolean.FALSE : Boolean.TRUE;
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -181,6 +193,7 @@
         }
     }
 
+    @Override
     public boolean readBoolean(final boolean defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -192,7 +205,7 @@
             case EncodingCodes.BOOLEAN_FALSE:
                 return false;
             case EncodingCodes.BOOLEAN:
-                return (Boolean) _constructors[EncodingCodes.BOOLEAN & 0xff].readValue();
+                return readRawByte() != 0;
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -200,18 +213,20 @@
         }
     }
 
+    @Override
     public Byte readByte()
     {
         return readByte(null);
     }
 
+    @Override
     public Byte readByte(final Byte defaultVal)
     {
         byte encodingCode = _buffer.get();
 
         switch (encodingCode) {
             case EncodingCodes.BYTE:
-                return (Byte) _constructors[EncodingCodes.BYTE & 0xff].readValue();
+                return (Byte) readRawByte();
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -219,9 +234,10 @@
         }
     }
 
+    @Override
     public byte readByte(final byte defaultVal)
     {
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof ByteType.ByteEncoding)
         {
             return ((ByteType.ByteEncoding)constructor).readPrimitiveValue();
@@ -240,11 +256,13 @@
         }
     }
 
+    @Override
     public Short readShort()
     {
         return readShort(null);
     }
 
+    @Override
     public Short readShort(final Short defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -252,7 +270,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.SHORT:
-                return (Short) _constructors[EncodingCodes.SHORT & 0xff].readValue();
+                return Short.valueOf(readRawShort());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -260,10 +278,10 @@
         }
     }
 
+    @Override
     public short readShort(final short defaultVal)
     {
-
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof ShortType.ShortEncoding)
         {
             return ((ShortType.ShortEncoding)constructor).readPrimitiveValue();
@@ -282,11 +300,13 @@
         }
     }
 
+    @Override
     public Integer readInteger()
     {
         return readInteger(null);
     }
 
+    @Override
     public Integer readInteger(final Integer defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -294,9 +314,9 @@
         switch (encodingCode)
         {
             case EncodingCodes.SMALLINT:
-                return (Integer) _constructors[EncodingCodes.SMALLINT & 0xff].readValue();
+                return Integer.valueOf(readRawByte());
             case EncodingCodes.INT:
-                return (Integer) _constructors[EncodingCodes.INT & 0xff].readValue();
+                return Integer.valueOf(readRawInt());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -304,10 +324,10 @@
         }
     }
 
+    @Override
     public int readInteger(final int defaultVal)
     {
-
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof IntegerType.IntegerEncoding)
         {
             return ((IntegerType.IntegerEncoding)constructor).readPrimitiveValue();
@@ -326,11 +346,13 @@
         }
     }
 
+    @Override
     public Long readLong()
     {
         return readLong(null);
     }
 
+    @Override
     public Long readLong(final Long defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -338,9 +360,9 @@
         switch (encodingCode)
         {
             case EncodingCodes.SMALLLONG:
-                return (Long) _constructors[EncodingCodes.SMALLLONG & 0xff].readValue();
+                return Long.valueOf(readRawByte());
             case EncodingCodes.LONG:
-                return (Long) _constructors[EncodingCodes.LONG & 0xff].readValue();
+                return Long.valueOf(readRawLong());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -348,10 +370,10 @@
         }
     }
 
+    @Override
     public long readLong(final long defaultVal)
     {
-
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof LongType.LongEncoding)
         {
             return ((LongType.LongEncoding)constructor).readPrimitiveValue();
@@ -370,11 +392,13 @@
         }
     }
 
+    @Override
     public UnsignedByte readUnsignedByte()
     {
         return readUnsignedByte(null);
     }
 
+    @Override
     public UnsignedByte readUnsignedByte(final UnsignedByte defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -382,7 +406,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.UBYTE:
-                return (UnsignedByte) _constructors[EncodingCodes.UBYTE & 0xff].readValue();
+                return UnsignedByte.valueOf(readRawByte());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -390,11 +414,13 @@
         }
     }
 
+    @Override
     public UnsignedShort readUnsignedShort()
     {
         return readUnsignedShort(null);
     }
 
+    @Override
     public UnsignedShort readUnsignedShort(final UnsignedShort defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -402,7 +428,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.USHORT:
-                return (UnsignedShort) _constructors[EncodingCodes.USHORT & 0xff].readValue();
+                return UnsignedShort.valueOf(readRawShort());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -410,11 +436,13 @@
         }
     }
 
+    @Override
     public UnsignedInteger readUnsignedInteger()
     {
         return readUnsignedInteger(null);
     }
 
+    @Override
     public UnsignedInteger readUnsignedInteger(final UnsignedInteger defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -424,9 +452,9 @@
             case EncodingCodes.UINT0:
                 return UnsignedInteger.ZERO;
             case EncodingCodes.SMALLUINT:
-                return (UnsignedInteger) _constructors[EncodingCodes.SMALLUINT & 0xff].readValue();
+                return UnsignedInteger.valueOf(((int) readRawByte()) & 0xff);
             case EncodingCodes.UINT:
-                return (UnsignedInteger) _constructors[EncodingCodes.UINT & 0xff].readValue();
+                return UnsignedInteger.valueOf(readRawInt());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -434,11 +462,13 @@
         }
     }
 
+    @Override
     public UnsignedLong readUnsignedLong()
     {
         return readUnsignedLong(null);
     }
 
+    @Override
     public UnsignedLong readUnsignedLong(final UnsignedLong defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -448,9 +478,9 @@
             case EncodingCodes.ULONG0:
                 return UnsignedLong.ZERO;
             case EncodingCodes.SMALLULONG:
-                return (UnsignedLong) _constructors[EncodingCodes.SMALLULONG & 0xff].readValue();
+                return UnsignedLong.valueOf(((long) readRawByte())&0xffl);
             case EncodingCodes.ULONG:
-                return (UnsignedLong) _constructors[EncodingCodes.ULONG & 0xff].readValue();
+                return UnsignedLong.valueOf(readRawLong());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -458,11 +488,13 @@
         }
     }
 
+    @Override
     public Character readCharacter()
     {
         return readCharacter(null);
     }
 
+    @Override
     public Character readCharacter(final Character defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -470,7 +502,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.CHAR:
-                return (Character) _constructors[EncodingCodes.CHAR & 0xff].readValue();
+                return Character.valueOf((char) (readRawInt() & 0xffff));
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -478,6 +510,7 @@
         }
     }
 
+    @Override
     public char readCharacter(final char defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -485,7 +518,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.CHAR:
-                return (Character) _constructors[EncodingCodes.CHAR & 0xff].readValue();
+                return (char) (readRawInt() & 0xffff);
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -493,11 +526,13 @@
         }
     }
 
+    @Override
     public Float readFloat()
     {
         return readFloat(null);
     }
 
+    @Override
     public Float readFloat(final Float defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -505,7 +540,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.FLOAT:
-                return (Float) _constructors[EncodingCodes.FLOAT & 0xff].readValue();
+                return Float.valueOf(readRawFloat());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -513,10 +548,10 @@
         }
     }
 
+    @Override
     public float readFloat(final float defaultVal)
     {
-
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof FloatType.FloatEncoding)
         {
             return ((FloatType.FloatEncoding)constructor).readPrimitiveValue();
@@ -535,11 +570,13 @@
         }
     }
 
+    @Override
     public Double readDouble()
     {
         return readDouble(null);
     }
 
+    @Override
     public Double readDouble(final Double defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -547,7 +584,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.DOUBLE:
-                return (Double) _constructors[EncodingCodes.DOUBLE & 0xff].readValue();
+                return Double.valueOf(readRawDouble());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -555,10 +592,10 @@
         }
     }
 
+    @Override
     public double readDouble(final double defaultVal)
     {
-
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor instanceof DoubleType.DoubleEncoding)
         {
             return ((DoubleType.DoubleEncoding)constructor).readPrimitiveValue();
@@ -577,11 +614,13 @@
         }
     }
 
+    @Override
     public UUID readUUID()
     {
         return readUUID(null);
     }
 
+    @Override
     public UUID readUUID(final UUID defaultVal)
     {
         byte encodingCode = _buffer.get();
@@ -589,7 +628,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.UUID:
-                return (UUID) _constructors[EncodingCodes.UUID & 0xff].readValue();
+                return new UUID(readRawLong(), readRawLong());
             case EncodingCodes.NULL:
                 return defaultVal;
             default:
@@ -597,11 +636,13 @@
         }
     }
 
+    @Override
     public Decimal32 readDecimal32()
     {
         return readDecimal32(null);
     }
 
+    @Override
     public Decimal32 readDecimal32(final Decimal32 defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -617,11 +658,13 @@
         }
     }
 
+    @Override
     public Decimal64 readDecimal64()
     {
         return readDecimal64(null);
     }
 
+    @Override
     public Decimal64 readDecimal64(final Decimal64 defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -637,11 +680,13 @@
         }
     }
 
+    @Override
     public Decimal128 readDecimal128()
     {
         return readDecimal128(null);
     }
 
+    @Override
     public Decimal128 readDecimal128(final Decimal128 defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -657,11 +702,13 @@
         }
     }
 
+    @Override
     public Date readTimestamp()
     {
         return readTimestamp(null);
     }
 
+    @Override
     public Date readTimestamp(final Date defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -669,7 +716,7 @@
         switch (encodingCode)
         {
             case EncodingCodes.TIMESTAMP:
-                return (Date) _constructors[EncodingCodes.TIMESTAMP & 0xff].readValue();
+                return new Date(readRawLong());
             case EncodingCodes.NULL:
                 return defaultValue;
             default:
@@ -677,11 +724,13 @@
         }
     }
 
+    @Override
     public Binary readBinary()
     {
         return readBinary(null);
     }
 
+    @Override
     public Binary readBinary(final Binary defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -699,11 +748,13 @@
         }
     }
 
+    @Override
     public Symbol readSymbol()
     {
         return readSymbol(null);
     }
 
+    @Override
     public Symbol readSymbol(final Symbol defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -721,11 +772,13 @@
         }
     }
 
+    @Override
     public String readString()
     {
         return readString(null);
     }
 
+    @Override
     public String readString(final String defaultValue)
     {
         byte encodingCode = _buffer.get();
@@ -743,6 +796,7 @@
         }
     }
 
+    @Override
     @SuppressWarnings("rawtypes")
     public List readList()
     {
@@ -763,11 +817,13 @@
         }
     }
 
+    @Override
     public <T> void readList(final ListProcessor<T> processor)
     {
         //TODO.
     }
 
+    @Override
     @SuppressWarnings("rawtypes")
     public Map readMap()
     {
@@ -786,57 +842,68 @@
         }
     }
 
+    @Override
     public <T> T[] readArray(final Class<T> clazz)
     {
         return null;  //TODO.
     }
 
+    @Override
     public Object[] readArray()
     {
         return (Object[]) readConstructor().readValue();
 
     }
 
+    @Override
     public boolean[] readBooleanArray()
     {
         return (boolean[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public byte[] readByteArray()
     {
         return (byte[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public short[] readShortArray()
     {
         return (short[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public int[] readIntegerArray()
     {
         return (int[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public long[] readLongArray()
     {
         return (long[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public float[] readFloatArray()
     {
         return (float[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public double[] readDoubleArray()
     {
         return (double[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public char[] readCharacterArray()
     {
         return (char[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
     }
 
+    @Override
     public <T> T[] readMultiple(final Class<T> clazz)
     {
         Object val = readObject();
@@ -867,6 +934,7 @@
         }
     }
 
+    @Override
     public Object[] readMultiple()
     {
         Object val = readObject();
@@ -886,41 +954,49 @@
         }
     }
 
+    @Override
     public byte[] readByteMultiple()
     {
         return new byte[0];  //TODO.
     }
 
+    @Override
     public short[] readShortMultiple()
     {
         return new short[0];  //TODO.
     }
 
+    @Override
     public int[] readIntegerMultiple()
     {
         return new int[0];  //TODO.
     }
 
+    @Override
     public long[] readLongMultiple()
     {
         return new long[0];  //TODO.
     }
 
+    @Override
     public float[] readFloatMultiple()
     {
         return new float[0];  //TODO.
     }
 
+    @Override
     public double[] readDoubleMultiple()
     {
         return new double[0];  //TODO.
     }
 
+    @Override
     public char[] readCharacterMultiple()
     {
         return new char[0];  //TODO.
     }
 
+    @Override
     public Object readObject()
     {
         boolean arrayType = false;
@@ -932,7 +1008,7 @@
                 arrayType = true;
         }
 
-        TypeConstructor constructor = readConstructor();
+        TypeConstructor<?> constructor = readConstructor();
         if(constructor== null)
         {
             throw new DecodeException("Unknown constructor");
@@ -945,6 +1021,7 @@
         }
     }
 
+    @Override
     public Object readObject(final Object defaultValue)
     {
         Object val = readObject();
@@ -1004,6 +1081,7 @@
         return decode;
     }
 
+    @Override
     public void setByteBuffer(final ByteBuffer buffer)
     {
         _buffer = new ReadableBuffer.ByteBufferReader(buffer);
@@ -1045,11 +1123,13 @@
             _described = described;
         }
 
+        @Override
         public Object getDescriptor()
         {
             return _descriptor;
         }
 
+        @Override
         public Object getDescribed()
         {
             return _described;
@@ -1070,6 +1150,7 @@
 
     }
 
+    @Override
     public int getByteBufferRemaining() {
         return _buffer.remaining();
     }
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 512805b..164a77d 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
@@ -157,48 +157,56 @@
         return getTypeFromClass(clazz, null);
     }
 
-    private AMQPType getTypeFromClass(final Class clazz, Object instance)
+    private AMQPType<?> getTypeFromClass(final Class<?> clazz, final Object instance)
     {
-        AMQPType amqpType = _typeRegistry.get(clazz);
+        AMQPType<?> amqpType = _typeRegistry.get(clazz);
         if(amqpType == null)
         {
-            if(clazz.isArray())
-            {
-                amqpType = _arrayType;
-            }
-            else
-            {
-                if(List.class.isAssignableFrom(clazz))
-                {
-                    amqpType = _listType;
-                }
-                else if(Map.class.isAssignableFrom(clazz))
-                {
-                    amqpType = _mapType;
-                }
-                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);
-                        }
-                    }
-
-                    return amqpType;
-                }
-            }
-            _typeRegistry.put(clazz, amqpType);
+            amqpType = deduceTypeFromClass(clazz, instance);
         }
 
         return amqpType;
     }
 
+    private AMQPType<?> deduceTypeFromClass(final Class<?> clazz, final Object instance) {
+        AMQPType<?> amqpType = null;
+
+        if(clazz.isArray())
+        {
+            amqpType = _arrayType;
+        }
+        else
+        {
+            if(List.class.isAssignableFrom(clazz))
+            {
+                amqpType = _listType;
+            }
+            else if(Map.class.isAssignableFrom(clazz))
+            {
+                amqpType = _mapType;
+            }
+            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);
+                    }
+                }
+
+                return amqpType;
+            }
+        }
+        _typeRegistry.put(clazz, amqpType);
+
+        return amqpType;
+    }
+
     @Override
     public <V> void register(AMQPType<V> type)
     {
@@ -212,7 +220,7 @@
 
     public void registerDescribedType(Class clazz, Object descriptor)
     {
-        AMQPType type = _describedDescriptorRegistry.get(descriptor);
+        AMQPType<?> type = _describedDescriptorRegistry.get(descriptor);
         if(type == null)
         {
             type = new DynamicDescribedType(this, descriptor);
@@ -513,7 +521,6 @@
         {
             _uuidType.fastWrite(this, uuid);
         }
-
     }
 
     @Override
@@ -553,7 +560,6 @@
         {
             _symbolType.fastWrite(this, s);
         }
-
     }
 
     @Override
@@ -715,44 +721,51 @@
         }
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     @Override
     public void writeObject(final Object o)
     {
-        if (o == null)
+        if (o != null)
         {
-            getBuffer().put(EncodingCodes.NULL);
-            return;
-        }
+            AMQPType type = _typeRegistry.get(o.getClass());
 
-        AMQPType type = _typeRegistry.get(o.getClass());
-
-        if(type == null)
-        {
-            if(o.getClass().isArray())
+            if(type != null)
             {
-                writeArrayType(o);
-            }
-            else if(o instanceof List)
-            {
-                writeList((List)o);
-            }
-            else if(o instanceof Map)
-            {
-                writeMap((Map)o);
-            }
-            else if(o instanceof DescribedType)
-            {
-                writeDescribedType((DescribedType)o);
+                type.write(o);
             }
             else
             {
-                throw new IllegalArgumentException(
-                    "Do not know how to write Objects of class " + o.getClass().getName());
+                writeUnregisteredType(o);
             }
         }
         else
         {
-            type.write(o);
+            _buffer.put(EncodingCodes.NULL);
+        }
+    }
+
+    private void writeUnregisteredType(final Object o)
+    {
+        if(o.getClass().isArray())
+        {
+            writeArrayType(o);
+        }
+        else if(o instanceof List)
+        {
+            writeList((List<?>)o);
+        }
+        else if(o instanceof Map)
+        {
+            writeMap((Map<?, ?>)o);
+        }
+        else if(o instanceof DescribedType)
+        {
+            writeDescribedType((DescribedType)o);
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                "Do not know how to write Objects of class " + o.getClass().getName());
         }
     }
 
@@ -843,7 +856,7 @@
         _buffer.put(string);
     }
 
-    AMQPType getNullTypeEncoder()
+    AMQPType<?> getNullTypeEncoder()
     {
         return _nullType;
     }
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
index 2562e57..b60d53e 100644
--- 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
@@ -28,6 +28,7 @@
 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.ReadableBuffer;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -57,6 +58,7 @@
     @Override
     public Header readValue() {
         DecoderImpl decoder = getDecoder();
+        ReadableBuffer buffer = decoder.getBuffer();
         byte typeCode = decoder.getBuffer().get();
 
         @SuppressWarnings("unused")
@@ -67,12 +69,12 @@
             case EncodingCodes.LIST0:
                 break;
             case EncodingCodes.LIST8:
-                size = ((int)decoder.getBuffer().get()) & 0xff;
-                count = ((int)decoder.getBuffer().get()) & 0xff;
+                size = buffer.get() & 0xff;
+                count = buffer.get() & 0xff;
                 break;
             case EncodingCodes.LIST32:
-                size = decoder.getBuffer().getInt();
-                count = decoder.getBuffer().getInt();
+                size = buffer.getInt();
+                count = buffer.getInt();
                 break;
             default:
                 throw new DecodeException("Incorrect type found in Header encoding: " + typeCode);
@@ -83,19 +85,19 @@
         for (int index = 0; index < count; ++index) {
             switch (index) {
                 case 0:
-                    header.setDurable(decoder.readBoolean());
+                    header.setDurable(decoder.readBoolean(null));
                     break;
                 case 1:
-                    header.setPriority(decoder.readUnsignedByte());
+                    header.setPriority(decoder.readUnsignedByte(null));
                     break;
                 case 2:
-                    header.setTtl(decoder.readUnsignedInteger());
+                    header.setTtl(decoder.readUnsignedInteger(null));
                     break;
                 case 3:
-                    header.setFirstAcquirer(decoder.readBoolean());
+                    header.setFirstAcquirer(decoder.readBoolean(null));
                     break;
                 case 4:
-                    header.setDeliveryCount(decoder.readUnsignedInteger());
+                    header.setDeliveryCount(decoder.readUnsignedInteger(null));
                     break;
                 default:
                     throw new IllegalStateException("To many entries in Header encoding");
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
index 3d5c7c4..22b30d1 100644
--- 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
@@ -1,5 +1,5 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
+  * 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
@@ -28,6 +28,7 @@
 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.ReadableBuffer;
 import org.apache.qpid.proton.codec.TypeEncoding;
 import org.apache.qpid.proton.codec.WritableBuffer;
 
@@ -57,6 +58,7 @@
     @Override
     public Properties readValue() {
         DecoderImpl decoder = getDecoder();
+        ReadableBuffer buffer = decoder.getBuffer();
         byte typeCode = decoder.getBuffer().get();
 
         @SuppressWarnings("unused")
@@ -67,12 +69,12 @@
             case EncodingCodes.LIST0:
                 break;
             case EncodingCodes.LIST8:
-                size = ((int)decoder.getBuffer().get()) & 0xff;
-                count = ((int)decoder.getBuffer().get()) & 0xff;
+                size = buffer.get() & 0xff;
+                count = buffer.get() & 0xff;
                 break;
             case EncodingCodes.LIST32:
-                size = decoder.getBuffer().getInt();
-                count = decoder.getBuffer().getInt();
+                size = buffer.getInt();
+                count = buffer.getInt();
                 break;
             default:
                 throw new DecodeException("Incorrect type found in Properties encoding: " + typeCode);
@@ -86,40 +88,40 @@
                     properties.setMessageId(decoder.readObject());
                     break;
                 case 1:
-                    properties.setUserId(decoder.readBinary());
+                    properties.setUserId(decoder.readBinary(null));
                     break;
                 case 2:
-                    properties.setTo(decoder.readString());
+                    properties.setTo(decoder.readString(null));
                     break;
                 case 3:
-                    properties.setSubject(decoder.readString());
+                    properties.setSubject(decoder.readString(null));
                     break;
                 case 4:
-                    properties.setReplyTo(decoder.readString());
+                    properties.setReplyTo(decoder.readString(null));
                     break;
                 case 5:
                     properties.setCorrelationId(decoder.readObject());
                     break;
                 case 6:
-                    properties.setContentType(decoder.readSymbol());
+                    properties.setContentType(decoder.readSymbol(null));
                     break;
                 case 7:
-                    properties.setContentEncoding(decoder.readSymbol());
+                    properties.setContentEncoding(decoder.readSymbol(null));
                     break;
                 case 8:
-                    properties.setAbsoluteExpiryTime(decoder.readTimestamp());
+                    properties.setAbsoluteExpiryTime(decoder.readTimestamp(null));
                     break;
                 case 9:
-                    properties.setCreationTime(decoder.readTimestamp());
+                    properties.setCreationTime(decoder.readTimestamp(null));
                     break;
                 case 10:
-                    properties.setGroupId(decoder.readString());
+                    properties.setGroupId(decoder.readString(null));
                     break;
                 case 11:
-                    properties.setGroupSequence(decoder.readUnsignedInteger());
+                    properties.setGroupSequence(decoder.readUnsignedInteger(null));
                     break;
                 case 12:
-                    properties.setReplyToGroupId(decoder.readString());
+                    properties.setReplyToGroupId(decoder.readString(null));
                     break;
                 default:
                     throw new IllegalStateException("To many entries in Properties encoding");
@@ -300,8 +302,7 @@
 
     public static void register(Decoder decoder, EncoderImpl encoder) {
         FastPathPropertiesType type = new FastPathPropertiesType(encoder);
-        for(Object descriptor : DESCRIPTORS)
-        {
+        for(Object descriptor : DESCRIPTORS) {
             decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
         }
         encoder.register(type);
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
index 4424cfa..32bed2b 100644
--- 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
@@ -124,10 +124,10 @@
                     disposition.setRole(Boolean.TRUE.equals(decoder.readBoolean()) ? Role.RECEIVER : Role.SENDER);
                     break;
                 case 1:
-                    disposition.setFirst(decoder.readUnsignedInteger());
+                    disposition.setFirst(decoder.readUnsignedInteger(null));
                     break;
                 case 2:
-                    disposition.setLast(decoder.readUnsignedInteger());
+                    disposition.setLast(decoder.readUnsignedInteger(null));
                     break;
                 case 3:
                     disposition.setSettled(decoder.readBoolean(false));
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
index 7ed89e4..534ab0c 100644
--- 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
@@ -109,28 +109,28 @@
         for (int index = 0; index < count; ++index) {
             switch (index) {
                 case 0:
-                    flow.setNextIncomingId(decoder.readUnsignedInteger());
+                    flow.setNextIncomingId(decoder.readUnsignedInteger(null));
                     break;
                 case 1:
-                    flow.setIncomingWindow(decoder.readUnsignedInteger());
+                    flow.setIncomingWindow(decoder.readUnsignedInteger(null));
                     break;
                 case 2:
-                    flow.setNextOutgoingId(decoder.readUnsignedInteger());
+                    flow.setNextOutgoingId(decoder.readUnsignedInteger(null));
                     break;
                 case 3:
-                    flow.setOutgoingWindow(decoder.readUnsignedInteger());
+                    flow.setOutgoingWindow(decoder.readUnsignedInteger(null));
                     break;
                 case 4:
-                    flow.setHandle(decoder.readUnsignedInteger());
+                    flow.setHandle(decoder.readUnsignedInteger(null));
                     break;
                 case 5:
-                    flow.setDeliveryCount(decoder.readUnsignedInteger());
+                    flow.setDeliveryCount(decoder.readUnsignedInteger(null));
                     break;
                 case 6:
-                    flow.setLinkCredit(decoder.readUnsignedInteger());
+                    flow.setLinkCredit(decoder.readUnsignedInteger(null));
                     break;
                 case 7:
-                    flow.setAvailable(decoder.readUnsignedInteger());
+                    flow.setAvailable(decoder.readUnsignedInteger(null));
                     break;
                 case 8:
                     flow.setDrain(decoder.readBoolean(false));
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
index d27e59c..b37c5b6 100644
--- 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
@@ -90,19 +90,19 @@
         for (int index = 0; index < count; ++index) {
             switch (index) {
                 case 0:
-                    transfer.setHandle(decoder.readUnsignedInteger());
+                    transfer.setHandle(decoder.readUnsignedInteger(null));
                     break;
                 case 1:
-                    transfer.setDeliveryId(decoder.readUnsignedInteger());
+                    transfer.setDeliveryId(decoder.readUnsignedInteger(null));
                     break;
                 case 2:
-                    transfer.setDeliveryTag(decoder.readBinary());
+                    transfer.setDeliveryTag(decoder.readBinary(null));
                     break;
                 case 3:
-                    transfer.setMessageFormat(decoder.readUnsignedInteger());
+                    transfer.setMessageFormat(decoder.readUnsignedInteger(null));
                     break;
                 case 4:
-                    transfer.setSettled(decoder.readBoolean());
+                    transfer.setSettled(decoder.readBoolean(null));
                     break;
                 case 5:
                     transfer.setMore(decoder.readBoolean(false));