160 lines
5.7 KiB
C++
160 lines
5.7 KiB
C++
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|
|
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|
|
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#include "mojo/public/cpp/bindings/array_data_view.h"
|
|
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
|
|
#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
|
|
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
|
|
#include "mojo/public/cpp/bindings/map_data_view.h"
|
|
|
|
namespace mojo {
|
|
namespace internal {
|
|
|
|
template <typename MaybeConstUserType>
|
|
class MapReaderBase {
|
|
public:
|
|
using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
|
using Traits = MapTraits<UserType>;
|
|
using MaybeConstIterator =
|
|
decltype(Traits::GetBegin(std::declval<MaybeConstUserType&>()));
|
|
|
|
explicit MapReaderBase(MaybeConstUserType& input)
|
|
: input_(input), iter_(Traits::GetBegin(input_)) {}
|
|
~MapReaderBase() {}
|
|
|
|
size_t GetSize() const { return Traits::GetSize(input_); }
|
|
|
|
// Return null because key or value elements are not stored continuously in
|
|
// memory.
|
|
void* GetDataIfExists() { return nullptr; }
|
|
|
|
protected:
|
|
MaybeConstUserType& input_;
|
|
MaybeConstIterator iter_;
|
|
};
|
|
|
|
// Used as the UserTypeReader template parameter of ArraySerializer.
|
|
template <typename MaybeConstUserType>
|
|
class MapKeyReader : public MapReaderBase<MaybeConstUserType> {
|
|
public:
|
|
using Base = MapReaderBase<MaybeConstUserType>;
|
|
using Traits = typename Base::Traits;
|
|
using MaybeConstIterator = typename Base::MaybeConstIterator;
|
|
|
|
explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {}
|
|
~MapKeyReader() {}
|
|
|
|
using GetNextResult =
|
|
decltype(Traits::GetKey(std::declval<MaybeConstIterator&>()));
|
|
GetNextResult GetNext() {
|
|
GetNextResult key = Traits::GetKey(this->iter_);
|
|
Traits::AdvanceIterator(this->iter_);
|
|
return key;
|
|
}
|
|
};
|
|
|
|
// Used as the UserTypeReader template parameter of ArraySerializer.
|
|
template <typename MaybeConstUserType>
|
|
class MapValueReader : public MapReaderBase<MaybeConstUserType> {
|
|
public:
|
|
using Base = MapReaderBase<MaybeConstUserType>;
|
|
using Traits = typename Base::Traits;
|
|
using MaybeConstIterator = typename Base::MaybeConstIterator;
|
|
|
|
explicit MapValueReader(MaybeConstUserType& input) : Base(input) {}
|
|
~MapValueReader() {}
|
|
|
|
using GetNextResult =
|
|
decltype(Traits::GetValue(std::declval<MaybeConstIterator&>()));
|
|
GetNextResult GetNext() {
|
|
GetNextResult value = Traits::GetValue(this->iter_);
|
|
Traits::AdvanceIterator(this->iter_);
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template <typename Key, typename Value, typename MaybeConstUserType>
|
|
struct Serializer<MapDataView<Key, Value>, MaybeConstUserType> {
|
|
using UserType = typename std::remove_const<MaybeConstUserType>::type;
|
|
using Traits = MapTraits<UserType>;
|
|
using UserKey = typename Traits::Key;
|
|
using UserValue = typename Traits::Value;
|
|
using Data = typename MojomTypeTraits<MapDataView<Key, Value>>::Data;
|
|
using KeyArraySerializer = ArraySerializer<ArrayDataView<Key>,
|
|
std::vector<UserKey>,
|
|
MapKeyReader<MaybeConstUserType>>;
|
|
using ValueArraySerializer =
|
|
ArraySerializer<ArrayDataView<Value>,
|
|
std::vector<UserValue>,
|
|
MapValueReader<MaybeConstUserType>>;
|
|
|
|
static void Serialize(MaybeConstUserType& input,
|
|
Buffer* buf,
|
|
typename Data::BufferWriter* writer,
|
|
const ContainerValidateParams* validate_params,
|
|
SerializationContext* context) {
|
|
DCHECK(validate_params->key_validate_params);
|
|
DCHECK(validate_params->element_validate_params);
|
|
if (CallIsNullIfExists<Traits>(input))
|
|
return;
|
|
|
|
writer->Allocate(buf);
|
|
typename MojomTypeTraits<ArrayDataView<Key>>::Data::BufferWriter
|
|
keys_writer;
|
|
keys_writer.Allocate(Traits::GetSize(input), buf);
|
|
MapKeyReader<MaybeConstUserType> key_reader(input);
|
|
KeyArraySerializer::SerializeElements(&key_reader, buf, &keys_writer,
|
|
validate_params->key_validate_params,
|
|
context);
|
|
(*writer)->keys.Set(keys_writer.data());
|
|
|
|
typename MojomTypeTraits<ArrayDataView<Value>>::Data::BufferWriter
|
|
values_writer;
|
|
values_writer.Allocate(Traits::GetSize(input), buf);
|
|
MapValueReader<MaybeConstUserType> value_reader(input);
|
|
ValueArraySerializer::SerializeElements(
|
|
&value_reader, buf, &values_writer,
|
|
validate_params->element_validate_params, context);
|
|
(*writer)->values.Set(values_writer.data());
|
|
}
|
|
|
|
static bool Deserialize(Data* input,
|
|
UserType* output,
|
|
SerializationContext* context) {
|
|
if (!input)
|
|
return CallSetToNullIfExists<Traits>(output);
|
|
|
|
std::vector<UserKey> keys;
|
|
std::vector<UserValue> values;
|
|
|
|
if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys,
|
|
context) ||
|
|
!ValueArraySerializer::DeserializeElements(input->values.Get(), &values,
|
|
context)) {
|
|
return false;
|
|
}
|
|
|
|
DCHECK_EQ(keys.size(), values.size());
|
|
size_t size = keys.size();
|
|
Traits::SetToEmpty(output);
|
|
|
|
for (size_t i = 0; i < size; ++i) {
|
|
if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i])))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace internal
|
|
} // namespace mojo
|
|
|
|
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_
|