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 2022/11/02 22:19:08 UTC

[qpid-protonj2] branch main updated: PROTON-2637 Streamline codec for commonly used performatives

This is an automated email from the ASF dual-hosted git repository.

tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git


The following commit(s) were added to refs/heads/main by this push:
     new 0dae4016 PROTON-2637 Streamline codec for commonly used performatives
0dae4016 is described below

commit 0dae4016b2bb68e0222fee130ba12fd98cdefe23
Author: Timothy Bish <ta...@gmail.com>
AuthorDate: Wed Nov 2 18:18:57 2022 -0400

    PROTON-2637 Streamline codec for commonly used performatives
    
    Provide small increases in encode an decode time for the frequently used
    performatives along with some other cleanups.
---
 .../qpid/protonj2/codec/DescribedTypeDecoder.java  |  11 ++
 .../qpid/protonj2/codec/DescribedTypeEncoder.java  |  11 ++
 .../protonj2/codec/decoders/ProtonDecoder.java     |   2 +
 .../decoders/messaging/AcceptedTypeDecoder.java    |  29 ++++-
 .../ApplicationPropertiesTypeDecoder.java          |  10 +-
 .../decoders/messaging/ReleasedTypeDecoder.java    |  29 ++++-
 .../protonj2/codec/encoders/ProtonEncoder.java     |   2 +-
 .../ApplicationPropertiesTypeEncoder.java          |   5 +-
 .../messaging/MessageAnnotationsTypeEncoder.java   |   5 +-
 .../encoders/transport/AttachTypeEncoder.java      | 124 ++++++--------------
 .../codec/encoders/transport/BeginTypeEncoder.java |  74 ++++--------
 .../encoders/transport/DetachTypeEncoder.java      |  30 ++---
 .../encoders/transport/DispositionTypeEncoder.java |  80 ++++++-------
 .../codec/encoders/transport/FlowTypeEncoder.java  | 127 +++++++++------------
 .../codec/encoders/transport/OpenTypeEncoder.java  |  90 +++++----------
 .../encoders/transport/TransferTypeEncoder.java    | 120 ++++++++-----------
 .../qpid/protonj2/types/transport/Attach.java      |   5 +
 .../qpid/protonj2/types/transport/Begin.java       |   5 +
 .../qpid/protonj2/types/transport/Detach.java      |   5 +
 .../qpid/protonj2/types/transport/Disposition.java |   5 +
 .../apache/qpid/protonj2/types/transport/Flow.java |   5 +
 .../apache/qpid/protonj2/types/transport/Open.java |   5 +
 .../apache/qpid/protonj2/types/transport/Role.java |  10 ++
 .../qpid/protonj2/types/transport/Transfer.java    |   5 +
 .../qpid/protonj2/codec/benchmark/Benchmark.java   |  20 ++++
 .../protonj2/types/transport/DispositionTest.java  |  15 +++
 .../protonj2/types/transport/TransferTest.java     |  26 +++++
 27 files changed, 434 insertions(+), 421 deletions(-)

diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeDecoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeDecoder.java
index d8ff14ac..b2bc29f8 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeDecoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeDecoder.java
@@ -40,4 +40,15 @@ public interface DescribedTypeDecoder<V> extends TypeDecoder<V> {
      */
     Symbol getDescriptorSymbol();
 
+    /**
+     * Allow the type decoder to react to being registered with a given {@link Decoder} instance.
+     *
+     * @param decoder
+     * 		The {@link Decoder} that this type decoder is now registered with.
+     *
+     * @return this type decoder value after having initialized itself following registration.
+     */
+    default DescribedTypeDecoder<V> decoderRegistered(Decoder decoder) {
+        return this;
+    }
 }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeEncoder.java
index 0855143b..5866da5d 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/DescribedTypeEncoder.java
@@ -36,4 +36,15 @@ public interface DescribedTypeEncoder<V> extends TypeEncoder<V> {
      */
     Symbol getDescriptorSymbol();
 
+    /**
+     * Allow the type encoder to react to being registered with a given {@link Encoder} instance.
+     *
+     * @param encoder
+     * 		The {@link Encoder} that this type encoder is now registered with.
+     *
+     * @return this type encoder value after having initialized itself following registration.
+     */
+    default DescribedTypeEncoder<V> encoderRegistered(Encoder encoder) {
+        return this;
+    }
 }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/ProtonDecoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/ProtonDecoder.java
