• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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