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/string_serialization.h" 15 #include "mojo/public/cpp/bindings/lib/template_util.h" 16 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 17 18 namespace mojo { 19 20 template <typename E> 21 inline size_t GetSerializedSize_(const Array<E>& input); 22 23 // Because ValidateParams requires explicit argument specification, the 24 // argument-dependent loopup technique used to omit namespace when calling 25 // Serialize_() doesn't seem to work. Therefore, this function is named 26 // differently from those Serialize_() overloads. 27 template <typename ValidateParams, typename E, typename F> 28 inline void SerializeArray_(Array<E> input, internal::Buffer* buf, 29 internal::Array_Data<F>** output); 30 31 template <typename E, typename F> 32 inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); 33 34 namespace internal { 35 36 template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value> 37 struct ArraySerializer; 38 39 template <typename E, typename F> struct ArraySerializer<E, F, false> { 40 MOJO_COMPILE_ASSERT(sizeof(E) == sizeof(F), wrong_array_serializer); 41 static size_t GetSerializedSize(const Array<E>& input) { 42 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); 43 } 44 template <bool element_is_nullable, typename ElementValidateParams> 45 static void SerializeElements( 46 Array<E> input, Buffer* buf, Array_Data<F>* output) { 47 MOJO_COMPILE_ASSERT(!element_is_nullable, 48 Primitive_type_should_be_non_nullable); 49 MOJO_COMPILE_ASSERT( 50 (IsSame<ElementValidateParams, NoValidateParams>::value), 51 Primitive_type_should_not_have_array_validate_params); 52 53 memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); 54 } 55 static void DeserializeElements( 56 Array_Data<F>* input, Array<E>* output) { 57 std::vector<E> result(input->size()); 58 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); 59 output->Swap(&result); 60 } 61 }; 62 63 template <> struct ArraySerializer<bool, bool, false> { 64 static size_t GetSerializedSize(const Array<bool>& input) { 65 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); 66 } 67 template <bool element_is_nullable, typename ElementValidateParams> 68 static void SerializeElements( 69 Array<bool> input, Buffer* buf, Array_Data<bool>* output) { 70 MOJO_COMPILE_ASSERT(!element_is_nullable, 71 Primitive_type_should_be_non_nullable); 72 MOJO_COMPILE_ASSERT( 73 (IsSame<ElementValidateParams, NoValidateParams>::value), 74 Primitive_type_should_not_have_array_validate_params); 75 76 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? 77 for (size_t i = 0; i < input.size(); ++i) 78 output->at(i) = input[i]; 79 } 80 static void DeserializeElements( 81 Array_Data<bool>* input, Array<bool>* output) { 82 Array<bool> result(input->size()); 83 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? 84 for (size_t i = 0; i < input->size(); ++i) 85 result.at(i) = input->at(i); 86 output->Swap(&result); 87 } 88 }; 89 90 template <typename H> struct ArraySerializer<ScopedHandleBase<H>, H, true> { 91 static size_t GetSerializedSize(const Array<ScopedHandleBase<H> >& input) { 92 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); 93 } 94 template <bool element_is_nullable, typename ElementValidateParams> 95 static void SerializeElements(Array<ScopedHandleBase<H> > input, 96 Buffer* buf, 97 Array_Data<H>* output) { 98 MOJO_COMPILE_ASSERT( 99 (IsSame<ElementValidateParams, NoValidateParams>::value), 100 Handle_type_should_not_have_array_validate_params); 101 102 for (size_t i = 0; i < input.size(); ++i) { 103 output->at(i) = input[i].release(); // Transfer ownership of the handle. 104 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( 105 !element_is_nullable && !output->at(i).is_valid(), 106 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 107 MakeMessageWithArrayIndex( 108 "invalid handle in array expecting valid handles", 109 input.size(), i)); 110 } 111 } 112 static void DeserializeElements( 113 Array_Data<H>* input, Array<ScopedHandleBase<H> >* output) { 114 Array<ScopedHandleBase<H> > result(input->size()); 115 for (size_t i = 0; i < input->size(); ++i) 116 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); 117 output->Swap(&result); 118 } 119 }; 120 121 template <typename S> struct ArraySerializer<S, typename S::Data_*, true> { 122 static size_t GetSerializedSize(const Array<S>& input) { 123 size_t size = sizeof(Array_Data<typename S::Data_*>) + 124 input.size() * sizeof(internal::StructPointer<typename S::Data_>); 125 for (size_t i = 0; i < input.size(); ++i) 126 size += GetSerializedSize_(input[i]); 127 return size; 128 } 129 template <bool element_is_nullable, typename ElementValidateParams> 130 static void SerializeElements(Array<S> input, 131 Buffer* buf, 132 Array_Data<typename S::Data_*>* output) { 133 for (size_t i = 0; i < input.size(); ++i) { 134 typename S::Data_* element; 135 SerializeCaller<S, ElementValidateParams>::Run( 136 input[i].Pass(), buf, &element); 137 output->at(i) = element; 138 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( 139 !element_is_nullable && !element, 140 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 141 MakeMessageWithArrayIndex( 142 "null in array expecting valid pointers", input.size(), i)); 143 } 144 } 145 static void DeserializeElements( 146 Array_Data<typename S::Data_*>* input, Array<S>* output) { 147 Array<S> result(input->size()); 148 for (size_t i = 0; i < input->size(); ++i) { 149 S element; 150 Deserialize_(input->at(i), &element); 151 result[i] = element.Pass(); 152 } 153 output->Swap(&result); 154 } 155 156 private: 157 template <typename T, typename Params> 158 struct SerializeCaller { 159 static void Run(T input, Buffer* buf, typename T::Data_** output) { 160 MOJO_COMPILE_ASSERT((IsSame<Params, NoValidateParams>::value), 161 Struct_type_should_not_have_array_validate_params); 162 163 Serialize_(input.Pass(), buf, output); 164 } 165 }; 166 167 template <typename T, typename Params> 168 struct SerializeCaller<Array<T>, Params> { 169 static void Run(Array<T> input, 170 Buffer* buf, 171 typename Array<T>::Data_** output) { 172 SerializeArray_<Params>(input.Pass(), buf, output); 173 } 174 }; 175 }; 176 177 template <> struct ArraySerializer<String, String_Data*, false> { 178 static size_t GetSerializedSize(const Array<String>& input) { 179 size_t size = sizeof(Array_Data<String_Data*>) + 180 input.size() * sizeof(internal::StringPointer); 181 for (size_t i = 0; i < input.size(); ++i) 182 size += GetSerializedSize_(input[i]); 183 return size; 184 } 185 template <bool element_is_nullable, typename ElementValidateParams> 186 static void SerializeElements( 187 Array<String> input, 188 Buffer* buf, 189 Array_Data<String_Data*>* output) { 190 MOJO_COMPILE_ASSERT( 191 (IsSame<ElementValidateParams, 192 ArrayValidateParams<0, false, NoValidateParams> >::value), 193 String_type_has_unexpected_array_validate_params); 194 195 for (size_t i = 0; i < input.size(); ++i) { 196 String_Data* element; 197 Serialize_(input[i], buf, &element); 198 output->at(i) = element; 199 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( 200 !element_is_nullable && !element, 201 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 202 MakeMessageWithArrayIndex( 203 "null in array expecting valid strings", input.size(), i)); 204 } 205 } 206 static void DeserializeElements( 207 Array_Data<String_Data*>* input, Array<String>* output) { 208 Array<String> result(input->size()); 209 for (size_t i = 0; i < input->size(); ++i) 210 Deserialize_(input->at(i), &result[i]); 211 output->Swap(&result); 212 } 213 }; 214 215 } // namespace internal 216 217 template <typename E> 218 inline size_t GetSerializedSize_(const Array<E>& input) { 219 if (!input) 220 return 0; 221 typedef typename internal::WrapperTraits<E>::DataType F; 222 return internal::ArraySerializer<E, F>::GetSerializedSize(input); 223 } 224 225 template <typename ValidateParams, typename E, typename F> 226 inline void SerializeArray_(Array<E> input, internal::Buffer* buf, 227 internal::Array_Data<F>** output) { 228 if (input) { 229 MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( 230 ValidateParams::expected_num_elements != 0 && 231 input.size() != ValidateParams::expected_num_elements, 232 internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, 233 internal::MakeMessageWithExpectedArraySize( 234 "fixed-size array has wrong number of elements", 235 input.size(), ValidateParams::expected_num_elements)); 236 237 internal::Array_Data<F>* result = 238 internal::Array_Data<F>::New(input.size(), buf); 239 if (result) { 240 internal::ArraySerializer<E, F>::template SerializeElements< 241 ValidateParams::element_is_nullable, 242 typename ValidateParams::ElementValidateParams>( 243 internal::Forward(input), buf, result); 244 } 245 *output = result; 246 } else { 247 *output = NULL; 248 } 249 } 250 251 template <typename E, typename F> 252 inline void Deserialize_(internal::Array_Data<F>* input, Array<E>* output) { 253 if (input) { 254 internal::ArraySerializer<E, F>::DeserializeElements(input, output); 255 } else { 256 output->reset(); 257 } 258 } 259 260 } // namespace mojo 261 262 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ 263