| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
| 7 | |
| 8 #include <string.h> // For |memcpy()|. | |
| 9 | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "mojo/public/c/system/macros.h" | |
| 13 #include "mojo/public/cpp/bindings/lib/array_internal.h" | |
| 14 #include "mojo/public/cpp/bindings/lib/map_serialization.h" | |
| 15 #include "mojo/public/cpp/bindings/lib/string_serialization.h" | |
| 16 #include "mojo/public/cpp/bindings/lib/template_util.h" | |
| 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | |
| 18 | |
| 19 namespace mojo { | |
| 20 | |
| 21 template <typename E> | |
| 22 inline size_t GetSerializedSize_(const Array<E>& input); | |
| 23 | |
| 24 // Because ValidateParams requires explicit argument specification, the | |
| 25 // argument-dependent loopup technique used to omit namespace when calling | |
| 26 // Serialize_() doesn't seem to work. Therefore, this function is named | |
| 27 // differently from those Serialize_() overloads. | |
| 28 template <typename ValidateParams, typename E, typename F> | |
| 29 inline void SerializeArray_(Array<E> input, | |
| 30 internal::Buffer* buf, | |
| 31 internal::Array_Data<F>** output); | |
| 32 | |
| 33 template <typename ValueValidateParams, | |
| 34 typename KeyWrapperType, | |
| 35 typename ValueWrapperType, | |
| 36 typename KeySerializationType, | |
| 37 typename ValueSerializationType> | |
| 38 inline void SerializeMap_( | |
| 39 Map<KeyWrapperType, ValueWrapperType> input, | |
| 40 internal::Buffer* buf, | |
| 41 internal::Map_Data<KeySerializationType, ValueSerializationType>** output); | |
| 42 | |
| 43 template <typename E, typename F> | |
| 44 inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); | |
| 45 | |
| 46 namespace internal { | |
| 47 | |
| 48 template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value> | |
| 49 struct ArraySerializer; | |
| 50 | |
| 51 template <typename E, typename F> | |
| 52 struct ArraySerializer<E, F, false> { | |
| 53 static_assert(sizeof(E) == sizeof(F), "Incorrect array serializer"); | |
| 54 static size_t GetSerializedSize(const Array<E>& input) { | |
| 55 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); | |
| 56 } | |
| 57 template <bool element_is_nullable, typename ElementValidateParams> | |
| 58 static void SerializeElements(Array<E> input, | |
| 59 Buffer* buf, | |
| 60 Array_Data<F>* output) { | |
| 61 static_assert(!element_is_nullable, | |
| 62 "Primitive type should be non-nullable"); | |
| 63 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
| 64 "Primitive type should not have array validate params"); | |
| 65 | |
| 66 if (input.size()) | |
| 67 memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); | |
| 68 } | |
| 69 static void DeserializeElements(Array_Data<F>* input, Array<E>* output) { | |
| 70 std::vector<E> result(input->size()); | |
| 71 if (input->size()) | |
| 72 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); | |
| 73 output->Swap(&result); | |
| 74 } | |
| 75 }; | |
| 76 | |
| 77 template <> | |
| 78 struct ArraySerializer<bool, bool, false> { | |
| 79 static size_t GetSerializedSize(const Array<bool>& input) { | |
| 80 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); | |
| 81 } | |
| 82 template <bool element_is_nullable, typename ElementValidateParams> | |
| 83 static void SerializeElements(Array<bool> input, | |
| 84 Buffer* buf, | |
| 85 Array_Data<bool>* output) { | |
| 86 static_assert(!element_is_nullable, | |
| 87 "Primitive type should be non-nullable"); | |
| 88 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
| 89 "Primitive type should not have array validate params"); | |
| 90 | |
| 91 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | |
| 92 for (size_t i = 0; i < input.size(); ++i) | |
| 93 output->at(i) = input[i]; | |
| 94 } | |
| 95 static void DeserializeElements(Array_Data<bool>* input, | |
| 96 Array<bool>* output) { | |
| 97 Array<bool> result(input->size()); | |
| 98 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? | |
| 99 for (size_t i = 0; i < input->size(); ++i) | |
| 100 result.at(i) = input->at(i); | |
| 101 output->Swap(&result); | |
| 102 } | |
| 103 }; | |
| 104 | |
| 105 template <typename H> | |
| 106 struct ArraySerializer<ScopedHandleBase<H>, H, true> { | |
| 107 static size_t GetSerializedSize(const Array<ScopedHandleBase<H>>& input) { | |
| 108 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); | |
| 109 } | |
| 110 template <bool element_is_nullable, typename ElementValidateParams> | |
| 111 static void SerializeElements(Array<ScopedHandleBase<H>> input, | |
| 112 Buffer* buf, | |
| 113 Array_Data<H>* output) { | |
| 114 static_assert((IsSame<ElementValidateParams, NoValidateParams>::value), | |
| 115 "Handle type should not have array validate params"); | |
| 116 | |
| 117 for (size_t i = 0; i < input.size(); ++i) { | |
| 118 output->at(i) = input[i].release(); // Transfer ownership of the handle. | |
| 119 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
| 120 !element_is_nullable && !output->at(i).is_valid(), | |
| 121 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, | |
| 122 MakeMessageWithArrayIndex( | |
| 123 "invalid handle in array expecting valid handles", | |
| 124 input.size(), | |
| 125 i)); | |
| 126 } | |
| 127 } | |
| 128 static void DeserializeElements(Array_Data<H>* input, | |
| 129 Array<ScopedHandleBase<H>>* output) { | |
| 130 Array<ScopedHandleBase<H>> result(input->size()); | |
| 131 for (size_t i = 0; i < input->size(); ++i) | |
| 132 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); | |
| 133 output->Swap(&result); | |
| 134 } | |
| 135 }; | |
| 136 | |
| 137 // This template must only apply to pointer mojo entity (structs and arrays). | |
| 138 // This is done by ensuring that WrapperTraits<S>::DataType is a pointer. | |
| 139 template <typename S> | |
| 140 struct ArraySerializer<S, | |
| 141 typename internal::EnableIf< | |
| 142 internal::IsPointer<typename internal::WrapperTraits< | |
| 143 S>::DataType>::value, | |
| 144 typename internal::WrapperTraits<S>::DataType>::type, | |
| 145 true> { | |
| 146 typedef typename internal::RemovePointer< | |
| 147 typename internal::WrapperTraits<S>::DataType>::type S_Data; | |
| 148 static size_t GetSerializedSize(const Array<S>& input) { | |
| 149 size_t size = sizeof(Array_Data<S_Data*>) + | |
| 150 input.size() * sizeof(internal::StructPointer<S_Data>); | |
| 151 for (size_t i = 0; i < input.size(); ++i) | |
| 152 size += GetSerializedSize_(input[i]); | |
| 153 return size; | |
| 154 } | |
| 155 template <bool element_is_nullable, typename ElementValidateParams> | |
| 156 static void SerializeElements(Array<S> input, | |
| 157 Buffer* buf, | |
| 158 Array_Data<S_Data*>* output) { | |
| 159 for (size_t i = 0; i < input.size(); ++i) { | |
| 160 S_Data* element; | |
| 161 SerializeCaller<S, ElementValidateParams>::Run( | |
| 162 input[i].Pass(), buf, &element); | |
| 163 output->at(i) = element; | |
| 164 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
| 165 !element_is_nullable && !element, | |
| 166 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | |
| 167 MakeMessageWithArrayIndex( | |
| 168 "null in array expecting valid pointers", input.size(), i)); | |
| 169 } | |
| 170 } | |
| 171 static void DeserializeElements(Array_Data<S_Data*>* input, | |
| 172 Array<S>* output) { | |
| 173 Array<S> result(input->size()); | |
| 174 for (size_t i = 0; i < input->size(); ++i) { | |
| 175 S element; | |
| 176 Deserialize_(input->at(i), &element); | |
| 177 result[i] = element.Pass(); | |
| 178 } | |
| 179 output->Swap(&result); | |
| 180 } | |
| 181 | |
| 182 private: | |
| 183 template <typename T, typename Params> | |
| 184 struct SerializeCaller { | |
| 185 static void Run(T input, | |
| 186 Buffer* buf, | |
| 187 typename internal::WrapperTraits<T>::DataType* output) { | |
| 188 static_assert((IsSame<Params, NoValidateParams>::value), | |
| 189 "Struct type should not have array validate params"); | |
| 190 | |
| 191 Serialize_(input.Pass(), buf, output); | |
| 192 } | |
| 193 }; | |
| 194 | |
| 195 template <typename T, typename Params> | |
| 196 struct SerializeCaller<Array<T>, Params> { | |
| 197 static void Run(Array<T> input, | |
| 198 Buffer* buf, | |
| 199 typename Array<T>::Data_** output) { | |
| 200 SerializeArray_<Params>(input.Pass(), buf, output); | |
| 201 } | |
| 202 }; | |
| 203 | |
| 204 template <typename T, typename U, typename Params> | |
| 205 struct SerializeCaller<Map<T, U>, Params> { | |
| 206 static void Run(Map<T, U> input, | |
| 207 Buffer* buf, | |
| 208 typename Map<T, U>::Data_** output) { | |
| 209 SerializeMap_<Params>(input.Pass(), buf, output); | |
| 210 } | |
| 211 }; | |
| 212 }; | |
| 213 | |
| 214 template <> | |
| 215 struct ArraySerializer<String, String_Data*, false> { | |
| 216 static size_t GetSerializedSize(const Array<String>& input) { | |
| 217 size_t size = sizeof(Array_Data<String_Data*>) + | |
| 218 input.size() * sizeof(internal::StringPointer); | |
| 219 for (size_t i = 0; i < input.size(); ++i) | |
| 220 size += GetSerializedSize_(input[i]); | |
| 221 return size; | |
| 222 } | |
| 223 template <bool element_is_nullable, typename ElementValidateParams> | |
| 224 static void SerializeElements(Array<String> input, | |
| 225 Buffer* buf, | |
| 226 Array_Data<String_Data*>* output) { | |
| 227 static_assert( | |
| 228 (IsSame<ElementValidateParams, | |
| 229 ArrayValidateParams<0, false, NoValidateParams>>::value), | |
| 230 "String type has unexpected array validate params"); | |
| 231 | |
| 232 for (size_t i = 0; i < input.size(); ++i) { | |
| 233 String_Data* element; | |
| 234 Serialize_(input[i], buf, &element); | |
| 235 output->at(i) = element; | |
| 236 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
| 237 !element_is_nullable && !element, | |
| 238 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, | |
| 239 MakeMessageWithArrayIndex( | |
| 240 "null in array expecting valid strings", input.size(), i)); | |
| 241 } | |
| 242 } | |
| 243 static void DeserializeElements(Array_Data<String_Data*>* input, | |
| 244 Array<String>* output) { | |
| 245 Array<String> result(input->size()); | |
| 246 for (size_t i = 0; i < input->size(); ++i) | |
| 247 Deserialize_(input->at(i), &result[i]); | |
| 248 output->Swap(&result); | |
| 249 } | |
| 250 }; | |
| 251 | |
| 252 } // namespace internal | |
| 253 | |
| 254 template <typename E> | |
| 255 inline size_t GetSerializedSize_(const Array<E>& input) { | |
| 256 if (!input) | |
| 257 return 0; | |
| 258 typedef typename internal::WrapperTraits<E>::DataType F; | |
| 259 return internal::ArraySerializer<E, F>::GetSerializedSize(input); | |
| 260 } | |
| 261 | |
| 262 template <typename ValidateParams, typename E, typename F> | |
| 263 inline void SerializeArray_(Array<E> input, | |
| 264 internal::Buffer* buf, | |
| 265 internal::Array_Data<F>** output) { | |
| 266 if (input) { | |
| 267 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( | |
| 268 ValidateParams::expected_num_elements != 0 && | |
| 269 input.size() != ValidateParams::expected_num_elements, | |
| 270 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, | |
| 271 internal::MakeMessageWithExpectedArraySize( | |
| 272 "fixed-size array has wrong number of elements", | |
| 273 input.size(), | |
| 274 ValidateParams::expected_num_elements)); | |
| 275 | |
| 276 internal::Array_Data<F>* result = | |
| 277 internal::Array_Data<F>::New(input.size(), buf); | |
| 278 if (result) { | |
| 279 internal::ArraySerializer<E, F>::template SerializeElements< | |
| 280 ValidateParams::element_is_nullable, | |
| 281 typename ValidateParams::ElementValidateParams>( | |
| 282 internal::Forward(input), buf, result); | |
| 283 } | |
| 284 *output = result; | |
| 285 } else { | |
| 286 *output = nullptr; | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 template <typename E, typename F> | |
| 291 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) { | |
| 292 if (input) { | |
| 293 internal::ArraySerializer<E, F>::DeserializeElements(input, output); | |
| 294 } else { | |
| 295 output->reset(); | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 } // namespace mojo | |
| 300 | |
| 301 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ | |
| OLD | NEW |