/// <summary>
        /// Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
        /// </summary>
        ///
        /// <param name="lpPacket">The LpPacket object whose fields are updated.</param>
        /// <param name="input"></param>
        /// <param name="copy">unchanged while the Blob values are used.</param>
        /// <exception cref="EncodingException">For invalid encoding.</exception>
        public override void decodeLpPacket(LpPacket lpPacket, ByteBuffer input, bool copy)
        {
            lpPacket.clear();

            TlvDecoder decoder = new TlvDecoder(input);
            int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket);

            while (decoder.getOffset() < endOffset) {
                // Imitate TlvDecoder.readTypeAndLength.
                int fieldType = decoder.readVarNumber();
                int fieldLength = decoder.readVarNumber();
                int fieldEndOffset = decoder.getOffset() + fieldLength;
                if (fieldEndOffset > input.limit())
                    throw new EncodingException(
                            "TLV length exceeds the buffer length");

                if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Fragment) {
                    // Set the fragment to the bytes of the TLV value.
                    lpPacket.setFragmentWireEncoding(new Blob(decoder.getSlice(
                            decoder.getOffset(), fieldEndOffset), copy));
                    decoder.seek(fieldEndOffset);

                    // The fragment is supposed to be the last field.
                    break;
                } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Nack) {
                    NetworkNack networkNack = new NetworkNack();
                    int code = (int) decoder.readOptionalNonNegativeIntegerTlv(
                            net.named_data.jndn.encoding.tlv.Tlv.LpPacket_NackReason, fieldEndOffset);
                    // The enum numeric values are the same as this wire format, so use as is.
                    if (code < 0
                            || code == net.named_data.jndn.NetworkNack.Reason.NONE.getNumericType())
                        // This includes an omitted NackReason.
                        networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NONE);
                    else if (code == net.named_data.jndn.NetworkNack.Reason.CONGESTION.getNumericType())
                        networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.CONGESTION);
                    else if (code == net.named_data.jndn.NetworkNack.Reason.DUPLICATE.getNumericType())
                        networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.DUPLICATE);
                    else if (code == net.named_data.jndn.NetworkNack.Reason.NO_ROUTE.getNumericType())
                        networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NO_ROUTE);
                    else {
                        // Unrecognized reason.
                        networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.OTHER_CODE);
                        networkNack.setOtherReasonCode(code);
                    }

                    lpPacket.addHeaderField(networkNack);
                } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IncomingFaceId) {
                    IncomingFaceId incomingFaceId = new IncomingFaceId();
                    incomingFaceId.setFaceId(decoder
                            .readNonNegativeInteger(fieldLength));
                    lpPacket.addHeaderField(incomingFaceId);
                } else {
                    // Unrecognized field type. The conditions for ignoring are here:
                    // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
                    bool canIgnore = (fieldType >= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MIN
                            && fieldType <= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MAX && (fieldType & 0x01) == 1);
                    if (!canIgnore)
                        throw new EncodingException(
                                "Did not get the expected TLV type");

                    // Ignore.
                    decoder.seek(fieldEndOffset);
                }

                decoder.finishNestedTlvs(fieldEndOffset);
            }

            decoder.finishNestedTlvs(endOffset);
        }