activity_telemetry_parser.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * Telemetry and reservation bodies. Each one is framed only as far as its recovered grammar
  3. * reaches, and the caller is told how many bits that was, so a body that is retained rather than
  4. * understood is never counted as fully read.
  5. */
  6. #include <bit>
  7. #include "../../encoding/bit_reader.h"
  8. #include "../../encoding/byte_order.h"
  9. #include "telemetry.h"
  10. namespace sunrise::middleware::bap::activity_message::telemetry {
  11. namespace {
  12. /** Opaque scalar bodies are biased by the midpoint of the unsigned 32-bit range. */
  13. constexpr std::uint32_t kScalarBias = 0x80000000U;
  14. /** Every high-water word is read most significant bit first, as the rest of the body is. */
  15. constexpr std::uint8_t kNarrowWidth = 32;
  16. /** See kNarrowWidth. */
  17. constexpr std::uint8_t kWideWidth = 64;
  18. } // namespace
  19. /** Parses a peer-reservation request. */
  20. bool parse_reservation_request(std::span<const std::byte> input,
  21. ReservationRequest& request,
  22. std::size_t& consumedBits) noexcept {
  23. request = {};
  24. consumedBits = 0;
  25. if (input.size() < kReservationRevisionSize) {
  26. return false;
  27. }
  28. request.revision = encoding::read_u32_be(input.first<encoding::kU32Size>());
  29. request.recordBytes = static_cast<std::uint32_t>(input.size() - kReservationRevisionSize);
  30. consumedBits = kReservationRevisionSize * encoding::kBitsPerByte;
  31. return true;
  32. }
  33. /** Parses a lag-switch report as far as its record count. */
  34. bool parse_lag_switch(std::span<const std::byte> input,
  35. LagSwitchReport& report,
  36. std::size_t& consumedBits) noexcept {
  37. report = {};
  38. consumedBits = 0;
  39. encoding::bits::Reader reader(input);
  40. std::uint64_t count = 0;
  41. if (!reader.read(kLagRecordCountWidth, count)) {
  42. return false;
  43. }
  44. report.recordCount = static_cast<std::uint8_t>(count);
  45. report.aboveSupported = report.recordCount > kLagRecordSupported;
  46. report.recordBits = static_cast<std::uint32_t>(reader.remaining_bits());
  47. consumedBits = kLagRecordCountWidth;
  48. return true;
  49. }
  50. /** Parses the fixed high-water telemetry block. */
  51. bool parse_high_water(std::span<const std::byte> input,
  52. HighWater& block,
  53. std::size_t& consumedBits) noexcept {
  54. block = {};
  55. consumedBits = 0;
  56. if (input.size() < kHighWaterSize) {
  57. return false;
  58. }
  59. encoding::bits::Reader reader(input);
  60. std::uint64_t field = 0;
  61. for (std::uint32_t& word : block.narrow) {
  62. if (!reader.read(kNarrowWidth, field)) {
  63. return false;
  64. }
  65. word = static_cast<std::uint32_t>(field);
  66. }
  67. for (std::uint64_t& word : block.wide) {
  68. if (!reader.read(kWideWidth, field)) {
  69. return false;
  70. }
  71. word = field;
  72. }
  73. consumedBits = input.size() * encoding::kBitsPerByte - reader.remaining_bits();
  74. return true;
  75. }
  76. /** Parses one biased signed scalar body. */
  77. bool parse_opaque_scalar(std::span<const std::byte> input,
  78. std::int32_t& value,
  79. std::size_t& consumedBits) noexcept {
  80. value = 0;
  81. consumedBits = 0;
  82. if (input.size() < kScalarSize) {
  83. return false;
  84. }
  85. const std::uint32_t raw = encoding::read_u32_be(input.first<encoding::kU32Size>());
  86. value = std::bit_cast<std::int32_t>(raw - kScalarBias);
  87. consumedBits = kScalarSize * encoding::kBitsPerByte;
  88. return true;
  89. }
  90. } // namespace sunrise::middleware::bap::activity_message::telemetry