index 47d23bbe..1c37f797 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/ProtonDecoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/ProtonDecoder.java
@@ -292,6 +292,8 @@ public final class ProtonDecoder implements Decoder {
         describedTypeDecoders.put(describedTypeDecoder.getDescriptorCode(), describedTypeDecoder);
         describedTypeDecoders.put(describedTypeDecoder.getDescriptorSymbol(), describedTypeDecoder);
 
+        decoder.decoderRegistered(this);
+
         return this;
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/AcceptedTypeDecoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/AcceptedTypeDecoder.java
index 0fca5ddc..b52ef741 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/AcceptedTypeDecoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/AcceptedTypeDecoder.java
@@ -19,12 +19,16 @@ package org.apache.qpid.protonj2.codec.decoders.messaging;
 import java.io.InputStream;
 
 import org.apache.qpid.protonj2.buffer.ProtonBuffer;
+import org.apache.qpid.protonj2.codec.DecodeEOFException;
 import org.apache.qpid.protonj2.codec.DecodeException;
 import org.apache.qpid.protonj2.codec.DecoderState;
+import org.apache.qpid.protonj2.codec.EncodingCodes;
 import org.apache.qpid.protonj2.codec.StreamDecoderState;
 import org.apache.qpid.protonj2.codec.StreamTypeDecoder;
 import org.apache.qpid.protonj2.codec.TypeDecoder;
 import org.apache.qpid.protonj2.codec.decoders.AbstractDescribedTypeDecoder;
+import org.apache.qpid.protonj2.codec.decoders.primitives.List32TypeDecoder;
+import org.apache.qpid.protonj2.codec.decoders.primitives.List8TypeDecoder;
 import org.apache.qpid.protonj2.codec.decoders.primitives.ListTypeDecoder;
 import org.apache.qpid.protonj2.types.Symbol;
 import org.apache.qpid.protonj2.types.UnsignedLong;
@@ -35,6 +39,9 @@ import org.apache.qpid.protonj2.types.messaging.Accepted;
  */
 public final class AcceptedTypeDecoder extends AbstractDescribedTypeDecoder<Accepted> {
 
+    private static final ListTypeDecoder SMALL_LIST_TYPE_DECODER = new List8TypeDecoder();
+    private static final ListTypeDecoder LARGE_LIST_TYPE_DECODER = new List32TypeDecoder();
+
     @Override
     public Class<Accepted> getTypeClass() {
         return Accepted.class;
@@ -52,11 +59,27 @@ public final class AcceptedTypeDecoder extends AbstractDescribedTypeDecoder<Acce
 
     @Override
     public Accepted readValue(ProtonBuffer buffer, DecoderState state) throws DecodeException {
-        final TypeDecoder<?> decoder = state.getDecoder().readNextTypeDecoder(buffer, state);
+        final byte encodingCode;
 
-        checkIsExpectedType(ListTypeDecoder.class, decoder);
+        try {
+            encodingCode = buffer.readByte();
+        } catch (IndexOutOfBoundsException e) {
+            throw new DecodeEOFException(e);
+        }
 
-        decoder.skipValue(buffer, state);
+        switch (encodingCode) {
+            case EncodingCodes.LIST0:
+                break;
+            case EncodingCodes.LIST8:
+                SMALL_LIST_TYPE_DECODER.skipValue(buffer, state);
+                break;
+            case EncodingCodes.LIST32:
+                LARGE_LIST_TYPE_DECODER.skipValue(buffer, state);
+                break;
+            default:
+                throw new DecodeException(
+                    "Expected list encoding but got decoder for type code: " + encodingCode);
+        }
 
         return Accepted.getInstance();
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ApplicationPropertiesTypeDecoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ApplicationPropertiesTypeDecoder.java
index 1a745fdf..beaf5181 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ApplicationPropertiesTypeDecoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ApplicationPropertiesTypeDecoder.java
@@ -111,10 +111,7 @@ public final class ApplicationPropertiesTypeDecoder extends AbstractDescribedTyp
         // Count include both key and value so we must include that in the loop
         final Map<String, Object> map = new LinkedHashMap<>(count);
         for (int i = 0; i < count / 2; i++) {
-            String key = decoder.readString(buffer, state);
-            Object value = decoder.readObject(buffer, state);
-
-            map.put(key, value);
+            map.put(decoder.readString(buffer, state), decoder.readObject(buffer, state));
         }
 
         return map;
@@ -171,10 +168,7 @@ public final class ApplicationPropertiesTypeDecoder extends AbstractDescribedTyp
         // Count include both key and value so we must include that in the loop
         final Map<String, Object> map = new LinkedHashMap<>(count);
         for (int i = 0; i < count / 2; i++) {
-            String key = decoder.readString(stream, state);
-            Object value = decoder.readObject(stream, state);
-
-            map.put(key, value);
+            map.put(decoder.readString(stream, state), decoder.readObject(stream, state));
         }
 
         return map;
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ReleasedTypeDecoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ReleasedTypeDecoder.java
index ba7683f3..0582cbf3 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ReleasedTypeDecoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/decoders/messaging/ReleasedTypeDecoder.java
@@ -19,12 +19,16 @@ package org.apache.qpid.protonj2.codec.decoders.messaging;
 import java.io.InputStream;
 
 import org.apache.qpid.protonj2.buffer.ProtonBuffer;
+import org.apache.qpid.protonj2.codec.DecodeEOFException;
 import org.apache.qpid.protonj2.codec.DecodeException;
 import org.apache.qpid.protonj2.codec.DecoderState;
+import org.apache.qpid.protonj2.codec.EncodingCodes;
 import org.apache.qpid.protonj2.codec.StreamDecoderState;
 import org.apache.qpid.protonj2.codec.StreamTypeDecoder;
 import org.apache.qpid.protonj2.codec.TypeDecoder;
 import org.apache.qpid.protonj2.codec.decoders.AbstractDescribedTypeDecoder;
+import org.apache.qpid.protonj2.codec.decoders.primitives.List32TypeDecoder;
+import org.apache.qpid.protonj2.codec.decoders.primitives.List8TypeDecoder;
 import org.apache.qpid.protonj2.codec.decoders.primitives.ListTypeDecoder;
 import org.apache.qpid.protonj2.types.Symbol;
 import org.apache.qpid.protonj2.types.UnsignedLong;
@@ -35,6 +39,9 @@ import org.apache.qpid.protonj2.types.messaging.Released;
  */
 public final class ReleasedTypeDecoder extends AbstractDescribedTypeDecoder<Released> {
 
+    private static final ListTypeDecoder SMALL_LIST_TYPE_DECODER = new List8TypeDecoder();
+    private static final ListTypeDecoder LARGE_LIST_TYPE_DECODER = new List32TypeDecoder();
+
     @Override
     public Class<Released> getTypeClass() {
         return Released.class;
@@ -52,11 +59,27 @@ public final class ReleasedTypeDecoder extends AbstractDescribedTypeDecoder<Rele
 
     @Override
     public Released readValue(ProtonBuffer buffer, DecoderState state) throws DecodeException {
-        final TypeDecoder<?> decoder = state.getDecoder().readNextTypeDecoder(buffer, state);
+        final byte encodingCode;
 
-        checkIsExpectedType(ListTypeDecoder.class, decoder);
+        try {
+            encodingCode = buffer.readByte();
+        } catch (IndexOutOfBoundsException e) {
+            throw new DecodeEOFException(e);
+        }
 
-        decoder.skipValue(buffer, state);
+        switch (encodingCode) {
+            case EncodingCodes.LIST0:
+                break;
+            case EncodingCodes.LIST8:
+                SMALL_LIST_TYPE_DECODER.skipValue(buffer, state);
+                break;
+            case EncodingCodes.LIST32:
+                LARGE_LIST_TYPE_DECODER.skipValue(buffer, state);
+                break;
+            default:
+                throw new DecodeException(
+                    "Expected list encoding but got decoder for type code: " + encodingCode);
+        }
 
         return Released.getInstance();
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/ProtonEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/ProtonEncoder.java
index c0d7bcd7..bdbd8ba0 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/ProtonEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/ProtonEncoder.java
@@ -708,7 +708,7 @@ public final class ProtonEncoder implements Encoder {
 
     @Override
     public <V> ProtonEncoder registerDescribedTypeEncoder(DescribedTypeEncoder<V> encoder) {
-        typeEncoders.put(encoder.getTypeClass(), encoder);
+        typeEncoders.put(encoder.getTypeClass(), encoder.encoderRegistered(this));
         return this;
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ApplicationPropertiesTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ApplicationPropertiesTypeEncoder.java
index a0548e4e..ec839860 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ApplicationPropertiesTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ApplicationPropertiesTypeEncoder.java
@@ -20,6 +20,7 @@ import org.apache.qpid.protonj2.buffer.ProtonBuffer;
 import org.apache.qpid.protonj2.codec.Encoder;
 import org.apache.qpid.protonj2.codec.EncoderState;
 import org.apache.qpid.protonj2.codec.encoders.AbstractDescribedMapTypeEncoder;
+import org.apache.qpid.protonj2.codec.encoders.primitives.StringTypeEncoder;
 import org.apache.qpid.protonj2.types.Symbol;
 import org.apache.qpid.protonj2.types.UnsignedLong;
 import org.apache.qpid.protonj2.types.messaging.ApplicationProperties;
@@ -29,6 +30,8 @@ import org.apache.qpid.protonj2.types.messaging.ApplicationProperties;
  */
 public final class ApplicationPropertiesTypeEncoder extends AbstractDescribedMapTypeEncoder<String, Object, ApplicationProperties> {
 
+    private static final StringTypeEncoder STRING_ENCODER = new StringTypeEncoder();
+
     @Override
     public Class<ApplicationProperties> getTypeClass() {
         return ApplicationProperties.class;
@@ -62,7 +65,7 @@ public final class ApplicationPropertiesTypeEncoder extends AbstractDescribedMap
     public void writeMapEntries(ProtonBuffer buffer, Encoder encoder, EncoderState state, ApplicationProperties properties) {
         // Write the Map elements and then compute total size written.
         properties.getValue().forEach((key, value) -> {
-            encoder.writeString(buffer, state, key);
+            STRING_ENCODER.writeType(buffer, state, key);
             encoder.writeObject(buffer, state, value);
         });
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/MessageAnnotationsTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/MessageAnnotationsTypeEncoder.java
index c4943bc4..3479534b 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/MessageAnnotationsTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/MessageAnnotationsTypeEncoder.java
@@ -20,6 +20,7 @@ import org.apache.qpid.protonj2.buffer.ProtonBuffer;
 import org.apache.qpid.protonj2.codec.Encoder;
 import org.apache.qpid.protonj2.codec.EncoderState;
 import org.apache.qpid.protonj2.codec.encoders.AbstractDescribedMapTypeEncoder;
+import org.apache.qpid.protonj2.codec.encoders.primitives.SymbolTypeEncoder;
 import org.apache.qpid.protonj2.types.Symbol;
 import org.apache.qpid.protonj2.types.UnsignedLong;
 import org.apache.qpid.protonj2.types.messaging.MessageAnnotations;
@@ -29,6 +30,8 @@ import org.apache.qpid.protonj2.types.messaging.MessageAnnotations;
  */
 public final class MessageAnnotationsTypeEncoder extends AbstractDescribedMapTypeEncoder<Symbol, Object, MessageAnnotations> {
 
+    private static final SymbolTypeEncoder SYMBOL_ENCODER = new SymbolTypeEncoder();
+
     @Override
     public Class<MessageAnnotations> getTypeClass() {
         return MessageAnnotations.class;
@@ -62,7 +65,7 @@ public final class MessageAnnotationsTypeEncoder extends AbstractDescribedMapTyp
     public void writeMapEntries(ProtonBuffer buffer, Encoder encoder, EncoderState state, MessageAnnotations annotations) {
         // Write the Map elements and then compute total size written.
         annotations.getValue().forEach((key, value) -> {
-            encoder.writeSymbol(buffer, state, key);
+            SYMBOL_ENCODER.writeType(buffer, state, key);
             encoder.writeObject(buffer, state, value);
         });
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/AttachTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/AttachTypeEncoder.java
index 920cc494..883c9aca 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/AttachTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/AttachTypeEncoder.java
@@ -47,107 +47,55 @@ public final class AttachTypeEncoder extends AbstractDescribedListTypeEncoder<At
 
     @Override
     public void writeElement(Attach attach, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (attach.hasName()) {
+        if (attach.hasElement(index)) {
+            switch (index) {
+                case 0:
                     encoder.writeString(buffer, state, attach.getName());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (attach.hasHandle()) {
+                    break;
+                case 1:
                     encoder.writeUnsignedInteger(buffer, state, attach.getHandle());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (attach.hasRole()) {
-                    buffer.writeByte(attach.getRole().getValue() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (attach.hasSenderSettleMode()) {
+                    break;
+                case 2:
+                    buffer.writeByte(attach.getRole().encodingCode());
+                    break;
+                case 3:
                     encoder.writeUnsignedByte(buffer, state, attach.getSenderSettleMode().byteValue());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (attach.hasReceiverSettleMode()) {
+                    break;
+                case 4:
                     encoder.writeUnsignedByte(buffer, state, attach.getReceiverSettleMode().byteValue());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 5:
-                if (attach.hasSource()) {
+                    break;
+                case 5:
                     encoder.writeObject(buffer, state, attach.getSource());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 6:
-                if (attach.hasTargetOrCoordinator()) {
+                    break;
+                case 6:
                     encoder.writeObject(buffer, state, attach.getTarget());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 7:
-                if (attach.hasUnsettled()) {
+                    break;
+                case 7:
                     encoder.writeMap(buffer, state, attach.getUnsettled());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 8:
-                if (attach.hasIncompleteUnsettled()) {
+                    break;
+                case 8:
                     buffer.writeByte(attach.getIncompleteUnsettled() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 9:
-                if (attach.hasInitialDeliveryCount()) {
+                    break;
+                case 9:
                     encoder.writeUnsignedInteger(buffer, state, attach.getInitialDeliveryCount());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 10:
-                if (attach.hasMaxMessageSize()) {
+                    break;
+                case 10:
                     encoder.writeUnsignedLong(buffer, state, attach.getMaxMessageSize());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 11:
-                if (attach.hasOfferedCapabilities()) {
+                    break;
+                case 11:
                     encoder.writeArray(buffer, state, attach.getOfferedCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 12:
-                if (attach.hasDesiredCapabilities()) {
+                    break;
+                case 12:
                     encoder.writeArray(buffer, state, attach.getDesiredCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 13:
-                if (attach.hasProperties()) {
+                    break;
+                case 13:
                     encoder.writeMap(buffer, state, attach.getProperties());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Attach value index: " + index);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Attach value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/BeginTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/BeginTypeEncoder.java
index c3007979..93b72504 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/BeginTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/BeginTypeEncoder.java
@@ -47,65 +47,37 @@ public final class BeginTypeEncoder extends AbstractDescribedListTypeEncoder<Beg
 
     @Override
     public void writeElement(Begin begin, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (begin.hasRemoteChannel()) {
+        if (begin.hasElement(index)) {
+            switch (index) {
+                case 0:
                     encoder.writeUnsignedShort(buffer, state, begin.getRemoteChannel());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (begin.hasNextOutgoingId()) {
+                    break;
+                case 1:
                     encoder.writeUnsignedInteger(buffer, state, begin.getNextOutgoingId());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (begin.hasIncomingWindow()) {
+                    break;
+                case 2:
                     encoder.writeUnsignedInteger(buffer, state, begin.getIncomingWindow());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (begin.hasOutgoingWindow()) {
+                    break;
+                case 3:
                     encoder.writeUnsignedInteger(buffer, state, begin.getOutgoingWindow());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (begin.hasHandleMax()) {
+                    break;
+                case 4:
                     encoder.writeUnsignedInteger(buffer, state, begin.getHandleMax());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 5:
-                if (begin.hasOfferedCapabilities()) {
+                    break;
+                case 5:
                     encoder.writeArray(buffer, state, begin.getOfferedCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 6:
-                if (begin.hasDesiredCapabilities()) {
+                    break;
+                case 6:
                     encoder.writeArray(buffer, state, begin.getDesiredCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 7:
-                if (begin.hasProperties()) {
+                    break;
+                case 7:
                     encoder.writeMap(buffer, state, begin.getProperties());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Begin value index: " + index);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Begin value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DetachTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DetachTypeEncoder.java
index d2c7cd96..69371e9c 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DetachTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DetachTypeEncoder.java
@@ -47,22 +47,22 @@ public final class DetachTypeEncoder extends AbstractDescribedListTypeEncoder<De
 
     @Override
     public void writeElement(Detach detach, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (detach.hasHandle()) {
+        if (detach.hasElement(index)) {
+            switch (index) {
+                case 0:
                     encoder.writeUnsignedInteger(buffer, state, detach.getHandle());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                buffer.writeByte(detach.getClosed() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                break;
-            case 2:
-                encoder.writeObject(buffer, state, detach.getError());
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Detach value index: " + index);
+                    break;
+                case 1:
+                    buffer.writeByte(detach.getClosed() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
+                    break;
+                case 2:
+                    encoder.writeObject(buffer, state, detach.getError());
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Detach value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
index b03fdb61..5b94cffe 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
@@ -54,58 +54,52 @@ public final class DispositionTypeEncoder extends AbstractDescribedListTypeEncod
         return Disposition.class;
     }
 
+    /*
+     * This assumes that the value was already check be the setter in Disposition
+     */
+    private static void writeCheckedUnsignedInteger(final long value, final ProtonBuffer buffer) {
+        if (value == 0) {
+            buffer.writeByte(EncodingCodes.UINT0);
+        } else if (value <= 255) {
+            buffer.writeByte(EncodingCodes.SMALLUINT);
+            buffer.writeByte((byte) value);
+        } else {
+            buffer.writeByte(EncodingCodes.UINT);
+            buffer.writeInt((int) value);
+        }
+    }
+
     @Override
     public void writeElement(Disposition disposition, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (disposition.hasRole()) {
-                    buffer.writeByte(disposition.getRole().getValue() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (disposition.hasFirst()) {
-                    encoder.writeUnsignedInteger(buffer, state, disposition.getFirst());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (disposition.hasLast()) {
-                    encoder.writeUnsignedInteger(buffer, state, disposition.getLast());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (disposition.hasSettled()) {
+        if (disposition.hasElement(index)) {
+            switch (index) {
+                case 0:
+                    buffer.writeByte(disposition.getRole().encodingCode());
+                    break;
+                case 1:
+                    writeCheckedUnsignedInteger(disposition.getFirst(), buffer);
+                    break;
+                case 2:
+                    writeCheckedUnsignedInteger(disposition.getLast(), buffer);
+                    break;
+                case 3:
                     buffer.writeByte(disposition.getSettled() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (disposition.hasState()) {
+                    break;
+                case 4:
                     if (disposition.getState() == Accepted.getInstance()) {
                         buffer.writeBytes(ACCEPTED_ENCODING);
                     } else {
                         encoder.writeObject(buffer, state, disposition.getState());
                     }
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-
-                break;
-            case 5:
-                if (disposition.hasBatchable()) {
+                    break;
+                case 5:
                     buffer.writeByte(disposition.getBatchable() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Disposition value index: " + index);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Disposition value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/FlowTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/FlowTypeEncoder.java
index b2cf747b..1953853c 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/FlowTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/FlowTypeEncoder.java
@@ -45,84 +45,63 @@ public final class FlowTypeEncoder extends AbstractDescribedListTypeEncoder<Flow
         return Flow.class;
     }
 
+    /*
+     * This assumes that the value was already check be the setter in Flow
+     */
+    private static void writeCheckedUnsignedInteger(final long value, final ProtonBuffer buffer) {
+        if (value == 0) {
+            buffer.writeByte(EncodingCodes.UINT0);
+        } else if (value <= 255) {
+            buffer.writeByte(EncodingCodes.SMALLUINT);
+            buffer.writeByte((byte) value);
+        } else {
+            buffer.writeByte(EncodingCodes.UINT);
+            buffer.writeInt((int) value);
+        }
+    }
+
     @Override
     public void writeElement(Flow flow, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (flow.hasNextIncomingId()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getNextIncomingId());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (flow.hasIncomingWindow()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getIncomingWindow());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (flow.hasNextOutgoingId()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getNextOutgoingId());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (flow.hasOutgoingWindow()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getOutgoingWindow());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (flow.hasHandle()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getHandle());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 5:
-                if (flow.hasDeliveryCount()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getDeliveryCount());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 6:
-                if (flow.hasLinkCredit()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getLinkCredit());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 7:
-                if (flow.hasAvailable()) {
-                    encoder.writeUnsignedInteger(buffer, state, flow.getAvailable());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 8:
-                if (flow.hasDrain()) {
+        if (flow.hasElement(index)) {
+            switch (index) {
+                case 0:
+                    writeCheckedUnsignedInteger(flow.getNextIncomingId(), buffer);
+                    break;
+                case 1:
+                    writeCheckedUnsignedInteger(flow.getIncomingWindow(), buffer);
+                    break;
+                case 2:
+                    writeCheckedUnsignedInteger(flow.getNextOutgoingId(), buffer);
+                    break;
+                case 3:
+                    writeCheckedUnsignedInteger(flow.getOutgoingWindow(), buffer);
+                    break;
+                case 4:
+                    writeCheckedUnsignedInteger(flow.getHandle(), buffer);
+                    break;
+                case 5:
+                    writeCheckedUnsignedInteger(flow.getDeliveryCount(), buffer);
+                    break;
+                case 6:
+                    writeCheckedUnsignedInteger(flow.getLinkCredit(), buffer);
+                    break;
+                case 7:
+                    writeCheckedUnsignedInteger(flow.getAvailable(), buffer);
+                    break;
+                case 8:
                     buffer.writeByte(flow.getDrain() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 9:
-                if (flow.hasEcho()) {
+                    break;
+                case 9:
                     buffer.writeByte(flow.getEcho() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 10:
-                encoder.writeMap(buffer, state, flow.getProperties());
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Flow value index: " + index);
+                    break;
+                case 10:
+                    encoder.writeMap(buffer, state, flow.getProperties());
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Flow value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/OpenTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/OpenTypeEncoder.java
index 66131281..5091ca23 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/OpenTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/OpenTypeEncoder.java
@@ -47,79 +47,43 @@ public final class OpenTypeEncoder extends AbstractDescribedListTypeEncoder<Open
 
     @Override
     public void writeElement(Open open, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (open.hasContainerId()) {
+        if (open.hasElement(index)) {
+            switch (index) {
+                case 0:
                     encoder.writeString(buffer, state, open.getContainerId());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (open.hasHostname()) {
+                    break;
+                case 1:
                     encoder.writeString(buffer, state, open.getHostname());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (open.hasMaxFrameSize()) {
+                    break;
+                case 2:
                     encoder.writeUnsignedInteger(buffer, state, open.getMaxFrameSize());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (open.hasChannelMax()) {
+                    break;
+                case 3:
                     encoder.writeUnsignedShort(buffer, state, open.getChannelMax());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (open.hasIdleTimeout()) {
+                    break;
+                case 4:
                     encoder.writeUnsignedInteger(buffer, state, open.getIdleTimeout());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 5:
-                if (open.hasOutgoingLocales()) {
+                    break;
+                case 5:
                     encoder.writeArray(buffer, state, open.getOutgoingLocales());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 6:
-                if (open.hasIncomingLocales()) {
+                    break;
+                case 6:
                     encoder.writeArray(buffer, state, open.getIncomingLocales());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 7:
-                if (open.hasOfferedCapabilities()) {
+                    break;
+                case 7:
                     encoder.writeArray(buffer, state, open.getOfferedCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 8:
-                if (open.hasDesiredCapabilities()) {
+                    break;
+                case 8:
                     encoder.writeArray(buffer, state, open.getDesiredCapabilities());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 9:
-                if (open.hasProperties()) {
+                    break;
+                case 9:
                     encoder.writeMap(buffer, state, open.getProperties());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Open value index: " + index);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Open value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/TransferTypeEncoder.java b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/TransferTypeEncoder.java
index 5120df1b..09fda1e0 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/TransferTypeEncoder.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/TransferTypeEncoder.java
@@ -45,84 +45,64 @@ public final class TransferTypeEncoder extends AbstractDescribedListTypeEncoder<
         return Transfer.class;
     }
 
+    /*
+     * This assumes that the value was already check be the setter in Transfer
+     */
+    private static void writeCheckedUnsignedInteger(final long value, final ProtonBuffer buffer) {
+        if (value == 0) {
+            buffer.writeByte(EncodingCodes.UINT0);
+        } else if (value <= 255) {
+            buffer.writeByte(EncodingCodes.SMALLUINT);
+            buffer.writeByte((byte) value);
+        } else {
+            buffer.writeByte(EncodingCodes.UINT);
+            buffer.writeInt((int) value);
+        }
+    }
+
     @Override
     public void writeElement(Transfer transfer, int index, ProtonBuffer buffer, Encoder encoder, EncoderState state) {
-        switch (index) {
-            case 0:
-                if (transfer.hasHandle()) {
-                    encoder.writeUnsignedInteger(buffer, state, transfer.getHandle());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 1:
-                if (transfer.hasDeliveryId()) {
-                    encoder.writeUnsignedInteger(buffer, state, transfer.getDeliveryId());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 2:
-                if (transfer.hasDeliveryTag()) {
+        if (transfer.hasElement(index)) {
+            switch (index) {
+                case 0:
+                    writeCheckedUnsignedInteger(transfer.getHandle(), buffer);
+                    break;
+                case 1:
+                    writeCheckedUnsignedInteger(transfer.getDeliveryId(), buffer);
+                    break;
+                case 2:
                     encoder.writeDeliveryTag(buffer, state, transfer.getDeliveryTag());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 3:
-                if (transfer.hasMessageFormat()) {
-                    encoder.writeUnsignedInteger(buffer, state, transfer.getMessageFormat());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 4:
-                if (transfer.hasSettled()) {
+                    break;
+                case 3:
+                    writeCheckedUnsignedInteger(transfer.getMessageFormat(), buffer);
+                    break;
+                case 4:
                     buffer.writeByte(transfer.getSettled() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 5:
-                if (transfer.hasMore()) {
+                    break;
+                case 5:
                     buffer.writeByte(transfer.getMore() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 6:
-                if (transfer.hasRcvSettleMode()) {
-                    encoder.writeUnsignedByte(buffer, state, transfer.getRcvSettleMode().byteValue());
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 7:
-                encoder.writeObject(buffer, state, transfer.getState());
-                break;
-            case 8:
-                if (transfer.hasResume()) {
+                    break;
+                case 6:
+                    buffer.writeByte(EncodingCodes.UBYTE);
+                    buffer.writeByte(transfer.getRcvSettleMode().byteValue());
+                    break;
+                case 7:
+                    encoder.writeObject(buffer, state, transfer.getState());
+                    break;
+                case 8:
                     buffer.writeByte(transfer.getResume() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 9:
-                if (transfer.hasAborted()) {
+                    break;
+                case 9:
                     buffer.writeByte(transfer.getAborted() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            case 10:
-                if (transfer.hasBatchable()) {
+                    break;
+                case 10:
                     buffer.writeByte(transfer.getBatchable() ? EncodingCodes.BOOLEAN_TRUE : EncodingCodes.BOOLEAN_FALSE);
-                } else {
-                    buffer.writeByte(EncodingCodes.NULL);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown Transfer value index: " + index);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown Transfer value index: " + index);
+            }
+        } else {
+            buffer.writeByte(EncodingCodes.NULL);
         }
     }
 
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Attach.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Attach.java
index 950d7508..04dedbf3 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Attach.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Attach.java
@@ -120,6 +120,11 @@ public final class Attach implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasName() {
         return (modified & NAME) == NAME;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Begin.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Begin.java
index ed80613d..59850cc4 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Begin.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Begin.java
@@ -96,6 +96,11 @@ public final class Begin implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasRemoteChannel() {
         return (modified & REMOTE_CHANNEL) == REMOTE_CHANNEL;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Detach.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Detach.java
index 3de21b3b..9a472ebb 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Detach.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Detach.java
@@ -52,6 +52,11 @@ public final class Detach implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasHandle() {
         return (modified & HANDLE) == HANDLE;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Disposition.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Disposition.java
index cff0e172..fcf19897 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Disposition.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Disposition.java
@@ -53,6 +53,11 @@ public final class Disposition implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasRole() {
         return (modified & ROLE) == ROLE;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Flow.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Flow.java
index 7a83ec18..b9cc31d6 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Flow.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Flow.java
@@ -71,6 +71,11 @@ public final class Flow implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasNextIncomingId() {
         return (modified & NEXT_INCOMING_ID) == NEXT_INCOMING_ID;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Open.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Open.java
index 53c2d855..57066508 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Open.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Open.java
@@ -108,6 +108,11 @@ public final class Open implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasContainerId() {
         return (modified & CONTAINER_ID) == CONTAINER_ID;
     }
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Role.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Role.java
index 9e5a13ce..c9e0ab67 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Role.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Role.java
@@ -16,6 +16,8 @@
  */
 package org.apache.qpid.protonj2.types.transport;
 
+import org.apache.qpid.protonj2.codec.EncodingCodes;
+
 public enum Role {
 
     SENDER(false), RECEIVER(true);
@@ -30,6 +32,14 @@ public enum Role {
         return receiver;
     }
 
+    public byte encodingCode() {
+        if (receiver) {
+            return EncodingCodes.BOOLEAN_TRUE;
+        } else {
+            return EncodingCodes.BOOLEAN_FALSE;
+        }
+    }
+
     public static Role valueOf(boolean role) {
         if (role) {
             return RECEIVER;
diff --git a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Transfer.java b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Transfer.java
index 0be53029..fb3c4d96 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Transfer.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/transport/Transfer.java
@@ -70,6 +70,11 @@ public final class Transfer implements Performative {
         return 32 - Integer.numberOfLeadingZeros(modified);
     }
 
+    public boolean hasElement(int index) {
+        final int value = 1 << index;
+        return (modified & value) == value;
+    }
+
     public boolean hasHandle() {
         return (modified & HANDLE) == HANDLE;
     }
diff --git a/protonj2/src/test/java/org/apache/qpid/protonj2/codec/benchmark/Benchmark.java b/protonj2/src/test/java/org/apache/qpid/protonj2/codec/benchmark/Benchmark.java
index 669690ab..91f08090 100644
--- a/protonj2/src/test/java/org/apache/qpid/protonj2/codec/benchmark/Benchmark.java
+++ b/protonj2/src/test/java/org/apache/qpid/protonj2/codec/benchmark/Benchmark.java
@@ -96,6 +96,7 @@ public class Benchmark implements Runnable {
         benchmarkApplicationProperties();
         benchmarkSymbols();
         benchmarkTransfer();
+        benchmarkAccepted();
         benchmarkFlow();
         benchmarkDisposition();
         benchmarkString();
@@ -169,6 +170,25 @@ public class Benchmark implements Runnable {
         time("Transfer", resultSet);
     }
 
+    private void benchmarkAccepted() throws IOException {
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            buffer.clear();
+            encoder.writeObject(buffer, encoderState, Accepted.getInstance());
+        }
+        resultSet.encodesComplete();
+
+        resultSet.start();
+        for (int i = 0; i < ITERATIONS; i++) {
+            buffer.setReadIndex(0);
+            decoder.readObject(buffer, decoderState);
+        }
+        resultSet.decodesComplete();
+
+        time("Accepted", resultSet);
+    }
+
     private void benchmarkFlow() throws IOException {
         Flow flow = new Flow();
         flow.setNextIncomingId(1);
diff --git a/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/DispositionTest.java b/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/DispositionTest.java
index db4c3444..f0f4f840 100644
--- a/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/DispositionTest.java
+++ b/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/DispositionTest.java
@@ -96,6 +96,13 @@ public class DispositionTest {
         assertFalse(disposition.hasRole());
         assertFalse(disposition.hasSettled());
         assertFalse(disposition.hasState());
+
+        assertFalse(disposition.hasElement(0));
+        assertFalse(disposition.hasElement(1));
+        assertFalse(disposition.hasElement(2));
+        assertFalse(disposition.hasElement(3));
+        assertFalse(disposition.hasElement(4));
+        assertFalse(disposition.hasElement(5));
     }
 
     @Test
@@ -117,6 +124,14 @@ public class DispositionTest {
         assertTrue(disposition.hasSettled());
         assertTrue(disposition.hasState());
 
+        assertTrue(disposition.hasElement(0));
+        assertTrue(disposition.hasElement(1));
+        assertTrue(disposition.hasElement(2));
+        assertTrue(disposition.hasElement(3));
+        assertTrue(disposition.hasElement(4));
+        assertTrue(disposition.hasElement(5));
+        assertFalse(disposition.hasElement(6));
+
         disposition.clearBatchable();
         disposition.clearFirst();
         disposition.clearLast();
diff --git a/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/TransferTest.java b/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/TransferTest.java
index 49e48670..b8194a74 100644
--- a/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/TransferTest.java
+++ b/protonj2/src/test/java/org/apache/qpid/protonj2/types/transport/TransferTest.java
@@ -89,6 +89,19 @@ public class TransferTest {
         assertTrue(transfer.hasSettled());
         assertTrue(transfer.hasState());
 
+        assertTrue(transfer.hasElement(0));
+        assertTrue(transfer.hasElement(1));
+        assertTrue(transfer.hasElement(2));
+        assertTrue(transfer.hasElement(3));
+        assertTrue(transfer.hasElement(4));
+        assertTrue(transfer.hasElement(5));
+        assertTrue(transfer.hasElement(6));
+        assertTrue(transfer.hasElement(7));
+        assertTrue(transfer.hasElement(8));
+        assertTrue(transfer.hasElement(9));
+        assertTrue(transfer.hasElement(10));
+        assertFalse(transfer.hasElement(11));
+
         transfer.clearAborted();
         transfer.clearBatchable();
         transfer.clearDeliveryId();
@@ -115,6 +128,19 @@ public class TransferTest {
         assertFalse(transfer.hasSettled());
         assertFalse(transfer.hasState());
 
+        assertFalse(transfer.hasElement(0));
+        assertFalse(transfer.hasElement(1));
+        assertFalse(transfer.hasElement(2));
+        assertFalse(transfer.hasElement(3));
+        assertFalse(transfer.hasElement(4));
+        assertFalse(transfer.hasElement(5));
+        assertFalse(transfer.hasElement(6));
+        assertFalse(transfer.hasElement(7));
+        assertFalse(transfer.hasElement(8));
+        assertFalse(transfer.hasElement(9));
+        assertFalse(transfer.hasElement(10));
+        assertFalse(transfer.hasElement(11));
+
         transfer.setDeliveryTag(new byte[] { 1 });
         assertTrue(transfer.hasDeliveryTag());
         transfer.setDeliveryTag((byte[]) null);


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