aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h')
-rw-r--r--libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h755
1 files changed, 755 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h b/libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h
new file mode 100644
index 00000000..443eeca0
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/ccnxCodec_TlvEncoder.h
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file ccnxCodec_TlvEncoder.h
+ * @ingroup networking
+ * @brief TLV codec for messages
+ *
+ * TLV encoder
+ *
+ * Terminology:
+ * type = a field that labels a value
+ * length = the byte lenth of the value
+ * value = the data
+ * header = type + length
+ * container= a value that contains TLVs
+ *
+ * For example, in this structure, the "type 1" TLV is a container that holds a second TLV
+ * The second TLV is a terminal, and holds an opaque value.
+ *
+ * { .type = 1, .length = 20, .value = { .type = 2, .length = 16, .value ="It was a dark a " } }
+ *
+ * Example to encode a container that wraps a name and an address:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *nameAndAddress = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ *
+ * // Initialize starts a new buffer
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 3, nameAndAddress);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *container = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ *
+ * parcBuffer_Destroy(&nameAndAddress);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ *
+ * // now use the container for something...
+ * }
+ * @endcode
+ *
+ * The TLV will look something like this:
+ * @code
+ * { .type = 3, .length = L1 + L2 + overhead, .value = {
+ * {.type = 1, .length = L1, .value = name},
+ * {.type = 2, .length = L2, .value = address}
+ * }
+ * }
+ * @endcode
+ *
+ * An alternative way to encode it that does not require recursive encoder is to use Position:
+ * @code
+ * {
+ * // Creates {{T=3, L=length, V={{T=1, L=..., V=name}, {T=2, L=..., V=address}}}}
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * size_t offset = ccnxCodecTlvEncoder_Position(encoder);
+ * ccnxCodecTlvEncoder_AppendContainer(encoder, 3, 0);
+ * size_t length = 0;
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 1, name);
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, address);
+ * ccnxCodecTlvEncoder_SetContainerLength(encoder, offset, length);
+ * }
+ * @endcode
+ *
+ */
+
+#ifndef libccnx_ccnx_TlvEncoder_h
+#define libccnx_ccnx_TlvEncoder_h
+
+#include <parc/algol/parc_Buffer.h>
+#include <ccnx/common/codec/ccnxCodec_NetworkBuffer.h>
+#include <parc/security/parc_Signer.h>
+#include <parc/security/parc_Signature.h>
+
+#include <ccnx/common/codec/ccnxCodec_Error.h>
+
+// ======================================================
+
+struct ccnx_codec_tlv_encoder;
+typedef struct ccnx_codec_tlv_encoder CCNxCodecTlvEncoder;
+
+/**
+ * Creates a TLV encoder
+ *
+ * The encoder is re-usable, as the state is reset for each Initialize.
+ *
+ * @return non-null A TLV encoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxCodecTlvEncoder *ccnxCodecTlvEncoder_Create(void);
+
+/**
+ * Destroys the TLV encoder and all internal state
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_Destroy(CCNxCodecTlvEncoder **encoderPtr);
+
+/**
+ * Initialize the encoder to start a new encoding
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] tlv <#description#>
+ *
+ * @return non-null The encoder
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+CCNxCodecTlvEncoder *ccnxCodecTlvEncoder_Initialize(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Appends a TL container and a PARCBuffer to the enoder
+ *
+ * The type is from the parameter `type', the length is from the remaining size
+ * of the value buffer, and the value comes from `value'.
+ *
+ * @param [in] encoder The encoder to append to
+ * @param [in] type The TLV type
+ * @param [in] value The length is the remaining buffer size, the position is advanced.
+ *
+ * @return number The total bytes of the TLV, including the T and L.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendBuffer(CCNxCodecTlvEncoder *encoder, uint16_t type, PARCBuffer *value);
+
+/**
+ * Appends a "TL" container then the bytes of the array
+ *
+ * Writes a Type of 'type' and Length of 'length' then appends 'length' bytes from
+ * the array to the encoder.
+ *
+ * @param [in] encoder An allocated CCnxCodecTlvEncoder
+ * @param [in] type The TLV type
+ * @param [in] length The TLV length
+ * @param [in] array The bytes to append
+ *
+ * @return number The number of bytes appended (including the T and L)
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendArray(CCNxCodecTlvEncoder *encoder, uint16_t type, uint16_t length, const uint8_t *array);
+
+/**
+ * Appends a TL without a V.
+ *
+ * Appends a T and L without a V. Useful for doing a heirarchical encoding where the V
+ * will be more TLVs. You will either need to know L or go back and fix it up.
+ *
+ * @param [in] encoder The encoder to modify
+ * @param [in] type The TLV type
+ * @param [in] length The TLV length, use 0 if you do not know.
+ *
+ * @return bytes The bytes appended (the size of the T and L)
+ *
+ * Example:
+ * @code
+ * {
+ * // Creates {{ T=99, L=.., V=SequenceNumber }, {T=1, L=length, V={{T=2, L=..., V=name}, {T=3, L=..., V=address}}}}
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendBuffer(encoder, 99, sequenceNumber);
+ * size_t offset = ccnxCodecTlvEncoder_Position(encoder);
+ * ccnxCodecTlvEncoder_AppendContainer(encoder, 1, 0);
+ * size_t length = 0;
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, name);
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 3, address);
+ * ccnxCodecTlvEncoder_SetContainerLength(encoder, offset, length);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendContainer(CCNxCodecTlvEncoder *encoder, uint16_t type, uint16_t length);
+
+/**
+ * Adds a TLV with an 8-bit value
+ *
+ * Uses network byte order for the value. The returned size includes
+ * the type and length lengths plus the value length.
+ *
+ * @param [in] encoder The TLV encoder
+ * @param [in] type The Type value to use for the container
+ * @param [in] value The value to encode
+ *
+ * @return number The number of bytes appended to the encoded (5)
+ *
+ * Example:
+ * @code
+ * {
+ * // encoded buffer with be { .type = 1, .length = 1, .value = 0x19 }
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendUint8(encoder, 1, (uint8_t) 25);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendUint8(CCNxCodecTlvEncoder *encoder, uint16_t type, uint8_t value);
+
+/**
+ * Adds a TLV with a 16-bit value
+ *
+ * Uses network byte order for the value. The returned size includes
+ * the type and length lengths plus the value length.
+ *
+ * @param [in] encoder The TLV encoder
+ * @param [in] type The Type value to use for the container
+ * @param [in] value The value to encode
+ *
+ * @return number The number of bytes appended to the encoded (6)
+ *
+ * Example:
+ * @code
+ * {
+ * // encoded buffer with be { .type = 1, .length = 2, .value = 0x1234 }
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendUint16(encoder, 1, (uint16_t) 0x1234);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendUint16(CCNxCodecTlvEncoder *encoder, uint16_t type, uint16_t value);
+
+/**
+ * Adds a TLV with a 32-bit value
+ *
+ * Uses network byte order for the value. The returned size includes
+ * the type and length lengths plus the value length.
+ *
+ * @param [in] encoder The TLV encoder
+ * @param [in] type The Type value to use for the container
+ * @param [in] value The value to encode
+ *
+ * @return number The number of bytes appended to the encoded (8)
+ *
+ * Example:
+ * @code
+ * {
+ * // encoded buffer with be { .type = 1, .length = 4, .value = 0x12345678 }
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendUint32(encoder, 1, (uint32_t) 0x12345678);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendUint32(CCNxCodecTlvEncoder *encoder, uint16_t type, uint32_t value);
+
+
+/**
+ * Adds a TLV with a 64-bit value
+ *
+ * Uses network byte order for the value. The returned size includes
+ * the type and length lengths plus the value length.
+ *
+ * @param [in] encoder The TLV encoder
+ * @param [in] type The Type value to use for the container
+ * @param [in] value The value to encode
+ *
+ * @return number The number of bytes appended to the encoded (8)
+ *
+ * Example:
+ * @code
+ * {
+ * // encoded buffer with be { .type = 1, .length = 8, .value = 0x0000000012345678 }
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendUint64(encoder, 1, (uint64_t) 0x12345678);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendUint64(CCNxCodecTlvEncoder *encoder, uint16_t type, uint64_t value);
+
+/**
+ * Returns the current encoding buffer position
+ *
+ * This is useful if you need to backtrack to fill in a length you did not know before.
+ *
+ * @param [in] encoder The Tlv encoder object
+ *
+ * @return number The byte offset of the encode buffer
+ *
+ * Example:
+ * @code
+ * {
+ * // Creates {{ T=99, L=.., V=SequenceNumber }, {T=1, L=length, V={{T=2, L=..., V=name}, {T=3, L=..., V=address}}}}
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendBuffer(encoder, 99, sequenceNumber);
+ * size_t offset = ccnxCodecTlvEncoder_Position(encoder);
+ * ccnxCodecTlvEncoder_AppendContainer(encoder, 1, 0);
+ * size_t length = 0;
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, name);
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 3, address);
+ * ccnxCodecTlvEncoder_SetContainerLength(encoder, offset, length);
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_Position(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Used to rewind and erase
+ *
+ * For example, you called ccnxCodecTlvEncoder_AppendContainer() then found out that
+ * the container was empty. If you rewind to just before you added the container, it
+ * is as if the container were never added.
+ *
+ * @param [in] position Must be no more than ccnxCodecTlvEncoder_Position()
+ *
+ * @return number The position after calling SetPosition
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_SetPosition(CCNxCodecTlvEncoder *encoder, size_t position);
+
+/**
+ * Sets the length field of the container at the given offset
+ *
+ * User `ccnxCodecTlvEncoder_Position' before `ccnxCodecTlvEncoder_AppendContainer' to get the container's
+ * offset. You can then set that container's length with this function.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ * @param [in] offset position of the container in the Tlv Encoder
+ * @param [in] length The container length to set
+ *
+ * Example:
+ * @code
+ * {
+ * // Creates {{ T=99, L=.., V=SequenceNumber }, {T=1, L=length, V={{T=2, L=..., V=name}, {T=3, L=..., V=address}}}}
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_AppendBuffer(encoder, 99, sequenceNumber);
+ * size_t offset = ccnxCodecTlvEncoder_Position(encoder);
+ * ccnxCodecTlvEncoder_AppendContainer(encoder, 1, 0);
+ * size_t length = 0;
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, name);
+ * length += ccnxCodecTlvEncoder_AppendBuffer(encoder, 3, address);
+ * ccnxCodecTlvEncoder_SetContainerLength(encoder, offset, length);
+ * }
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_SetContainerLength(CCNxCodecTlvEncoder *encoder, size_t offset, uint16_t length);
+
+/**
+ * Finalizes the encoding and returns the encoded buffer
+ *
+ * The buffer is ready for reading. In specific, it will truncate the buffer at the
+ * current position, setting the Limit to that location. This will cut off any
+ * writes to the buffer that have been "erased" by setting the position to an
+ * earlier location.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_Finalize(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Creates a PARCBuffer from position 0 to the Limit.
+ *
+ * Returns a PARCBuffer from position 0 to the Limit. If the user has called
+ * ccnxCodecTlvEncoder_SetPosition() to rewind the buffer, the user should likely call
+ * ccnxCodecTlvEncoder_Finalize() to trim the Limit, otherwise there may be unexpected
+ * bytes at the end.
+ *
+ * The PARCBuffer representation is not the native form of the buffer and will result
+ * in a deep copy of the buffer.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return non-null An allocated PARCBuffer, use parcBuffer_Release() on it
+ * @return null An error.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxCodecTlvEncoder_CreateBuffer(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Creates a vectored I/O representation of the encoder
+ *
+ * Returns a CCNxCodecNetworkBufferIoVec from position 0 to the Limit. If the user has called
+ * ccnxCodecTlvEncoder_SetPosition() to rewind the buffer, the user should likely call
+ * ccnxCodecTlvEncoder_Finalize() to trim the Limit, otherwise there may be unexpected
+ * bytes at the end.
+ *
+ * The CCNxCodecNetworkBufferIoVec is the native form of the memory and does not involve any copies.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return non-null An allocated CCNxCodecNetworkBufferIoVec, use CCNxCodecNetworkBufferIoVec_Release() on it
+ * @return null An error.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Initialize(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_Finalize(encoder);
+ * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvEncoder_CreateIoVec(encoder);
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+CCNxCodecNetworkBufferIoVec *ccnxCodecTlvEncoder_CreateIoVec(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Marks the current position as the start of the signature
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+ *
+ * // The signature is calcualted over the TLV field of the "address"
+ * PARCSignature *sig = ccnxCodecTlvEncoder_ComputeSignature(encoder, signer);
+ *
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_MarkSignatureStart(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Marks the current position as the end (non-inclusive) of the Signature
+ * Example:
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+ *
+ * // The signature is calcualted over the TLV field of the "address"
+ * PARCSignature *sig = ccnxCodecTlvEncoder_ComputeSignature(encoder, signer);
+ *
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_MarkSignatureEnd(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Computes the cryptographic signature over the designated area.
+ * If both a Start and End have not been set, function will assert
+ *
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @retval non-null An allocated PARCSignature
+ * @retval null An error
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ * ccnxCodecTlvEncoder_Append(encoder, 1, name);
+ * ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ * ccnxCodecTlvEncoder_Append(encoder, 2, address);
+ * ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+ *
+ * // The signature is calcualted over the TLV field of the "address"
+ * ccnxCodecTlvEncoder_SetSigner(signer);
+ * PARCSignature *sig = ccnxCodecTlvEncoder_ComputeSignature(encoder);
+ *
+ * ccnxCodecTlvEncoder_Destroy(&encoder);
+ * }
+ * @endcode
+ */
+PARCSignature *ccnxCodecTlvEncoder_ComputeSignature(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Puts a uint8_t at the specified position.
+ *
+ * Does not modify the current position of the Tlv Encoder
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return number The number of bytes put
+ *
+ * Example:
+ * @code
+ * {
+ * <#example#>
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_PutUint8(CCNxCodecTlvEncoder *encoder, size_t offset, uint8_t value);
+
+/**
+ * Puts a uint16_t at the specified position.
+ *
+ * Does not modify the current position of the Tlv Encoder
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return number The number of bytes put
+ *
+ * Example:
+ * @code
+ * {
+ * <#example#>
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_PutUint16(CCNxCodecTlvEncoder *encoder, size_t offset, uint16_t value);
+
+/**
+ * Writes an array to the current position. No "TL" container is written.
+ *
+ * Unlike ccnxCodecTlvEncoder_AppendArray, this does not append a Type and Length container for the array.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ * @param [in] length The number of bytes from array to write
+ * @param [in] array The source array
+ *
+ * @return number The number of bytes appended to the encoder
+ *
+ * Example:
+ * @code
+ * {
+ * <#example#>
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendRawArray(CCNxCodecTlvEncoder *encoder, size_t length, uint8_t *array);
+
+
+/**
+ * Determines if the TLV Encoder has an error condition set
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @retval true An error condition is set
+ * @retval false No error condition is set
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecTlvEncoder_HasError(const CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Sets an error condition. Only one error condition may be set.
+ *
+ * Stores a reference counted copy of the CCNxCodecError. If an error is already set,
+ * this function returns false and does not store a reference to the error. The previous error
+ * stays as the current error.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return true Error condition set
+ * @return false Error already set, you must clear it first
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecTlvEncoder_SetError(CCNxCodecTlvEncoder *encoder, CCNxCodecError *error);
+
+/**
+ * Clears the error condition, if any
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_ClearError(CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Retrieves the error message
+ *
+ * Retrieves the error condition, if any. If no error is set, will return NULL.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return non-null The error condition set
+ * @return null No error condition is set
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxCodecError *ccnxCodecTlvEncoder_GetError(const CCNxCodecTlvEncoder *encoder);
+
+
+/**
+ * Associates a signer with the encoder for producing signatures or MACs
+ *
+ * Stores a reference counted copy of the signer. The reference will be released with the
+ * CCNxCodecTlvEncoder is released or if this function is called multiple times.
+ *
+ * It is allowed to set a NULL singer.
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ * @param [in] singer Assocaited a PARCSigner with the encoder, storing a reference to it
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void ccnxCodecTlvEncoder_SetSigner(CCNxCodecTlvEncoder *encoder, PARCSigner *signer);
+
+/**
+ * Returns the PARCSigner associated with the encoder, if any
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] encoder An allocated CCNxCodecTlvEncoder
+ *
+ * @return non-null The signer assocated with the encoder
+ * @return null There is no singer associated with the encoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+PARCSigner *ccnxCodecTlvEncoder_GetSigner(const CCNxCodecTlvEncoder *encoder);
+
+/**
+ * Appends a TLV container holding the value as a VarInt
+ *
+ * A VarInt may be 1 to 8 bytes long. It is interpreted as an unsigned
+ * integer in network byte order. The value of "0" is encoded as a single
+ * byte of "0".
+ *
+ * @param [in] decoder The TLV decoder
+ * @param [in] type The Type value to use for the container
+ * @param [in] value The value of the varint
+ *
+ * @return number The number of bytes appended
+ *
+ * Example:
+ * @code
+ * {
+ * uint64_t value = 0x0000000000102300
+ * size_t length = ccnxCodecTlvEncoder_AppendVarInt(encoder, 12, value);
+ * // length = 7
+ * // appedned { 0x00, 0x0C, 0x00, 0x03, 0x10, 0x23, 0x00 }
+ * }
+ * @endcode
+ */
+size_t ccnxCodecTlvEncoder_AppendVarInt(CCNxCodecTlvEncoder *encoder, uint16_t type, uint64_t value);
+
+#endif // libccnx_ccnx_TlvEncoder_h