• 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.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