cache_payload_writer.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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(records::kChecksumOffsetBasis, domains.constants);
  59. return checksum_domain<records::NamedRecord>(domains.named, checksum)
  60. && checksum_domain<records::ItemRecord>(domains.items, checksum)
  61. && checksum_domain<records::CollectibleRecord>(domains.collectibles, checksum)
  62. && checksum_domain<records::MaterialRequirementSetRecord>(
  63. domains.materialRequirementSets, checksum)
  64. && checksum_domain<records::ItemDetailRecord>(domains.itemDetails, checksum)
  65. && checksum_domain<records::SocketPlugRuleRecord>(domains.socketPlugRules, checksum)
  66. && checksum_domain<records::SocketPlugPoolRecord>(domains.socketPlugPools, checksum)
  67. && checksum_domain<records::SocketPlugMemberRecord>(domains.socketPlugMembers, checksum)
  68. && checksum_domain<records::InventoryBucketRecord>(domains.inventoryBuckets, checksum)
  69. && checksum_domain<records::SocketEntryListRecord>(domains.socketEntryLists, checksum)
  70. && checksum_domain<records::SocketEntryTableRecord>(domains.socketEntryTables, checksum)
  71. && checksum_domain<records::AbilityBucketRecord>(domains.abilityBuckets, checksum)
  72. && checksum_domain<records::ProgressionRecord>(domains.progressions, checksum)
  73. && checksum_domain<records::ScenarioRecord>(domains.scenarios, checksum)
  74. && checksum_domain<records::RosterGroupRecord>(domains.rosterGroups, checksum)
  75. && checksum_domain<records::SpawnStemRecord>(domains.spawnStems, checksum)
  76. && checksum_domain<records::SpawnNameHashRecord>(domains.spawnNameHashes, checksum)
  77. && checksum_domain<records::HashNameRecord>(domains.hashNames, checksum);
  78. }
  79. /** Writes every array in the same order used by the payload checksum. */
  80. bool write_payload(HANDLE file, records::Domains domains) noexcept {
  81. return write_domain<records::NamedRecord>(file, domains.named)
  82. && write_domain<records::ItemRecord>(file, domains.items)
  83. && write_domain<records::CollectibleRecord>(file, domains.collectibles)
  84. && write_domain<records::MaterialRequirementSetRecord>(file,
  85. domains.materialRequirementSets)
  86. && write_domain<records::ItemDetailRecord>(file, domains.itemDetails)
  87. && write_domain<records::SocketPlugRuleRecord>(file, domains.socketPlugRules)
  88. && write_domain<records::SocketPlugPoolRecord>(file, domains.socketPlugPools)
  89. && write_domain<records::SocketPlugMemberRecord>(file, domains.socketPlugMembers)
  90. && write_domain<records::InventoryBucketRecord>(file, domains.inventoryBuckets)
  91. && write_domain<records::SocketEntryListRecord>(file, domains.socketEntryLists)
  92. && write_domain<records::SocketEntryTableRecord>(file, domains.socketEntryTables)
  93. && write_domain<records::AbilityBucketRecord>(file, domains.abilityBuckets)
  94. && write_domain<records::ProgressionRecord>(file, domains.progressions)
  95. && write_domain<records::ScenarioRecord>(file, domains.scenarios)
  96. && write_domain<records::RosterGroupRecord>(file, domains.rosterGroups)
  97. && write_domain<records::SpawnStemRecord>(file, domains.spawnStems)
  98. && write_domain<records::SpawnNameHashRecord>(file, domains.spawnNameHashes)
  99. && write_domain<records::HashNameRecord>(file, domains.hashNames);
  100. }
  101. } // namespace sunrise::state::build_data::cache::writer