// 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 #include #include "mojo/public/cpp/bindings/array.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.h" namespace mojo { namespace internal { template class MapReaderBase { public: using UserType = typename std::remove_const::type; using Traits = MapTraits; using MaybeConstIterator = decltype(Traits::GetBegin(std::declval())); 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 class MapKeyReader : public MapReaderBase { public: using Base = MapReaderBase; using Traits = typename Base::Traits; explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} ~MapKeyReader() {} const typename Traits::Key& GetNext() { const typename Traits::Key& key = Traits::GetKey(this->iter_); Traits::AdvanceIterator(this->iter_); return key; } }; // Used as the UserTypeReader template parameter of ArraySerializer. template class MapValueReader : public MapReaderBase { public: using Base = MapReaderBase; using Traits = typename Base::Traits; using MaybeConstIterator = typename Base::MaybeConstIterator; explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} ~MapValueReader() {} using GetNextResult = decltype(Traits::GetValue(std::declval())); GetNextResult GetNext() { GetNextResult value = Traits::GetValue(this->iter_); Traits::AdvanceIterator(this->iter_); return value; } }; template struct Serializer, MaybeConstUserType> { using UserType = typename std::remove_const::type; using Traits = MapTraits; using UserKey = typename Traits::Key; using UserValue = typename Traits::Value; using Data = typename MojomTypeTraits>::Data; using KeyArraySerializer = ArraySerializer, std::vector, MapKeyReader>; using ValueArraySerializer = ArraySerializer, std::vector, MapValueReader>; static size_t PrepareToSerialize(MaybeConstUserType& input, SerializationContext* context) { if (CallIsNullIfExists(input)) return 0; size_t struct_overhead = sizeof(Data); MapKeyReader key_reader(input); size_t keys_size = KeyArraySerializer::GetSerializedSize(&key_reader, context); MapValueReader value_reader(input); size_t values_size = ValueArraySerializer::GetSerializedSize(&value_reader, context); return struct_overhead + keys_size + values_size; } static void Serialize(MaybeConstUserType& input, Buffer* buf, Data** output, const ContainerValidateParams* validate_params, SerializationContext* context) { DCHECK(validate_params->key_validate_params); DCHECK(validate_params->element_validate_params); if (CallIsNullIfExists(input)) { *output = nullptr; return; } auto result = Data::New(buf); if (result) { auto keys_ptr = MojomTypeTraits>::Data::New(Traits::GetSize(input), buf); if (keys_ptr) { MapKeyReader key_reader(input); KeyArraySerializer::SerializeElements( &key_reader, buf, keys_ptr, validate_params->key_validate_params, context); result->keys.Set(keys_ptr); } auto values_ptr = MojomTypeTraits>::Data::New(Traits::GetSize(input), buf); if (values_ptr) { MapValueReader value_reader(input); ValueArraySerializer::SerializeElements( &value_reader, buf, values_ptr, validate_params->element_validate_params, context); result->values.Set(values_ptr); } } *output = result; } static bool Deserialize(Data* input, UserType* output, SerializationContext* context) { if (!input) return CallSetToNullIfExists(output); std::vector keys; std::vector 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_