/// <summary> /// Encode this Schedule. /// </summary> /// /// <returns>The encoded buffer.</returns> public Blob wireEncode() { // For now, don't use WireFormat and hardcode to use TLV since the encoding // doesn't go out over the wire, only into the local SQL database. TlvEncoder encoder = new TlvEncoder(256); int saveLength = encoder.getLength(); // Encode backwards. // Encode the blackIntervalList. int saveLengthForList = encoder.getLength(); Object[] array = ILOG.J2CsMapping.Collections.Collections.ToArray(blackIntervalList_); System.Array.Sort(array); for (int i = array.Length - 1; i >= 0; --i) { RepetitiveInterval element = (RepetitiveInterval) array[i]; encodeRepetitiveInterval(element, encoder); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_BlackIntervalList, encoder.getLength() - saveLengthForList); // Encode the whiteIntervalList. saveLengthForList = encoder.getLength(); array = ILOG.J2CsMapping.Collections.Collections.ToArray(whiteIntervalList_); System.Array.Sort(array); for (int i_0 = array.Length - 1; i_0 >= 0; --i_0) { RepetitiveInterval element_1 = (RepetitiveInterval) array[i_0]; encodeRepetitiveInterval(element_1, encoder); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_WhiteIntervalList, encoder.getLength() - saveLengthForList); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_Schedule, encoder.getLength() - saveLength); return new Blob(encoder.getOutput(), false); }
/// <summary> /// Encode the RepetitiveInterval as NDN-TLV to the encoder. /// </summary> /// /// <param name="repetitiveInterval">The RepetitiveInterval to encode.</param> /// <param name="encoder">The TlvEncoder to receive the encoding.</param> private static void encodeRepetitiveInterval( RepetitiveInterval repetitiveInterval, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_RepeatUnit, net.named_data.jndn.encrypt.RepetitiveInterval.getRepeatUnitNumericType(repetitiveInterval .getRepeatUnit())); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_NRepeats, repetitiveInterval.getNRepeats()); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_IntervalEndHour, repetitiveInterval.getIntervalEndHour()); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_IntervalStartHour, repetitiveInterval.getIntervalStartHour()); // Use Blob to convert the string to UTF8 encoding. encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_EndDate, new Blob( toIsoString(repetitiveInterval.getEndDate())).buf()); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_StartDate, new Blob( toIsoString(repetitiveInterval.getStartDate())).buf()); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_RepetitiveInterval, encoder.getLength() - saveLength); }
private static void encodeControlParameters( ControlParameters controlParameters, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. encoder.writeOptionalNonNegativeIntegerTlvFromDouble( net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_ExpirationPeriod, controlParameters.getExpirationPeriod()); // Encode strategy if (controlParameters.getStrategy().size() != 0) { int strategySaveLength = encoder.getLength(); encodeName(controlParameters.getStrategy(), new int[1], new int[1], encoder); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_Strategy, encoder.getLength() - strategySaveLength); } // Encode ForwardingFlags int flags = controlParameters.getForwardingFlags() .getNfdForwardingFlags(); if (flags != new ForwardingFlags().getNfdForwardingFlags()) // The flags are not the default value. encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_Flags, flags); encoder.writeOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_Cost, controlParameters.getCost()); encoder.writeOptionalNonNegativeIntegerTlv( net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_Origin, controlParameters.getOrigin()); encoder.writeOptionalNonNegativeIntegerTlv( net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_LocalControlFeature, controlParameters.getLocalControlFeature()); // Encode URI if (controlParameters.getUri().Length != 0) { encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_Uri, new Blob( controlParameters.getUri()).buf()); } encoder.writeOptionalNonNegativeIntegerTlv( net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_FaceId, controlParameters.getFaceId()); // Encode name if (controlParameters.getName() != null) { encodeName(controlParameters.getName(), new int[1], new int[1], encoder); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength); }
private static void encodeExclude(Exclude exclude, TlvEncoder encoder) { int saveLength = encoder.getLength(); // TODO: Do we want to order the components (except for ANY)? // Encode the entries backwards. for (int i = exclude.size() - 1; i >= 0; --i) { Exclude.Entry entry = exclude.get(i); if (entry.getType() == net.named_data.jndn.Exclude.Type.ANY) encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Any, 0); else encodeNameComponent(entry.getComponent(), encoder); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Exclude, encoder.getLength() - saveLength); }
/// <summary> /// Encode the EncryptedContent in NDN-TLV and return the encoding. /// </summary> /// /// <param name="encryptedContent">The EncryptedContent object to encode.</param> /// <returns>A Blob containing the encoding.</returns> public override Blob encodeEncryptedContent(EncryptedContent encryptedContent) { TlvEncoder encoder = new TlvEncoder(256); int saveLength = encoder.getLength(); // Encode backwards. encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_EncryptedPayload, encryptedContent .getPayload().buf()); encoder.writeOptionalBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_InitialVector, encryptedContent.getInitialVector().buf()); // Assume the algorithmType value is the same as the TLV type. encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_EncryptionAlgorithm, encryptedContent.getAlgorithmType().getNumericType()); Tlv0_2WireFormat.encodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, encryptedContent.getKeyLocator(), encoder); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Encrypt_EncryptedContent, encoder.getLength() - saveLength); return new Blob(encoder.getOutput(), false); }
/// <summary> /// Encode interest using NDN-TLV and return the encoding. /// </summary> /// /// <param name="interest">The Interest object to encode.</param> /// <param name="signedPortionBeginOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param> /// <param name="signedPortionEndOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param> /// <returns>A Blob containing the encoding.</returns> public override Blob encodeInterest(Interest interest, int[] signedPortionBeginOffset, int[] signedPortionEndOffset) { TlvEncoder encoder = new TlvEncoder(); int saveLength = encoder.getLength(); // Encode backwards. encoder.writeOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SelectedDelegation, interest.getSelectedDelegationIndex()); try { Blob linkWireEncoding = interest.getLinkWireEncoding(this); if (!linkWireEncoding.isNull()) // Encode the entire link as is. encoder.writeBuffer(linkWireEncoding.buf()); } catch (EncodingException ex) { throw new Exception(ex.Message); } encoder.writeOptionalNonNegativeIntegerTlvFromDouble( net.named_data.jndn.encoding.tlv.Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds()); // Encode the Nonce as 4 bytes. if (interest.getNonce().size() == 0) { // This is the most common case. Generate a nonce. ByteBuffer nonce = ILOG.J2CsMapping.NIO.ByteBuffer.allocate(4); random_.nextBytes(nonce.array()); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Nonce, nonce); } else if (interest.getNonce().size() < 4) { ByteBuffer nonce_0 = ILOG.J2CsMapping.NIO.ByteBuffer.allocate(4); // Copy existing nonce bytes. nonce_0.put(interest.getNonce().buf()); // Generate random bytes for remaining bytes in the nonce. for (int i = 0; i < 4 - interest.getNonce().size(); ++i) nonce_0.put((byte) random_.Next()); nonce_0.flip(); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Nonce, nonce_0); } else if (interest.getNonce().size() == 4) // Use the nonce as-is. encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Nonce, interest.getNonce().buf()); else { // Truncate. ByteBuffer nonce_1 = interest.getNonce().buf(); // buf() returns a new ByteBuffer, so we can change its limit. nonce_1.limit(nonce_1.position() + 4); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Nonce, nonce_1); } encodeSelectors(interest, encoder); int[] tempSignedPortionBeginOffset = new int[1]; int[] tempSignedPortionEndOffset = new int[1]; encodeName(interest.getName(), tempSignedPortionBeginOffset, tempSignedPortionEndOffset, encoder); int signedPortionBeginOffsetFromBack = encoder.getLength() - tempSignedPortionBeginOffset[0]; int signedPortionEndOffsetFromBack = encoder.getLength() - tempSignedPortionEndOffset[0]; encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Interest, encoder.getLength() - saveLength); signedPortionBeginOffset[0] = encoder.getLength() - signedPortionBeginOffsetFromBack; signedPortionEndOffset[0] = encoder.getLength() - signedPortionEndOffsetFromBack; return new Blob(encoder.getOutput(), false); }
/// <summary> /// Encode data in NDN-TLV and return the encoding. /// </summary> /// /// <param name="data">The Data object to encode.</param> /// <param name="signedPortionBeginOffset">If you are not encoding in order to sign, you can call encodeData(data) to ignore this returned value.</param> /// <param name="signedPortionEndOffset">If you are not encoding in order to sign, you can call encodeData(data) to ignore this returned value.</param> /// <returns>A Blob containing the encoding.</returns> public override Blob encodeData(Data data, int[] signedPortionBeginOffset, int[] signedPortionEndOffset) { TlvEncoder encoder = new TlvEncoder(1500); int saveLength = encoder.getLength(); // Encode backwards. encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureValue, (data.getSignature()) .getSignature().buf()); int signedPortionEndOffsetFromBack = encoder.getLength(); encodeSignatureInfo(data.getSignature(), encoder); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.Content, data.getContent().buf()); encodeMetaInfo(data.getMetaInfo(), encoder); encodeName(data.getName(), new int[1], new int[1], encoder); int signedPortionBeginOffsetFromBack = encoder.getLength(); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Data, encoder.getLength() - saveLength); signedPortionBeginOffset[0] = encoder.getLength() - signedPortionBeginOffsetFromBack; signedPortionEndOffset[0] = encoder.getLength() - signedPortionEndOffsetFromBack; return new Blob(encoder.getOutput(), false); }
/// <summary> /// Encode delegationSet as a sequence of NDN-TLV Delegation, and return the /// encoding. Note that the sequence of Delegation does not have an outer TLV /// type and length because it is intended to use the type and length of a Data /// packet's Content. /// </summary> /// /// <param name="delegationSet">The DelegationSet object to encode.</param> /// <returns>A Blob containing the encoding.</returns> public override Blob encodeDelegationSet(DelegationSet delegationSet) { TlvEncoder encoder = new TlvEncoder(256); // Encode backwards. for (int i = delegationSet.size() - 1; i >= 0; --i) { int saveLength = encoder.getLength(); encodeName(delegationSet.get(i).getName(), new int[1], new int[1], encoder); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Link_Preference, delegationSet.get(i).getPreference()); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Link_Delegation, encoder.getLength() - saveLength); } return new Blob(encoder.getOutput(), false); }
/// <summary> /// An internal method to encode signature as the appropriate form of /// SignatureInfo in NDN-TLV. /// </summary> /// /// <param name="signature">An object of a subclass of Signature to encode.</param> /// <param name="encoder">The TlvEncoder to receive the encoding.</param> private void encodeSignatureInfo(Signature signature, TlvEncoder encoder) { if (signature is GenericSignature) { // Handle GenericSignature separately since it has the entire encoding. Blob encoding = ((GenericSignature) signature) .getSignatureInfoEncoding(); // Do a test decoding to sanity check that it is valid TLV. try { TlvDecoder decoder = new TlvDecoder(encoding.buf()); int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.SignatureInfo); decoder.readNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType); decoder.finishNestedTlvs(endOffset); } catch (EncodingException ex) { throw new Exception( "The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: " + ex.Message); } encoder.writeBuffer(encoding.buf()); return; } int saveLength = encoder.getLength(); // Encode backwards. if (signature is Sha256WithRsaSignature) { if (((Sha256WithRsaSignature) signature).getValidityPeriod() .hasPeriod()) encodeValidityPeriod( ((Sha256WithRsaSignature) signature) .getValidityPeriod(), encoder); encodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, ((Sha256WithRsaSignature) signature).getKeyLocator(), encoder); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType, net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureSha256WithRsa); } else if (signature is Sha256WithEcdsaSignature) { if (((Sha256WithEcdsaSignature) signature).getValidityPeriod() .hasPeriod()) encodeValidityPeriod( ((Sha256WithEcdsaSignature) signature) .getValidityPeriod(), encoder); encodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, ((Sha256WithEcdsaSignature) signature).getKeyLocator(), encoder); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType, net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureSha256WithEcdsa); } else if (signature is HmacWithSha256Signature) { encodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.KeyLocator, ((HmacWithSha256Signature) signature).getKeyLocator(), encoder); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType, net.named_data.jndn.encoding.tlv.Tlv.SignatureType_SignatureHmacWithSha256); } else if (signature is DigestSha256Signature) encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.SignatureType, net.named_data.jndn.encoding.tlv.Tlv.SignatureType_DigestSha256); else throw new Exception( "encodeSignatureInfo: Unrecognized Signature object type"); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.SignatureInfo, encoder.getLength() - saveLength); }
/// <summary> /// Encode controlResponse in NDN-TLV and return the encoding. /// </summary> /// /// <param name="controlResponse">The ControlResponse object to encode.</param> /// <returns>A Blob containing the encoding.</returns> public override Blob encodeControlResponse(ControlResponse controlResponse) { TlvEncoder encoder = new TlvEncoder(256); int saveLength = encoder.getLength(); // Encode backwards. // Encode the body. if (controlResponse.getBodyAsControlParameters() != null) encodeControlParameters( controlResponse.getBodyAsControlParameters(), encoder); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.NfdCommand_StatusText, new Blob( controlResponse.getStatusText()).buf()); encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.NfdCommand_StatusCode, controlResponse.getStatusCode()); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.NfdCommand_ControlResponse, encoder.getLength() - saveLength); return new Blob(encoder.getOutput(), false); }
private static void encodeValidityPeriod(ValidityPeriod validityPeriod, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.ValidityPeriod_NotAfter, new Blob(net.named_data.jndn.encrypt.Schedule.toIsoString(validityPeriod.getNotAfter())) .buf()); encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.ValidityPeriod_NotBefore, new Blob(net.named_data.jndn.encrypt.Schedule.toIsoString(validityPeriod.getNotBefore())) .buf()); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.ValidityPeriod_ValidityPeriod, encoder.getLength() - saveLength); }
/// <summary> /// Encode the interest selectors. If no selectors are written, do not output /// a Selectors TLV. /// </summary> /// private static void encodeSelectors(Interest interest, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. if (interest.getMustBeFresh()) encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.MustBeFresh, 0); encoder.writeOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.ChildSelector, interest.getChildSelector()); if (interest.getExclude().size() > 0) encodeExclude(interest.getExclude(), encoder); if (interest.getKeyLocator().getType() != net.named_data.jndn.KeyLocatorType.NONE) encodeKeyLocator(net.named_data.jndn.encoding.tlv.Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), encoder); encoder.writeOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents()); encoder.writeOptionalNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.MinSuffixComponents, interest.getMinSuffixComponents()); // Only output the type and length if values were written. if (encoder.getLength() != saveLength) encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Selectors, encoder.getLength() - saveLength); }
/// <summary> /// Encode the name as NDN-TLV to the encoder. /// </summary> /// /// <param name="name">The name to encode.</param> /// <param name="signedPortionBeginOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param> /// <param name="signedPortionEndOffset">name component and ends just before the final name component (which is assumed to be a signature for a signed interest).</param> /// <param name="encoder">The TlvEncoder to receive the encoding.</param> private static void encodeName(Name name, int[] signedPortionBeginOffset, int[] signedPortionEndOffset, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode the components backwards. int signedPortionEndOffsetFromBack = 0; for (int i = name.size() - 1; i >= 0; --i) { encodeNameComponent(name.get(i), encoder); if (i == name.size() - 1) signedPortionEndOffsetFromBack = encoder.getLength(); } int signedPortionBeginOffsetFromBack = encoder.getLength(); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Name, encoder.getLength() - saveLength); signedPortionBeginOffset[0] = encoder.getLength() - signedPortionBeginOffsetFromBack; if (name.size() == 0) // There is no "final component", so set signedPortionEndOffset // arbitrarily. signedPortionEndOffset[0] = signedPortionBeginOffset[0]; else signedPortionEndOffset[0] = encoder.getLength() - signedPortionEndOffsetFromBack; }
private static void encodeMetaInfo(MetaInfo metaInfo, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. ByteBuffer finalBlockIdBuf = metaInfo.getFinalBlockId().getValue() .buf(); if (finalBlockIdBuf != null && finalBlockIdBuf.remaining() > 0) { // FinalBlockId has an inner NameComponent. int finalBlockIdSaveLength = encoder.getLength(); encodeNameComponent(metaInfo.getFinalBlockId(), encoder); encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength); } encoder.writeOptionalNonNegativeIntegerTlvFromDouble( net.named_data.jndn.encoding.tlv.Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod()); if (!(metaInfo.getType() == net.named_data.jndn.ContentType.BLOB)) { // Not the default, so we need to encode the type. if (metaInfo.getType() == net.named_data.jndn.ContentType.LINK || metaInfo.getType() == net.named_data.jndn.ContentType.KEY || metaInfo.getType() == net.named_data.jndn.ContentType.NACK) // The ContentType enum is set up with the correct integer for // each NDN-TLV ContentType. encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.ContentType, metaInfo .getType().getNumericType()); else if (metaInfo.getType() == net.named_data.jndn.ContentType.OTHER_CODE) encoder.writeNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.ContentType, metaInfo.getOtherTypeCode()); else // We don't expect this to happen. throw new Exception("unrecognized TLV ContentType"); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.MetaInfo, encoder.getLength() - saveLength); }
private static void encodeKeyLocator(int type, KeyLocator keyLocator, TlvEncoder encoder) { int saveLength = encoder.getLength(); // Encode backwards. if (keyLocator.getType() != net.named_data.jndn.KeyLocatorType.NONE) { if (keyLocator.getType() == net.named_data.jndn.KeyLocatorType.KEYNAME) encodeName(keyLocator.getKeyName(), new int[1], new int[1], encoder); else if (keyLocator.getType() == net.named_data.jndn.KeyLocatorType.KEY_LOCATOR_DIGEST && keyLocator.getKeyData().size() > 0) encoder.writeBlobTlv(net.named_data.jndn.encoding.tlv.Tlv.KeyLocatorDigest, keyLocator .getKeyData().buf()); else throw new Exception("Unrecognized KeyLocatorType " + keyLocator.getType()); } encoder.writeTypeAndLength(type, encoder.getLength() - saveLength); }