#include "cache_payload_writer.h" #include "../records/codec.h" namespace sunrise::state::build_data::cache::writer { namespace { /** * Writes one whole object at the current file position. * @tparam Value Trivially copied cache object. * @param file Open temporary cache handle. * @param value Whole object to write. * @return True when Windows writes every byte. */ template [[nodiscard]] bool write_value(HANDLE file, const Value& value) noexcept { DWORD transferred = 0; return WriteFile(file, &value, static_cast(sizeof value), &transferred, nullptr) != FALSE && transferred == sizeof value; } /** * Encodes one domain and extends the shared checksum with each packed row. * @tparam Record Packed disk record type. * @tparam Value Runtime row type the codec overload picks. * @param values Complete sorted runtime rows. * @param checksum Running payload checksum. * @return True when every row has a valid disk form. */ template [[nodiscard]] bool checksum_domain(std::span values, std::uint64_t& checksum) noexcept { for (const Value& value : values) { Record record{}; if (!records::encode(value, record)) { return false; } checksum = records::checksum_value(checksum, record); } return true; } /** * Encodes and writes one whole domain in its checked sort order. * @tparam Record Packed disk record type. * @tparam Value Runtime row type the codec overload picks. * @param file Open temporary cache handle. * @param values Complete sorted runtime rows. * @return True when every packed row is written in full. */ template [[nodiscard]] bool write_domain(HANDLE file, std::span values) noexcept { for (const Value& value : values) { Record record{}; if (!records::encode(value, record) || !write_value(file, record)) { return false; } } return true; } } // namespace /** Computes one checksum across every array in its fixed file order. */ bool payload_checksum(records::Domains domains, std::uint64_t& checksum) noexcept { checksum = records::checksum_value(records::kChecksumOffsetBasis, domains.constants); return checksum_domain(domains.named, checksum) && checksum_domain(domains.items, checksum) && checksum_domain(domains.collectibles, checksum) && checksum_domain( domains.materialRequirementSets, checksum) && checksum_domain(domains.itemDetails, checksum) && checksum_domain(domains.socketPlugRules, checksum) && checksum_domain(domains.socketPlugPools, checksum) && checksum_domain(domains.socketPlugMembers, checksum) && checksum_domain(domains.inventoryBuckets, checksum) && checksum_domain(domains.socketEntryLists, checksum) && checksum_domain(domains.socketEntryTables, checksum) && checksum_domain(domains.abilityBuckets, checksum) && checksum_domain(domains.progressions, checksum) && checksum_domain(domains.scenarios, checksum) && checksum_domain(domains.rosterGroups, checksum) && checksum_domain(domains.spawnStems, checksum) && checksum_domain(domains.spawnNameHashes, checksum) && checksum_domain(domains.hashNames, checksum); } /** Writes every array in the same order used by the payload checksum. */ bool write_payload(HANDLE file, records::Domains domains) noexcept { return write_domain(file, domains.named) && write_domain(file, domains.items) && write_domain(file, domains.collectibles) && write_domain(file, domains.materialRequirementSets) && write_domain(file, domains.itemDetails) && write_domain(file, domains.socketPlugRules) && write_domain(file, domains.socketPlugPools) && write_domain(file, domains.socketPlugMembers) && write_domain(file, domains.inventoryBuckets) && write_domain(file, domains.socketEntryLists) && write_domain(file, domains.socketEntryTables) && write_domain(file, domains.abilityBuckets) && write_domain(file, domains.progressions) && write_domain(file, domains.scenarios) && write_domain(file, domains.rosterGroups) && write_domain(file, domains.spawnStems) && write_domain(file, domains.spawnNameHashes) && write_domain(file, domains.hashNames); } } // namespace sunrise::state::build_data::cache::writer