// // Serialization.h // CoreEntitlements // // #ifndef CORE_ENTITLEMENTS_SERIALIZATION_H #define CORE_ENTITLEMENTS_SERIALIZATION_H #ifndef _CE_INDIRECT #error "Please include instead of this file" #endif #include #include #include __ptrcheck_abi_assume_single(); /*! * @enum CESerializedElementType_t * These are the primitive types that CoreEntitlements can serialize * Depending on the underlying representation some of these elements may be "virtual" or zero-sized. * However, they must still be included. */ OS_CLOSED_ENUM(CESerializedElementType, int64_t, /* A boolean element with a true / false value */ kCESerializedBool = 1, /* A string element with a definite length */ kCESerializedString = 2, /* A key string element with a definite length */ kCESerializedKey = 3, /* An integer element, must be representable as int64_t */ kCESerializedInteger = 4, /* Marks the start of an array / ordered sequence */ kCESerializedArrayBegin = 5, /* Marks the end of an array / ordered sequence */ kCESerializedArrayEnd = 6, /* Marks the start of a dictionary */ /* The only valid elements contained in a dictionary are tuples (represented as an ordered sequence) */ /* The first element of the ordered sequence must be kCESerializedString value */ /* No restrictions are placed on the contents of the second element*/ kCESerializedDictionaryBegin = 7, /* Marks the end of a dictionary */ kCESerializedDictionaryEnd = 8, /* A data element with a definite length*/ kCESerializedData = 9, ); /*! * @typedef CESerializedElement_t * This structure represents an encodable piece of data, along with its type and length (in bytes). * For the most part you will not need to use this structure manually, and instead you should use the helpers below */ typedef struct CESerializedElement { CESerializedElementType_t type; union { #if !__has_ptrcheck void* bytes; #endif int64_t value; } data; size_t length; bool pair; } CESerializedElement_t; static inline void *CE_HEADER_INDEXABLE CESerializedElementGetData(const CESerializedElement_t *element) { return __unsafe_forge_bidi_indexable(void *, element->data.value, element->length); } static inline void CESerializedElementSetData(CESerializedElement_t *element, void *__sized_by(length) bytes, size_t length) { element->data.value = (intptr_t)bytes; element->length = length; } /*! * @function CESizeSerialization * This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made * for a successful serialization. * * @note * This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed * * @returns * kCENoError if the requiredSize has been successfully populated and contains a valid value */ CEError_t CESizeSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check; /*! * @function CESizeXMLSerialization * This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made * for a successful serialization to XML. * * @note * This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed * * @returns * kCENoError if the requiredSize has been successfully populated and contains a valid value */ CEError_t CESizeXMLSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check; /*! * @function CESerializeWithOptions * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function. * * @param runtime * The runtime to use for this operation * * @param options * Options that modify what can be serialized. * * @param elements * The list of elements to serialize * * @param elementsCount * How many elements are in that list * * @param start * A pointer to the first byte into a buffer that will be filled with the serialized representation * * @param end * A pointer 1 byte past the end of the buffer to be used for serialization */ CEError_t CESerializeWithOptions(const CERuntime_t runtime, CEValidationOptions* options, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check; /*! * @function CESerialize * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function. * * @param runtime * The runtime to use for this operation * * @param elements * The list of elements to serialize * * @param elementsCount * How many elements are in that list * * @param start * A pointer to the first byte into a buffer that will be filled with the serialized representation * * @param end * A pointer 1 byte past the end of the buffer to be used for serialization */ CEError_t CESerialize(const CERuntime_t runtime, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check; /*! * @function CESerializeXML * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeXMLSerialization before calling this function. * * @param runtime * The runtime to use for this operation * * @param elements * The list of elements to serialize * * @param elementsCount * How many elements are in that list * * @param start * A pointer to the first byte into a buffer that will be filled with the serialized representation * * @param end * A pointer 1 byte past the end of the buffer to be used for serialization */ CEError_t CESerializeXML(const CERuntime_t runtime, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check; // Helpers // These automatically construct CESerializedElements for you #define CESerializeInteger(intv) (CESerializedElement_t){.type = kCESerializedInteger, .data.value = intv} #define CESerializeBool(boolVal) (CESerializedElement_t){.type = kCESerializedBool, .data.value = !!boolVal} #define CESerializeStaticString(strVal) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1} #define CESerializeKey(strVal) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1} #define CESerializeDynamicKey(strVal, len) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = len} #define CESerializeString(strVal, len) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = len} #define CESerializeData(dataVal, len) (CESerializedElement_t){.type = kCESerializedData, .data.value = (intptr_t)dataVal, .length = len} #define CESerializeArray(...) (CESerializedElement_t){.type = kCESerializedArrayBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedArrayEnd} #define CESerializeDictionary(...) (CESerializedElement_t){.type = kCESerializedDictionaryBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedDictionaryEnd} #define CESerializeDictionaryPair(a, b) CESerializeArray(a, b) #endif