opcode406_codec.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #include <cstddef>
  2. #include "../../../state/account/inventory/item_state.h"
  3. #include "../../encoding/bit_reader.h"
  4. #include "opcode406.h"
  5. namespace sunrise::middleware::web_service::messages::opcode406 {
  6. namespace {
  7. /** The reflected item-state request occupies exactly 120 bits. */
  8. constexpr std::size_t kPayloadSize = 15;
  9. /** Signed native definition indices use one presence bit followed by fifteen value bits. */
  10. constexpr std::uint8_t kDefinitionIndexWidth = 15;
  11. /** The accumulated state value fills one signed 32-bit field. */
  12. constexpr std::uint8_t kValueWidth = 32;
  13. /** The descriptor pads its fields out to whole bytes. */
  14. constexpr std::uint8_t kPaddingWidth = 7;
  15. /** Nonnegative signed 32-bit values have this bit set after native descriptor biasing. */
  16. constexpr std::uint64_t kValueBias = 0x80000000ULL;
  17. } // namespace
  18. /** Parses the exact native item-state descriptor. */
  19. bool parse_request(const Message& message, Request& request) noexcept {
  20. request = {};
  21. if (message.opcode != kOpcode) {
  22. return false;
  23. }
  24. encoding::bits::Reader reader(message.payload);
  25. std::uint64_t instancePresent = 0;
  26. std::uint64_t instanceSoid = 0;
  27. std::uint64_t definitionPresent = 0;
  28. std::uint64_t definitionIndex = 0;
  29. std::uint64_t encodedFlags = 0;
  30. std::uint64_t padding = 0;
  31. const bool read = message.payload.size() == kPayloadSize && reader.read(1, instancePresent)
  32. && reader.read(64, instanceSoid) && reader.read(1, definitionPresent)
  33. && reader.read(kDefinitionIndexWidth, definitionIndex)
  34. && reader.read(kValueWidth, encodedFlags)
  35. && reader.read(kPaddingWidth, padding) && reader.remaining_bits() == 0;
  36. // Whatever the read reached is kept, so a refused request still describes itself.
  37. request.instanceSoid = instanceSoid;
  38. request.definitionIndex = static_cast<std::uint16_t>(definitionIndex);
  39. if (encodedFlags >= kValueBias) {
  40. request.flags = static_cast<std::uint32_t>(encodedFlags - kValueBias);
  41. }
  42. return read && instancePresent != 0 && instanceSoid != 0 && definitionPresent != 0
  43. && encodedFlags >= kValueBias && padding == 0
  44. && state::account::inventory::valid_item_state(
  45. static_cast<std::uint32_t>(encodedFlags - kValueBias));
  46. }
  47. } // namespace sunrise::middleware::web_service::messages::opcode406