auth_fields.h 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <span>
  5. #include "../../encoding/bit_writer.h"
  6. namespace sunrise::middleware::bap::activity_message::auth_fields {
  7. /** One fixed-width wire field. The row that builds it states what the value asserts. */
  8. struct Field final {
  9. std::uint64_t value{};
  10. std::uint8_t width{};
  11. };
  12. /** Presence bit that precedes every optional schema field. */
  13. inline constexpr std::uint8_t kPresenceWidth = 1;
  14. /** A schema boolean is one bit. */
  15. inline constexpr std::uint8_t kBoolWidth = 1;
  16. /** Signed 32-bit schema fields store zero at the middle of the unsigned wire range. */
  17. inline constexpr std::uint32_t kSigned32Bias = 0x80000000U;
  18. /** Generations and revisions are 31-bit counters that the client accepts only while positive. */
  19. inline constexpr std::uint8_t kCounterWidth = 31;
  20. inline constexpr std::uint32_t kMaximumCounter = 0x7FFFFFFFU;
  21. /** A nested ClientRef is a 32-bit registry key, a 7-bit biased slot type and a 16-bit biased index.
  22. */
  23. inline constexpr std::uint8_t kClientRefKeyWidth = 32;
  24. inline constexpr std::uint8_t kClientRefTypeWidth = 7;
  25. inline constexpr std::uint8_t kClientRefIndexWidth = 16;
  26. inline constexpr std::uint32_t kClientRefTypeBias = 1;
  27. inline constexpr std::uint32_t kClientRefIndexBias = 32'768;
  28. inline constexpr std::uint16_t kMaximumClientRefIndex = 32'767;
  29. /** The unset ClientRef carries the no-name hash, type zero and index -1. */
  30. inline constexpr std::uint32_t kClientRefAbsentKey = 0x811C9DC5U;
  31. inline constexpr std::size_t kClientRefBits =
  32. kClientRefKeyWidth + kClientRefTypeWidth + kClientRefIndexWidth;
  33. /** Writes the fields in order. @return False when the writer runs out of room. */
  34. [[nodiscard]] inline bool write_fields(encoding::bits::Writer& writer,
  35. std::span<const Field> fields) noexcept {
  36. for (const Field& field : fields) {
  37. if (!writer.write(field.value, field.width)) {
  38. return false;
  39. }
  40. }
  41. return true;
  42. }
  43. /** Writes one present ClientRef naming an exact slot. */
  44. [[nodiscard]] inline bool write_client_ref(encoding::bits::Writer& writer,
  45. std::uint32_t registryKey,
  46. std::uint32_t slotType,
  47. std::uint16_t slotIndex) noexcept {
  48. return writer.write(registryKey, kClientRefKeyWidth)
  49. && writer.write(slotType + kClientRefTypeBias, kClientRefTypeWidth)
  50. && writer.write(slotIndex + kClientRefIndexBias, kClientRefIndexWidth);
  51. }
  52. /** Writes the unset ClientRef. */
  53. [[nodiscard]] inline bool write_absent_client_ref(encoding::bits::Writer& writer) noexcept {
  54. return writer.write(kClientRefAbsentKey, kClientRefKeyWidth)
  55. && writer.write(0, kClientRefTypeWidth)
  56. && writer.write(kClientRefIndexBias - 1U, kClientRefIndexWidth);
  57. }
  58. /** @return True when the writer holds exactly the expected bits and closes into the byte count. */
  59. [[nodiscard]] inline bool finish_exact(encoding::bits::Writer& writer,
  60. std::size_t bits,
  61. std::size_t bytes,
  62. std::size_t& written) noexcept {
  63. return writer.bit_count() == bits && writer.finish(written) && written == bytes;
  64. }
  65. /** @return True when a body's byte count is the one its bit count needs. */
  66. [[nodiscard]] constexpr bool bytes_match_bits(std::size_t bytes, std::size_t bits) noexcept {
  67. return bytes == (bits + 7U) / 8U;
  68. }
  69. } // namespace sunrise::middleware::bap::activity_message::auth_fields