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_MAP_SERIALIZATION_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ 7 8 #include <type_traits> 9 #include <vector> 10 11 #include "mojo/public/cpp/bindings/array_data_view.h" 12 #include "mojo/public/cpp/bindings/lib/array_serialization.h" 13 #include "mojo/public/cpp/bindings/lib/map_data_internal.h" 14 #include "mojo/public/cpp/bindings/lib/serialization_forward.h" 15 #include "mojo/public/cpp/bindings/map_data_view.h" 16 17 namespace mojo { 18 namespace internal { 19 20 template <typename MaybeConstUserType> 21 class MapReaderBase { 22 public: 23 using UserType = typename std::remove_const<MaybeConstUserType>::type; 24 using Traits = MapTraits<UserType>; 25 using MaybeConstIterator = 26 decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>())); 27 MapReaderBase(MaybeConstUserType & input)28 explicit MapReaderBase(MaybeConstUserType& input) 29 : input_(input), iter_(Traits::GetBegin(input_)) {} ~MapReaderBase()30 ~MapReaderBase() {} 31 GetSize()32 size_t GetSize() const { return Traits::GetSize(input_); } 33 34 // Return null because key or value elements are not stored continuously in 35 // memory. GetDataIfExists()36 void* GetDataIfExists() { return nullptr; } 37 38 protected: 39 MaybeConstUserType& input_; 40 MaybeConstIterator iter_; 41 }; 42 43 // Used as the UserTypeReader template parameter of ArraySerializer. 44 template <typename MaybeConstUserType> 45 class MapKeyReader : public MapReaderBase<MaybeConstUserType> { 46 public: 47 using Base = MapReaderBase<MaybeConstUserType>; 48 using Traits = typename Base::Traits; 49 using MaybeConstIterator = typename Base::MaybeConstIterator; 50 MapKeyReader(MaybeConstUserType & input)51 explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} ~MapKeyReader()52 ~MapKeyReader() {} 53 54 using GetNextResult = 55 decltype(Traits::GetKey(std::declval<MaybeConstIterator&>())); GetNext()56 GetNextResult GetNext() { 57 GetNextResult key = Traits::GetKey(this->iter_); 58 Traits::AdvanceIterator(this->iter_); 59 return key; 60 } 61 }; 62 63 // Used as the UserTypeReader template parameter of ArraySerializer. 64 template <typename MaybeConstUserType> 65 class MapValueReader : public MapReaderBase<MaybeConstUserType> { 66 public: 67 using Base = MapReaderBase<MaybeConstUserType>; 68 using Traits = typename Base::Traits; 69 using MaybeConstIterator = typename Base::MaybeConstIterator; 70 MapValueReader(MaybeConstUserType & input)71 explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} ~MapValueReader()72 ~MapValueReader() {} 73 74 using GetNextResult = 75 decltype(Traits::GetValue(std::declval<MaybeConstIterator&>())); GetNext()76 GetNextResult GetNext() { 77 GetNextResult value = Traits::GetValue(this->iter_); 78 Traits::AdvanceIterator(this->iter_); 79 return value; 80 } 81 }; 82 83 template <typename Key, typename Value, typename MaybeConstUserType> 84 struct Serializer<MapDataView<Key, Value>, MaybeConstUserType> { 85 using UserType = typename std::remove_const<MaybeConstUserType>::type; 86 using Traits = MapTraits<UserType>; 87 using UserKey = typename Traits::Key; 88 using UserValue = typename Traits::Value; 89 using Data = typename MojomTypeTraits<MapDataView<Key, Value>>::Data; 90 using KeyArraySerializer = ArraySerializer<ArrayDataView<Key>, 91 std::vector<UserKey>, 92 MapKeyReader<MaybeConstUserType>>; 93 using ValueArraySerializer = 94 ArraySerializer<ArrayDataView<Value>, 95 std::vector<UserValue>, 96 MapValueReader<MaybeConstUserType>>; 97 98 static size_t PrepareToSerialize(MaybeConstUserType& input, 99 SerializationContext* context) { 100 if (CallIsNullIfExists<Traits>(input)) 101 return 0; 102 103 size_t struct_overhead = sizeof(Data); 104 MapKeyReader<MaybeConstUserType> key_reader(input); 105 size_t keys_size = 106 KeyArraySerializer::GetSerializedSize(&key_reader, context); 107 MapValueReader<MaybeConstUserType> value_reader(input); 108 size_t values_size = 109 ValueArraySerializer::GetSerializedSize(&value_reader, context); 110 111 return struct_overhead + keys_size + values_size; 112 } 113 114 static void Serialize(MaybeConstUserType& input, 115 Buffer* buf, 116 Data** output, 117 const ContainerValidateParams* validate_params, 118 SerializationContext* context) { 119 DCHECK(validate_params->key_validate_params); 120 DCHECK(validate_params->element_validate_params); 121 if (CallIsNullIfExists<Traits>(input)) { 122 *output = nullptr; 123 return; 124 } 125 126 auto result = Data::New(buf); 127 if (result) { 128 auto keys_ptr = MojomTypeTraits<ArrayDataView<Key>>::Data::New( 129 Traits::GetSize(input), buf); 130 if (keys_ptr) { 131 MapKeyReader<MaybeConstUserType> key_reader(input); 132 KeyArraySerializer::SerializeElements( 133 &key_reader, buf, keys_ptr, validate_params->key_validate_params, 134 context); 135 result->keys.Set(keys_ptr); 136 } 137 138 auto values_ptr = MojomTypeTraits<ArrayDataView<Value>>::Data::New( 139 Traits::GetSize(input), buf); 140 if (values_ptr) { 141 MapValueReader<MaybeConstUserType> value_reader(input); 142 ValueArraySerializer::SerializeElements( 143 &value_reader, buf, values_ptr, 144 validate_params->element_validate_params, context); 145 result->values.Set(values_ptr); 146 } 147 } 148 *output = result; 149 } 150 151 static bool Deserialize(Data* input, 152 UserType* output, 153 SerializationContext* context) { 154 if (!input) 155 return CallSetToNullIfExists<Traits>(output); 156 157 std::vector<UserKey> keys; 158 std::vector<UserValue> values; 159 160 if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys, 161 context) || 162 !ValueArraySerializer::DeserializeElements(input->values.Get(), &values, 163 context)) { 164 return false; 165 } 166 167 DCHECK_EQ(keys.size(), values.size()); 168 size_t size = keys.size(); 169 Traits::SetToEmpty(output); 170 171 for (size_t i = 0; i < size; ++i) { 172 if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i]))) 173 return false; 174 } 175 return true; 176 } 177 }; 178 179 } // namespace internal 180 } // namespace mojo 181 182 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ 183