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> 9 10 #include "mojo/public/cpp/bindings/lib/array_internal.h" 11 #include "mojo/public/cpp/bindings/lib/string_serialization.h" 12 13 namespace mojo { 14 15 template <typename E> 16 inline size_t GetSerializedSize_(const Array<E>& input); 17 18 template <typename E, typename F> 19 inline void Serialize_(Array<E> input, internal::Buffer* buf, 20 internal::Array_Data<F>** output); 21 template <typename E, typename F> 22 inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output); 23 24 namespace internal { 25 26 template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value> 27 struct ArraySerializer; 28 29 template <typename E, typename F> struct ArraySerializer<E, F, false> { 30 MOJO_COMPILE_ASSERT(sizeof(E) == sizeof(F), wrong_array_serializer); 31 static size_t GetSerializedSize(const Array<E>& input) { 32 return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E)); 33 } 34 static void SerializeElements( 35 Array<E> input, Buffer* buf, Array_Data<F>* output) { 36 memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E)); 37 } 38 static void DeserializeElements( 39 Array_Data<F>* input, Array<E>* output) { 40 std::vector<E> result(input->size()); 41 memcpy(&result[0], input->storage(), input->size() * sizeof(E)); 42 output->Swap(&result); 43 } 44 }; 45 46 template <> struct ArraySerializer<bool, bool, false> { 47 static size_t GetSerializedSize(const Array<bool>& input) { 48 return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8); 49 } 50 static void SerializeElements( 51 Array<bool> input, Buffer* buf, Array_Data<bool>* output) { 52 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? 53 for (size_t i = 0; i < input.size(); ++i) 54 output->at(i) = input[i]; 55 } 56 static void DeserializeElements( 57 Array_Data<bool>* input, Array<bool>* output) { 58 Array<bool> result(input->size()); 59 // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy? 60 for (size_t i = 0; i < input->size(); ++i) 61 result.at(i) = input->at(i); 62 output->Swap(&result); 63 } 64 }; 65 66 template <typename H> struct ArraySerializer<ScopedHandleBase<H>, H, true> { 67 static size_t GetSerializedSize(const Array<ScopedHandleBase<H> >& input) { 68 return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H)); 69 } 70 static void SerializeElements( 71 Array<ScopedHandleBase<H> > input, 72 Buffer* buf, 73 Array_Data<H>* output) { 74 for (size_t i = 0; i < input.size(); ++i) 75 output->at(i) = input[i].release(); // Transfer ownership of the handle. 76 } 77 static void DeserializeElements( 78 Array_Data<H>* input, Array<ScopedHandleBase<H> >* output) { 79 Array<ScopedHandleBase<H> > result(input->size()); 80 for (size_t i = 0; i < input->size(); ++i) 81 result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i))); 82 output->Swap(&result); 83 } 84 }; 85 86 template <typename S> struct ArraySerializer<S, typename S::Data_*, true> { 87 static size_t GetSerializedSize(const Array<S>& input) { 88 size_t size = sizeof(Array_Data<typename S::Data_*>) + 89 input.size() * sizeof(internal::StructPointer<typename S::Data_>); 90 for (size_t i = 0; i < input.size(); ++i) 91 size += GetSerializedSize_(input[i]); 92 return size; 93 } 94 static void SerializeElements( 95 Array<S> input, 96 Buffer* buf, 97 Array_Data<typename S::Data_*>* output) { 98 for (size_t i = 0; i < input.size(); ++i) { 99 typename S::Data_* element; 100 Serialize_(input[i].Pass(), buf, &element); 101 output->at(i) = element; 102 } 103 } 104 static void DeserializeElements( 105 Array_Data<typename S::Data_*>* input, Array<S>* output) { 106 Array<S> result(input->size()); 107 for (size_t i = 0; i < input->size(); ++i) { 108 S element; 109 Deserialize_(input->at(i), &element); 110 result[i] = element.Pass(); 111 } 112 output->Swap(&result); 113 } 114 }; 115 116 template <> struct ArraySerializer<String, String_Data*, false> { 117 static size_t GetSerializedSize(const Array<String>& input) { 118 size_t size = sizeof(Array_Data<String_Data*>) + 119 input.size() * sizeof(internal::StringPointer); 120 for (size_t i = 0; i < input.size(); ++i) 121 size += GetSerializedSize_(input[i]); 122 return size; 123 } 124 static void SerializeElements( 125 Array<String> input, 126 Buffer* buf, 127 Array_Data<String_Data*>* output) { 128 for (size_t i = 0; i < input.size(); ++i) { 129 String_Data* element; 130 Serialize_(input[i], buf, &element); 131 output->at(i) = element; 132 } 133 } 134 static void DeserializeElements( 135 Array_Data<String_Data*>* input, Array<String>* output) { 136 Array<String> result(input->size()); 137 for (size_t i = 0; i < input->size(); ++i) 138 Deserialize_(input->at(i), &result[i]); 139 output->Swap(&result); 140 } 141 }; 142 143 } // namespace internal 144 145 template <typename E> 146 inline size_t GetSerializedSize_(const Array<E>& input) { 147 if (!input) 148 return 0; 149 typedef typename internal::WrapperTraits<E>::DataType F; 150 return internal::ArraySerializer<E, F>::GetSerializedSize(input); 151 } 152 153 template <typename E, typename F> 154 inline void Serialize_(Array<E> input, internal::Buffer* buf, 155 internal::Array_Data<F>** output) { 156 if (input) { 157 internal::Array_Data<F>* result = 158 internal::Array_Data<F>::New(input.size(), buf); 159 internal::ArraySerializer<E, F>::SerializeElements( 160 internal::Forward(input), buf, result); 161 *output = result; 162 } else { 163 *output = NULL; 164 } 165 } 166 167 template <typename E, typename F> 168 inline void Deserialize_(internal::Array_Data<F>* input, 169 Array<E>* output) { 170 if (input) { 171 internal::ArraySerializer<E, F>::DeserializeElements(input, output); 172 } else { 173 output->reset(); 174 } 175 } 176 177 } // namespace mojo 178 179 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ 180