| 1 | // |
| 2 | // Serialization.h |
| 3 | // CoreEntitlements |
| 4 | // |
| 5 | // |
| 6 | |
| 7 | #ifndef CORE_ENTITLEMENTS_SERIALIZATION_H |
| 8 | #define CORE_ENTITLEMENTS_SERIALIZATION_H |
| 9 | |
| 10 | #ifndef _CE_INDIRECT |
| 11 | #error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file" |
| 12 | #endif |
| 13 | |
| 14 | #include <CoreEntitlements/Result.h> |
| 15 | #include <CoreEntitlements/Runtime.h> |
| 16 | #include <CoreEntitlements/Entitlements.h> |
| 17 | |
| 18 | __ptrcheck_abi_assume_single(); |
| 19 | |
| 20 | /*! |
| 21 | * @enum CESerializedElementType_t |
| 22 | * These are the primitive types that CoreEntitlements can serialize |
| 23 | * Depending on the underlying representation some of these elements may be "virtual" or zero-sized. |
| 24 | * However, they must still be included. |
| 25 | */ |
| 26 | OS_CLOSED_ENUM(CESerializedElementType, int64_t, |
| 27 | /* A boolean element with a true / false value */ |
| 28 | kCESerializedBool = 1, |
| 29 | /* A string element with a definite length */ |
| 30 | kCESerializedString = 2, |
| 31 | /* A key string element with a definite length */ |
| 32 | kCESerializedKey = 3, |
| 33 | /* An integer element, must be representable as int64_t */ |
| 34 | kCESerializedInteger = 4, |
| 35 | /* Marks the start of an array / ordered sequence */ |
| 36 | kCESerializedArrayBegin = 5, |
| 37 | /* Marks the end of an array / ordered sequence */ |
| 38 | kCESerializedArrayEnd = 6, |
| 39 | /* Marks the start of a dictionary */ |
| 40 | /* The only valid elements contained in a dictionary are tuples (represented as an ordered sequence) */ |
| 41 | /* The first element of the ordered sequence must be kCESerializedString value */ |
| 42 | /* No restrictions are placed on the contents of the second element*/ |
| 43 | kCESerializedDictionaryBegin = 7, |
| 44 | /* Marks the end of a dictionary */ |
| 45 | kCESerializedDictionaryEnd = 8, |
| 46 | /* A data element with a definite length*/ |
| 47 | kCESerializedData = 9, |
| 48 | ); |
| 49 | |
| 50 | /*! |
| 51 | * @typedef CESerializedElement_t |
| 52 | * This structure represents an encodable piece of data, along with its type and length (in bytes). |
| 53 | * For the most part you will not need to use this structure manually, and instead you should use the helpers below |
| 54 | */ |
| 55 | typedef struct CESerializedElement { |
| 56 | CESerializedElementType_t type; |
| 57 | union { |
| 58 | #if !__has_ptrcheck |
| 59 | void* bytes; |
| 60 | #endif |
| 61 | int64_t value; |
| 62 | } data; |
| 63 | size_t length; |
| 64 | bool pair; |
| 65 | } CESerializedElement_t; |
| 66 | |
| 67 | static inline void *CE_HEADER_INDEXABLE CESerializedElementGetData(const CESerializedElement_t *element) { |
| 68 | return __unsafe_forge_bidi_indexable(void *, element->data.value, element->length); |
| 69 | } |
| 70 | |
| 71 | static inline void CESerializedElementSetData(CESerializedElement_t *element, void *__sized_by(length) bytes, size_t length) { |
| 72 | element->data.value = (intptr_t)bytes; |
| 73 | element->length = length; |
| 74 | } |
| 75 | |
| 76 | /*! |
| 77 | * @function CESizeSerialization |
| 78 | * This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made |
| 79 | * for a successful serialization. |
| 80 | * |
| 81 | * @note |
| 82 | * This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed |
| 83 | * |
| 84 | * @returns |
| 85 | * kCENoError if the requiredSize has been successfully populated and contains a valid value |
| 86 | */ |
| 87 | CEError_t CESizeSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check; |
| 88 | |
| 89 | /*! |
| 90 | * @function CESizeXMLSerialization |
| 91 | * This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made |
| 92 | * for a successful serialization to XML. |
| 93 | * |
| 94 | * @note |
| 95 | * This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed |
| 96 | * |
| 97 | * @returns |
| 98 | * kCENoError if the requiredSize has been successfully populated and contains a valid value |
| 99 | */ |
| 100 | CEError_t CESizeXMLSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check; |
| 101 | |
| 102 | /*! |
| 103 | * @function CESerializeWithOptions |
| 104 | * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function. |
| 105 | * |
| 106 | * @param runtime |
| 107 | * The runtime to use for this operation |
| 108 | * |
| 109 | * @param options |
| 110 | * Options that modify what can be serialized. |
| 111 | * |
| 112 | * @param elements |
| 113 | * The list of elements to serialize |
| 114 | * |
| 115 | * @param elementsCount |
| 116 | * How many elements are in that list |
| 117 | * |
| 118 | * @param start |
| 119 | * A pointer to the first byte into a buffer that will be filled with the serialized representation |
| 120 | * |
| 121 | * @param end |
| 122 | * A pointer 1 byte past the end of the buffer to be used for serialization |
| 123 | */ |
| 124 | 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; |
| 125 | |
| 126 | /*! |
| 127 | * @function CESerialize |
| 128 | * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function. |
| 129 | * |
| 130 | * @param runtime |
| 131 | * The runtime to use for this operation |
| 132 | * |
| 133 | * @param elements |
| 134 | * The list of elements to serialize |
| 135 | * |
| 136 | * @param elementsCount |
| 137 | * How many elements are in that list |
| 138 | * |
| 139 | * @param start |
| 140 | * A pointer to the first byte into a buffer that will be filled with the serialized representation |
| 141 | * |
| 142 | * @param end |
| 143 | * A pointer 1 byte past the end of the buffer to be used for serialization |
| 144 | */ |
| 145 | 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; |
| 146 | |
| 147 | /*! |
| 148 | * @function CESerializeXML |
| 149 | * Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeXMLSerialization before calling this function. |
| 150 | * |
| 151 | * @param runtime |
| 152 | * The runtime to use for this operation |
| 153 | * |
| 154 | * @param elements |
| 155 | * The list of elements to serialize |
| 156 | * |
| 157 | * @param elementsCount |
| 158 | * How many elements are in that list |
| 159 | * |
| 160 | * @param start |
| 161 | * A pointer to the first byte into a buffer that will be filled with the serialized representation |
| 162 | * |
| 163 | * @param end |
| 164 | * A pointer 1 byte past the end of the buffer to be used for serialization |
| 165 | */ |
| 166 | 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; |
| 167 | |
| 168 | // Helpers |
| 169 | // These automatically construct CESerializedElements for you |
| 170 | #define CESerializeInteger(intv) (CESerializedElement_t){.type = kCESerializedInteger, .data.value = intv} |
| 171 | #define CESerializeBool(boolVal) (CESerializedElement_t){.type = kCESerializedBool, .data.value = !!boolVal} |
| 172 | #define CESerializeStaticString(strVal) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1} |
| 173 | #define CESerializeKey(strVal) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1} |
| 174 | #define CESerializeDynamicKey(strVal, len) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = len} |
| 175 | #define CESerializeString(strVal, len) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = len} |
| 176 | #define CESerializeData(dataVal, len) (CESerializedElement_t){.type = kCESerializedData, .data.value = (intptr_t)dataVal, .length = len} |
| 177 | #define CESerializeArray(...) (CESerializedElement_t){.type = kCESerializedArrayBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedArrayEnd} |
| 178 | #define CESerializeDictionary(...) (CESerializedElement_t){.type = kCESerializedDictionaryBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedDictionaryEnd} |
| 179 | #define CESerializeDictionaryPair(a, b) CESerializeArray(a, b) |
| 180 | |
| 181 | #endif |
| 182 | |