| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <optional> |
| #include <type_traits> |
| |
| #include "impeller/archivist/archivable.h" |
| #include "impeller/archivist/archive.h" |
| #include "impeller/base/allocation.h" |
| |
| namespace impeller { |
| |
| class Archive; |
| class ArchiveClassRegistration; |
| class ArchiveStatement; |
| |
| class ArchiveLocation { |
| public: |
| PrimaryKey GetPrimaryKey() const; |
| |
| template <class T, class = std::enable_if_t<std::is_integral<T>::value>> |
| bool Write(const std::string& member, T item) { |
| return WriteIntegral(member, static_cast<int64_t>(item)); |
| } |
| |
| bool Write(const std::string& member, double item); |
| |
| bool Write(const std::string& member, const std::string& item); |
| |
| bool Write(const std::string& member, const Allocation& allocation); |
| |
| template <class T, |
| class = std::enable_if_t<std::is_base_of<Archivable, T>::value>> |
| bool WriteArchivable(const std::string& member, const T& other) { |
| const ArchiveDef& otherDef = T::ArchiveDefinition; |
| return Write(member, otherDef, other); |
| } |
| |
| template <class T, class = std::enable_if_t<std::is_enum<T>::value>> |
| bool WriteEnum(const std::string& member, const T& item) { |
| return WriteIntegral(member, static_cast<int64_t>(item)); |
| } |
| |
| template <class T, |
| class = std::enable_if_t<std::is_base_of<Archivable, T>::value>> |
| bool Write(const std::string& member, const std::vector<T>& items) { |
| /* |
| * All items in the vector are individually encoded and their keys noted |
| */ |
| std::vector<int64_t> members; |
| members.reserve(items.size()); |
| |
| const ArchiveDef& itemDefinition = T::kArchiveDefinition; |
| for (const auto& item : items) { |
| auto row_id = context_.ArchiveInstance(itemDefinition, item); |
| if (!row_id.has_value()) { |
| return false; |
| } |
| members.emplace_back(row_id.value()); |
| } |
| |
| /* |
| * The keys are flattened into the vectors table. Write to that table |
| */ |
| auto vectorInsert = WriteVectorKeys(std::move(members)); |
| |
| if (!vectorInsert.has_value()) { |
| return false; |
| } |
| |
| return WriteIntegral(member, vectorInsert.value()); |
| } |
| |
| template <class T, class = std::enable_if_t<std::is_integral<T>::value>> |
| bool Read(const std::string& member, T& item) { |
| int64_t decoded = 0; |
| auto result = ReadIntegral(member, decoded); |
| item = static_cast<T>(decoded); |
| return result; |
| } |
| |
| bool Read(const std::string& member, double& item); |
| |
| bool Read(const std::string& member, std::string& item); |
| |
| bool Read(const std::string& member, Allocation& allocation); |
| |
| template <class T, |
| class = std::enable_if_t<std::is_base_of<Archivable, T>::value>> |
| bool ReadArchivable(const std::string& member, T& other) { |
| const ArchiveDef& otherDef = T::ArchiveDefinition; |
| return decode(member, otherDef, other); |
| } |
| |
| template <class T, class = std::enable_if_t<std::is_enum<T>::value>> |
| bool ReadEnum(const std::string& member, T& item) { |
| int64_t desugared = 0; |
| if (ReadIntegral(member, desugared)) { |
| item = static_cast<T>(desugared); |
| return true; |
| } |
| return false; |
| } |
| |
| template <class T, |
| class = std::enable_if_t<std::is_base_of<Archivable, T>::value>> |
| bool Read(const std::string& member, std::vector<T>& items) { |
| /* |
| * From the member, find the foreign key of the vector |
| */ |
| int64_t vectorForeignKey = 0; |
| if (!ReadIntegral(member, vectorForeignKey)) { |
| return false; |
| } |
| |
| /* |
| * Get vector keys |
| */ |
| std::vector<int64_t> keys; |
| if (!ReadVectorKeys(vectorForeignKey, keys)) { |
| return false; |
| } |
| |
| const ArchiveDef& otherDef = T::kArchiveDefinition; |
| for (const auto& key : keys) { |
| items.emplace_back(); |
| |
| if (!context_.UnarchiveInstance(otherDef, key, items.back())) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| private: |
| Archive& context_; |
| ArchiveStatement& statement_; |
| const ArchiveClassRegistration& registration_; |
| PrimaryKey primary_key_; |
| |
| friend class Archive; |
| |
| ArchiveLocation(Archive& context, |
| ArchiveStatement& statement, |
| const ArchiveClassRegistration& registration, |
| PrimaryKey name); |
| |
| bool WriteIntegral(const std::string& member, int64_t item); |
| |
| bool ReadIntegral(const std::string& member, int64_t& item); |
| |
| std::optional<int64_t> WriteVectorKeys(std::vector<int64_t>&& members); |
| |
| bool ReadVectorKeys(PrimaryKey name, std::vector<int64_t>& members); |
| |
| bool Write(const std::string& member, |
| const ArchiveDef& otherDef, |
| const Archivable& other); |
| |
| bool Read(const std::string& member, |
| const ArchiveDef& otherDef, |
| Archivable& other); |
| |
| ArchiveLocation(const ArchiveLocation&) = delete; |
| |
| ArchiveLocation& operator=(const ArchiveLocation&) = delete; |
| }; |
| |
| } // namespace impeller |