cache_payload_writer.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "cache_payload_writer.h"
  2. #include "../records/codec.h"
  3. namespace sunrise::state::build_data::cache::writer {
  4. namespace {
  5. /**
  6. * Writes one whole object at the current file position.
  7. * @tparam Value Trivially copied cache object.
  8. * @param file Open temporary cache handle.
  9. * @param value Whole object to write.
  10. * @return True when Windows writes every byte.
  11. */
  12. template <typename Value> [[nodiscard]] bool write_value(HANDLE file, const Value& value) noexcept {
  13. DWORD transferred = 0;
  14. return WriteFile(file, &value, static_cast<DWORD>(sizeof value), &transferred, nullptr) != FALSE
  15. && transferred == sizeof value;
  16. }
  17. /**
  18. * Encodes one domain and extends the shared checksum with each packed row.
  19. * @tparam Record Packed disk record type.
  20. * @tparam Value Runtime row type the codec overload picks.
  21. * @param values Complete sorted runtime rows.
  22. * @param checksum Running payload checksum.
  23. * @return True when every row has a valid disk form.
  24. */
  25. template <typename Record, typename Value>
  26. [[nodiscard]] bool checksum_domain(std::span<const Value> values,
  27. std::uint64_t& checksum) noexcept {
  28. for (const Value& value : values) {
  29. Record record{};
  30. if (!records::encode(value, record)) {
  31. return false;
  32. }
  33. checksum = records::checksum_value(checksum, record);
  34. }
  35. return true;
  36. }
  37. /**
  38. * Encodes and writes one whole domain in its checked sort order.
  39. * @tparam Record Packed disk record type.
  40. * @tparam Value Runtime row type the codec overload picks.
  41. * @param file Open temporary cache handle.
  42. * @param values Complete sorted runtime rows.
  43. * @return True when every packed row is written in full.
  44. */
  45. template <typename Record, typename Value>
  46. [[nodiscard]] bool write_domain(HANDLE file, std::span<const Value> values) noexcept {
  47. for (const Value& value : values) {
  48. Record record{};
  49. if (!records::encode(value, record) || !write_value(file, record)) {
  50. return false;
  51. }
  52. }
  53. return true;
  54. }
  55. } // namespace
  56. /** Computes one checksum across every array in its fixed file order. */
  57. bool payload_checksum(records::Domains domains, std::uint64_t& checksum) noexcept {
  58. checksum = records::checksum_value(
  59. records::checksum_value(records::kChecksumOffsetBasis, domains.constants),
  60. domains.positionFingerprint);
  61. return checksum_domain<records::NamedRecord>(domains.named, checksum)
  62. && checksum_domain<records::ItemRecord>(domains.items, checksum)
  63. && checksum_domain<records::CollectibleRecord>(domains.collectibles, checksum)
  64. && checksum_domain<records::MaterialRequirementSetRecord>(
  65. domains.materialRequirementSets, checksum)
  66. && checksum_domain<records::ItemDetailRecord>(domains.itemDetails, checksum)
  67. && checksum_domain<records::SocketPlugRuleRecord>(domains.socketPlugRules, checksum)
  68. && checksum_domain<records::SocketPlugPoolRecord>(domains.socketPlugPools, checksum)
  69. && checksum_domain<records::SocketPlugMemberRecord>(domains.socketPlugMembers, checksum)
  70. && checksum_domain<records::InventoryBucketRecord>(domains.inventoryBuckets, checksum)
  71. && checksum_domain<records::SocketEntryListRecord>(domains.socketEntryLists, checksum)
  72. && checksum_domain<records::SocketEntryTableRecord>(domains.socketEntryTables, checksum)
  73. && checksum_domain<records::AbilityBucketRecord>(domains.abilityBuckets, checksum)
  74. && checksum_domain<records::ProgressionRecord>(domains.progressions, checksum)
  75. && checksum_domain<records::ScenarioRecord>(domains.scenarios, checksum)
  76. && checksum_domain<records::RosterGroupRecord>(domains.rosterGroups, checksum)
  77. && checksum_domain<records::SpawnStemRecord>(domains.spawnStems, checksum)
  78. && checksum_domain<records::SpawnNameHashRecord>(domains.spawnNameHashes, checksum)
  79. && checksum_domain<records::SpawnPointRecord>(domains.spawnPoints, checksum)
  80. && checksum_domain<records::HashNameRecord>(domains.hashNames, checksum)
  81. && checksum_domain<records::VendorIndexRecord>(domains.vendorIndex, checksum)
  82. && checksum_domain<records::VendorDefinitionRecord>(domains.vendorDefinitions, checksum)
  83. && checksum_domain<records::VendorSaleRowRecord>(domains.vendorSaleRows, checksum)
  84. && checksum_domain<records::VendorInstalledRowRecord>(domains.vendorInstalledRows,
  85. checksum)
  86. && checksum_domain<records::PositionProfileRecord>(domains.positionProfiles, checksum)
  87. && checksum_domain<records::ObjectTypeRecord>(domains.objectTypes, checksum);
  88. }
  89. /** Writes every array in the same order used by the payload checksum. */
  90. bool write_payload(HANDLE file, records::Domains domains) noexcept {
  91. return write_domain<records::NamedRecord>(file, domains.named)
  92. && write_domain<records::ItemRecord>(file, domains.items)
  93. && write_domain<records::CollectibleRecord>(file, domains.collectibles)
  94. && write_domain<records::MaterialRequirementSetRecord>(file,
  95. domains.materialRequirementSets)
  96. && write_domain<records::ItemDetailRecord>(file, domains.itemDetails)
  97. && write_domain<records::SocketPlugRuleRecord>(file, domains.socketPlugRules)
  98. && write_domain<records::SocketPlugPoolRecord>(file, domains.socketPlugPools)
  99. && write_domain<records::SocketPlugMemberRecord>(file, domains.socketPlugMembers)
  100. && write_domain<records::InventoryBucketRecord>(file, domains.inventoryBuckets)
  101. && write_domain<records::SocketEntryListRecord>(file, domains.socketEntryLists)
  102. && write_domain<records::SocketEntryTableRecord>(file, domains.socketEntryTables)
  103. && write_domain<records::AbilityBucketRecord>(file, domains.abilityBuckets)
  104. && write_domain<records::ProgressionRecord>(file, domains.progressions)
  105. && write_domain<records::ScenarioRecord>(file, domains.scenarios)
  106. && write_domain<records::RosterGroupRecord>(file, domains.rosterGroups)
  107. && write_domain<records::SpawnStemRecord>(file, domains.spawnStems)
  108. && write_domain<records::SpawnNameHashRecord>(file, domains.spawnNameHashes)
  109. && write_domain<records::SpawnPointRecord>(file, domains.spawnPoints)
  110. && write_domain<records::HashNameRecord>(file, domains.hashNames)
  111. && write_domain<records::VendorIndexRecord>(file, domains.vendorIndex)
  112. && write_domain<records::VendorDefinitionRecord>(file, domains.vendorDefinitions)
  113. && write_domain<records::VendorSaleRowRecord>(file, domains.vendorSaleRows)
  114. && write_domain<records::VendorInstalledRowRecord>(file, domains.vendorInstalledRows)
  115. && write_domain<records::PositionProfileRecord>(file, domains.positionProfiles)
  116. && write_domain<records::ObjectTypeRecord>(file, domains.objectTypes);
  117. }
  118. } // namespace sunrise::state::build_data::cache::writer