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.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.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 MapKeyReader(MaybeConstUserType & input)50 explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} ~MapKeyReader()51 ~MapKeyReader() {} 52 GetNext()53 const typename Traits::Key& GetNext() { 54 const typename Traits::Key& key = Traits::GetKey(this->iter_); 55 Traits::AdvanceIterator(this->iter_); 56 return key; 57 } 58 }; 59 60 // Used as the UserTypeReader template parameter of ArraySerializer. 61 template <typename MaybeConstUserType> 62 class MapValueReader : public MapReaderBase<MaybeConstUserType> { 63 public: 64 using Base = MapReaderBase<MaybeConstUserType>; 65 using Traits = typename Base::Traits; 66 using MaybeConstIterator = typename Base::MaybeConstIterator; 67 MapValueReader(MaybeConstUserType & input)68 explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} ~MapValueReader()69 ~MapValueReader() {} 70 71 using GetNextResult = 72 decltype(Traits::GetValue(std::declval<MaybeConstIterator&>())); GetNext()73 GetNextResult GetNext() { 74 GetNextResult value = Traits::GetValue(this->iter_); 75 Traits::AdvanceIterator(this->iter_); 76 return value; 77 } 78 }; 79 80 template <typename Key, typename Value, typename MaybeConstUserType> 81 struct Serializer<Map<Key, Value>, MaybeConstUserType> { 82 using UserType = typename std::remove_const<MaybeConstUserType>::type; 83 using Traits = MapTraits<UserType>; 84 using UserKey = typename Traits::Key; 85 using UserValue = typename Traits::Value; 86 using Data = typename MojomTypeTraits<Map<Key, Value>>::Data; 87 using KeyArraySerializer = ArraySerializer<Array<Key>, 88 std::vector<UserKey>, 89 MapKeyReader<MaybeConstUserType>>; 90 using ValueArraySerializer = 91 ArraySerializer<Array<Value>, 92 std::vector<UserValue>, 93 MapValueReader<MaybeConstUserType>>; 94 95 static size_t PrepareToSerialize(MaybeConstUserType& input, 96 SerializationContext* context) { 97 if (CallIsNullIfExists<Traits>(input)) 98 return 0; 99 100 size_t struct_overhead = sizeof(Data); 101 MapKeyReader<MaybeConstUserType> key_reader(input); 102 size_t keys_size = 103 KeyArraySerializer::GetSerializedSize(&key_reader, context); 104 MapValueReader<MaybeConstUserType> value_reader(input); 105 size_t values_size = 106 ValueArraySerializer::GetSerializedSize(&value_reader, context); 107 108 return struct_overhead + keys_size + values_size; 109 } 110 111 static void Serialize(MaybeConstUserType& input, 112 Buffer* buf, 113 Data** output, 114 const ContainerValidateParams* validate_params, 115 SerializationContext* context) { 116 DCHECK(validate_params->key_validate_params); 117 DCHECK(validate_params->element_validate_params); 118 if (CallIsNullIfExists<Traits>(input)) { 119 *output = nullptr; 120 return; 121 } 122 123 auto result = Data::New(buf); 124 if (result) { 125 auto keys_ptr = 126 MojomTypeTraits<Array<Key>>::Data::New(Traits::GetSize(input), buf); 127 if (keys_ptr) { 128 MapKeyReader<MaybeConstUserType> key_reader(input); 129 KeyArraySerializer::SerializeElements( 130 &key_reader, buf, keys_ptr, validate_params->key_validate_params, 131 context); 132 result->keys.Set(keys_ptr); 133 } 134 135 auto values_ptr = 136 MojomTypeTraits<Array<Value>>::Data::New(Traits::GetSize(input), buf); 137 if (values_ptr) { 138 MapValueReader<MaybeConstUserType> value_reader(input); 139 ValueArraySerializer::SerializeElements( 140 &value_reader, buf, values_ptr, 141 validate_params->element_validate_params, context); 142 result->values.Set(values_ptr); 143 } 144 } 145 *output = result; 146 } 147 148 static bool Deserialize(Data* input, 149 UserType* output, 150 SerializationContext* context) { 151 if (!input) 152 return CallSetToNullIfExists<Traits>(output); 153 154 std::vector<UserKey> keys; 155 std::vector<UserValue> values; 156 157 if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys, 158 context) || 159 !ValueArraySerializer::DeserializeElements(input->values.Get(), &values, 160 context)) { 161 return false; 162 } 163 164 DCHECK_EQ(keys.size(), values.size()); 165 size_t size = keys.size(); 166 Traits::SetToEmpty(output); 167 168 for (size_t i = 0; i < size; ++i) { 169 if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i]))) 170 return false; 171 } 172 return true; 173 } 174 }; 175 176 } // namespace internal 177 } // namespace mojo 178 179 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ 180