Home | History | Annotate | Download | only in lib
      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 
     28   explicit MapReaderBase(MaybeConstUserType& input)
     29       : input_(input), iter_(Traits::GetBegin(input_)) {}
     30   ~MapReaderBase() {}
     31 
     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.
     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 
     51   explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {}
     52   ~MapKeyReader() {}
     53 
     54   using GetNextResult =
     55       decltype(Traits::GetKey(std::declval<MaybeConstIterator&>()));
     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 
     71   explicit MapValueReader(MaybeConstUserType& input) : Base(input) {}
     72   ~MapValueReader() {}
     73 
     74   using GetNextResult =
     75       decltype(Traits::GetValue(std::declval<MaybeConstIterator&>()));
     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