sense_update_body.h 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include "../../encoding/bit_reader.h"
  5. #include "sense_update.h"
  6. // Shared by the msg-6 packet framing and the per-schema Sense body readers.
  7. namespace sunrise::middleware::bap::activity_message::sense_update::body {
  8. /** How far one body decode got. */
  9. enum class NativeStatus : std::uint8_t { complete, unsupported, unsafeCount, malformed };
  10. /** Bit reader with its own budget, so one object cannot consume the whole packet. */
  11. class Reader final {
  12. public:
  13. Reader(encoding::bits::Reader& source, std::size_t budget, std::size_t total) noexcept
  14. : source_(source), left_(budget), total_(total) {}
  15. [[nodiscard]] bool read(std::uint8_t width, std::uint64_t& value) noexcept {
  16. if (width > left_ || !source_.read(width, value)) {
  17. return false;
  18. }
  19. left_ -= width;
  20. return true;
  21. }
  22. [[nodiscard]] bool skip(std::size_t width) noexcept {
  23. if (width > left_ || !source_.skip(width)) {
  24. return false;
  25. }
  26. left_ -= width;
  27. return true;
  28. }
  29. [[nodiscard]] std::size_t left() const noexcept {
  30. return left_;
  31. }
  32. [[nodiscard]] std::size_t position() const noexcept {
  33. return total_ - source_.remaining_bits();
  34. }
  35. private:
  36. encoding::bits::Reader& source_;
  37. std::size_t left_{};
  38. std::size_t total_{};
  39. };
  40. /** Collects decoded values into the packet, dropping them once the object's room runs out. */
  41. class Values final {
  42. public:
  43. Values(DecodedPacket& packet, DecodedObject* object) noexcept
  44. : packet_(packet), object_(object) {}
  45. /** Retains one field value, marking truncation when the packet's storage is full. */
  46. void put(std::uint32_t schema,
  47. std::uint16_t ordinal,
  48. std::uint32_t occurrence,
  49. std::uint32_t at,
  50. std::uint8_t width,
  51. ValueKind kind,
  52. std::uint64_t raw,
  53. std::int64_t signedRaw,
  54. float real,
  55. bool present) noexcept {
  56. if (object_ == nullptr) {
  57. return;
  58. }
  59. if (packet_.valueCount == packet_.values.size()) {
  60. packet_.valuesTruncated = true;
  61. return;
  62. }
  63. DecodedValue& value = packet_.values[packet_.valueCount++];
  64. value.schemaRow = schema;
  65. value.fieldRow = ordinal;
  66. value.fieldOrdinal = ordinal;
  67. value.occurrence = occurrence;
  68. value.bitOffset = at;
  69. value.width = width;
  70. value.kind = kind;
  71. value.unsignedValue = raw;
  72. value.signedValue = signedRaw;
  73. value.realValue = real;
  74. value.present = present;
  75. }
  76. private:
  77. DecodedPacket& packet_;
  78. DecodedObject* object_{};
  79. };
  80. /**
  81. * Decodes one root body of the given schema within the reader's budget.
  82. * @return How far it got; any status but malformed leaves the group skippable.
  83. */
  84. [[nodiscard]] NativeStatus
  85. decode_body(std::uint32_t schema, Reader& reader, Values& values) noexcept;
  86. } // namespace sunrise::middleware::bap::activity_message::sense_update::body