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 void Serialize(MaybeConstUserType& input, 99 Buffer* buf, 100 typename Data::BufferWriter* writer, 101 const ContainerValidateParams* validate_params, 102 SerializationContext* context) { 103 DCHECK(validate_params->key_validate_params); 104 DCHECK(validate_params->element_validate_params); 105 if (CallIsNullIfExists<Traits>(input)) 106 return; 107 108 writer->Allocate(buf); 109 typename MojomTypeTraits<ArrayDataView<Key>>::Data::BufferWriter 110 keys_writer; 111 keys_writer.Allocate(Traits::GetSize(input), buf); 112 MapKeyReader<MaybeConstUserType> key_reader(input); 113 KeyArraySerializer::SerializeElements(&key_reader, buf, &keys_writer, 114 validate_params->key_validate_params, 115 context); 116 (*writer)->keys.Set(keys_writer.data()); 117 118 typename MojomTypeTraits<ArrayDataView<Value>>::Data::BufferWriter 119 values_writer; 120 values_writer.Allocate(Traits::GetSize(input), buf); 121 MapValueReader<MaybeConstUserType> value_reader(input); 122 ValueArraySerializer::SerializeElements( 123 &value_reader, buf, &values_writer, 124 validate_params->element_validate_params, context); 125 (*writer)->values.Set(values_writer.data()); 126 } 127 128 static bool Deserialize(Data* input, 129 UserType* output, 130 SerializationContext* context) { 131 if (!input) 132 return CallSetToNullIfExists<Traits>(output); 133 134 std::vector<UserKey> keys; 135 std::vector<UserValue> values; 136 137 if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys, 138 context) || 139 !ValueArraySerializer::DeserializeElements(input->values.Get(), &values, 140 context)) { 141 return false; 142 } 143 144 DCHECK_EQ(keys.size(), values.size()); 145 size_t size = keys.size(); 146 Traits::SetToEmpty(output); 147 148 for (size_t i = 0; i < size; ++i) { 149 if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i]))) 150 return false; 151 } 152 return true; 153 } 154 }; 155 156 } // namespace internal 157 } // namespace mojo 158 159 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ 160