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 */
26OS_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 */
55typedef 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
67static inline void *CE_HEADER_INDEXABLE CESerializedElementGetData(const CESerializedElement_t *element) {
68 return __unsafe_forge_bidi_indexable(void *, element->data.value, element->length);
69}
70
71static 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 */
87CEError_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 */
100CEError_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 */
124CEError_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 */
145CEError_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 */
166CEError_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