activity_sense_update_decoder.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. #include <bit>
  2. #include <limits>
  3. #include "../../encoding/bit_reader.h"
  4. #include "../../encoding/byte_order.h"
  5. #include "sense_update.h"
  6. namespace sunrise::middleware::bap::activity_message::sense_update {
  7. namespace {
  8. namespace bits = middleware::encoding::bits;
  9. /** Field widths of the object header ClientRef, in bits. */
  10. constexpr std::uint8_t kKeyWidth = 32, kTypeWidth = 7, kIndexWidth = 16;
  11. /** The slot type and index are sent unsigned, biased so their absent value is zero. */
  12. constexpr std::uint32_t kTypeBias = 1, kIndexBias = 32768;
  13. /** Schema tags the sense-update objects and their nested arrays declare. */
  14. constexpr std::uint32_t kDevice = 0x80804F47U, kScene = 0x8080626AU;
  15. constexpr std::uint32_t kSquad = 0x80807ECCU, kObjective = 0x80807F04U;
  16. constexpr std::uint32_t kOccupancy = 0x80809531U;
  17. constexpr std::uint32_t kGhostLink = 0x80804D3EU;
  18. constexpr std::uint32_t kObject = 0x8080992EU;
  19. constexpr std::uint32_t kObjectSpawnMask = 0x80809E1BU, kObjectReplies = 0x80809AEAU;
  20. constexpr std::uint32_t kSceneEvents = 0x808094DFU, kSceneList = 0x808094E1U;
  21. constexpr std::uint32_t kSquadCounts = 0x80809491U, kSquadList = 0x80807ECFU;
  22. constexpr std::uint32_t kSquadReals = 0x80807ECDU;
  23. constexpr std::uint32_t kObjectiveBlock = 0x80807F07U, kObjectiveTasks = 0x80807F08U;
  24. constexpr std::uint32_t kCombatant = 0x80807DA2U, kCombatantAtoms = 0x80807F6EU;
  25. constexpr std::uint32_t kCombatantKeyed = 0x80807DA3U, kCombatantLanes = 0x80807DA4U;
  26. /** Type-13 participation root and its nested blocks, in body order. */
  27. constexpr std::uint32_t kPlayer = 0x80804F2FU, kPlayerState = 0x808094E4U;
  28. constexpr std::uint32_t kPlayerScalars = 0x80804F39U, kPlayerTail = 0x80804F35U;
  29. constexpr std::uint32_t kPlayerIdentity = 0x808094DDU, kPlayerKeys = 0x808094DFU;
  30. constexpr std::uint32_t kPlayerPairs = 0x808094E3U, kPlayerFlags = 0x80804F31U;
  31. constexpr std::uint32_t kPlayerOptional = 0x80804F34U;
  32. /** Type-20 damage monitor root: health, shield, echoed revision. */
  33. constexpr std::uint32_t kDamage = 0x80809562U;
  34. /** Registered object replies: the interaction latch and the ownership key. */
  35. constexpr std::uint32_t kInteractionReply = 0x80804FB7U, kOwnershipReply = 0x80809ACCU;
  36. /** Counted lists inside the participation body. */
  37. constexpr std::uint64_t kPlayerScalarCountMaximum = 4, kPlayerKeyCountMaximum = 32;
  38. /** Quantization ceilings the combatant reals carry in their own descriptors. */
  39. constexpr std::uint32_t kSpatialMaximumBits = 0x45000000U, kUnitMaximumBits = 0x3F800000U;
  40. enum class NativeStatus : std::uint8_t { complete, unsupported, unsafeCount, malformed };
  41. /** Bit reader with its own budget, so one object cannot consume the whole packet. */
  42. class Reader final {
  43. public:
  44. Reader(bits::Reader& source, std::size_t budget, std::size_t total) noexcept
  45. : source_(source), left_(budget), total_(total) {}
  46. [[nodiscard]] bool read(std::uint8_t width, std::uint64_t& value) noexcept {
  47. if (width > left_ || !source_.read(width, value)) {
  48. return false;
  49. }
  50. left_ -= width;
  51. return true;
  52. }
  53. [[nodiscard]] bool skip(std::size_t width) noexcept {
  54. if (width > left_ || !source_.skip(width)) {
  55. return false;
  56. }
  57. left_ -= width;
  58. return true;
  59. }
  60. [[nodiscard]] std::size_t left() const noexcept {
  61. return left_;
  62. }
  63. [[nodiscard]] std::size_t position() const noexcept {
  64. return total_ - source_.remaining_bits();
  65. }
  66. private:
  67. bits::Reader& source_;
  68. std::size_t left_{};
  69. std::size_t total_{};
  70. };
  71. /** @param width Field width in bits. @return Low-bit mask of that width. */
  72. [[nodiscard]] constexpr std::uint64_t mask(std::uint8_t width) noexcept {
  73. return width == 64 ? (std::numeric_limits<std::uint64_t>::max)()
  74. : (std::uint64_t{1} << width) - 1;
  75. }
  76. [[nodiscard]] std::int64_t
  77. signed_value(std::uint64_t raw, std::int32_t bias, std::uint8_t storageWidth) noexcept {
  78. const std::uint64_t decoded =
  79. (raw - static_cast<std::uint64_t>(static_cast<std::int64_t>(bias))) & mask(storageWidth);
  80. if (storageWidth == 64) {
  81. return static_cast<std::int64_t>(decoded);
  82. }
  83. const std::uint64_t sign = std::uint64_t{1} << (storageWidth - 1);
  84. return static_cast<std::int64_t>((decoded ^ sign) - sign);
  85. }
  86. /** Collects decoded values into the packet, dropping them once the object's room runs out. */
  87. class Values final {
  88. public:
  89. Values(DecodedPacket& packet, DecodedObject* object) noexcept
  90. : packet_(packet), object_(object) {}
  91. /**
  92. * Records one decoded field value, and marks truncation once storage is full.
  93. * @param schema Owning schema hash.
  94. * @param ordinal Field ordinal inside that schema.
  95. * @param occurrence Flattened repeat index of the field.
  96. * @param at Bit offset the value was read from.
  97. * @param width Wire width in bits.
  98. * @param kind Decoded value type.
  99. * @param raw Unsigned wire value.
  100. * @param signedRaw Signed value after bias removal.
  101. * @param real Real value for real32 fields.
  102. * @param present False when an optional field was absent.
  103. */
  104. void put(std::uint32_t schema,
  105. std::uint16_t ordinal,
  106. std::uint32_t occurrence,
  107. std::uint32_t at,
  108. std::uint8_t width,
  109. ValueKind kind,
  110. std::uint64_t raw,
  111. std::int64_t signedRaw,
  112. float real,
  113. bool present) noexcept {
  114. if (object_ == nullptr) {
  115. return;
  116. }
  117. if (packet_.valueCount == packet_.values.size()) {
  118. packet_.valuesTruncated = true;
  119. return;
  120. }
  121. DecodedValue& value = packet_.values[packet_.valueCount++];
  122. value.schemaRow = schema;
  123. value.fieldRow = ordinal;
  124. value.fieldOrdinal = ordinal;
  125. value.occurrence = occurrence;
  126. value.bitOffset = at;
  127. value.width = width;
  128. value.kind = kind;
  129. value.unsignedValue = raw;
  130. value.signedValue = signedRaw;
  131. value.realValue = real;
  132. value.present = present;
  133. }
  134. private:
  135. DecodedPacket& packet_;
  136. DecodedObject* object_{};
  137. };
  138. /**
  139. * Reads the presence bit that precedes an optional field.
  140. * @param optional False when the field is required, which is always present.
  141. * @param output Receives whether the field follows.
  142. * @return False when the bit does not fit the object's budget.
  143. */
  144. [[nodiscard]] bool present(Reader& reader, bool optional, bool& output) noexcept {
  145. output = true;
  146. if (!optional) {
  147. return true;
  148. }
  149. std::uint64_t raw = 0;
  150. if (!reader.read(1, raw)) {
  151. return false;
  152. }
  153. output = raw != 0;
  154. return true;
  155. }
  156. /**
  157. * Reads one optional or required unsigned field and records it.
  158. * @param optional True when a presence bit precedes the value.
  159. * @return True when the presence bit and any value were complete.
  160. */
  161. [[nodiscard]] bool read_unsigned(Reader& reader,
  162. Values& values,
  163. std::uint32_t schema,
  164. std::uint16_t ordinal,
  165. std::uint8_t width,
  166. bool optional,
  167. std::uint32_t occurrence = 0) noexcept {
  168. const auto at = static_cast<std::uint32_t>(reader.position());
  169. bool exists = true;
  170. if (!present(reader, optional, exists)) {
  171. return false;
  172. }
  173. std::uint64_t raw = 0;
  174. if (exists && !reader.read(width, raw)) {
  175. return false;
  176. }
  177. values.put(schema,
  178. ordinal,
  179. occurrence,
  180. at,
  181. exists ? width : 0,
  182. ValueKind::unsignedInteger,
  183. raw,
  184. 0,
  185. 0.0F,
  186. exists);
  187. return true;
  188. }
  189. /**
  190. * Reads one optional or required signed field and removes its wire bias.
  191. * @param wireWidth Bits on the wire.
  192. * @param storageWidth Bits of the signed host field, used for sign extension.
  193. * @param bias Positive value added by the wire encoder.
  194. * @return True when the presence bit and any value were complete.
  195. */
  196. [[nodiscard]] bool read_signed(Reader& reader,
  197. Values& values,
  198. std::uint32_t schema,
  199. std::uint16_t ordinal,
  200. std::uint8_t wireWidth,
  201. std::uint8_t storageWidth,
  202. std::int32_t bias,
  203. bool optional,
  204. std::uint32_t occurrence = 0) noexcept {
  205. const auto at = static_cast<std::uint32_t>(reader.position());
  206. bool exists = true;
  207. if (!present(reader, optional, exists)) {
  208. return false;
  209. }
  210. std::uint64_t raw = 0;
  211. if (exists && !reader.read(wireWidth, raw)) {
  212. return false;
  213. }
  214. const std::int64_t decoded = exists ? signed_value(raw, bias, storageWidth) : 0;
  215. values.put(schema,
  216. ordinal,
  217. occurrence,
  218. at,
  219. exists ? wireWidth : 0,
  220. ValueKind::signedInteger,
  221. static_cast<std::uint64_t>(decoded),
  222. decoded,
  223. 0.0F,
  224. exists);
  225. return true;
  226. }
  227. /** Reads one boolean field into the value table. */
  228. [[nodiscard]] bool read_bool(Reader& reader,
  229. Values& values,
  230. std::uint32_t schema,
  231. std::uint16_t ordinal,
  232. bool optional,
  233. std::uint32_t occurrence = 0) noexcept {
  234. const auto at = static_cast<std::uint32_t>(reader.position());
  235. bool exists = true;
  236. if (!present(reader, optional, exists)) {
  237. return false;
  238. }
  239. std::uint64_t raw = 0;
  240. if (exists && !reader.read(1, raw)) {
  241. return false;
  242. }
  243. values.put(
  244. schema, ordinal, occurrence, at, exists ? 1 : 0, ValueKind::boolean, raw, 0, 0.0F, exists);
  245. return true;
  246. }
  247. /**
  248. * Expands one quantized real back to its float value.
  249. * @param raw Field bits as read.
  250. * @param width Field width; 32 carries a raw float instead.
  251. * @param maximumBits Quantization ceiling, as float bits.
  252. * @return The decoded value. The lowest and highest levels are exact.
  253. */
  254. [[nodiscard]] float
  255. real_value(std::uint64_t raw, std::uint8_t width, std::uint32_t maximumBits) noexcept {
  256. if (width == 32) {
  257. return std::bit_cast<float>(static_cast<std::uint32_t>(raw));
  258. }
  259. const float maximum = std::bit_cast<float>(maximumBits);
  260. const std::uint64_t levels = std::uint64_t{1} << width;
  261. if (raw == 0) {
  262. return 0.0F;
  263. }
  264. if (raw == levels - 1) {
  265. return maximum;
  266. }
  267. const float step = maximum / static_cast<float>(levels - 2);
  268. return static_cast<float>(raw - 1) * step + step * 0.5F;
  269. }
  270. /**
  271. * Reads one optional or required real field, quantized or raw 32-bit.
  272. * @param maximumBits Quantization range, or zero for a raw 32-bit float.
  273. * @return True when the presence bit and any value were complete.
  274. */
  275. [[nodiscard]] bool read_real(Reader& reader,
  276. Values& values,
  277. std::uint32_t schema,
  278. std::uint16_t ordinal,
  279. std::uint8_t width,
  280. bool optional,
  281. std::uint32_t occurrence = 0,
  282. std::uint32_t maximumBits = 0) noexcept {
  283. const auto at = static_cast<std::uint32_t>(reader.position());
  284. bool exists = true;
  285. if (!present(reader, optional, exists)) {
  286. return false;
  287. }
  288. std::uint64_t raw = 0;
  289. if (exists && !reader.read(width, raw)) {
  290. return false;
  291. }
  292. values.put(schema,
  293. ordinal,
  294. occurrence,
  295. at,
  296. exists ? width : 0,
  297. ValueKind::real32,
  298. raw,
  299. 0,
  300. exists ? real_value(raw, width, maximumBits) : 0.0F,
  301. exists);
  302. return true;
  303. }
  304. /**
  305. * Decodes the three device channels, each a real and a biased signed value.
  306. * @param reader Budget-limited MSB-first reader positioned at the block.
  307. * @param values Receives every decoded field value.
  308. * @return complete, or the status that stopped the block.
  309. */
  310. [[nodiscard]] NativeStatus decode_device(Reader& reader, Values& values) noexcept {
  311. for (std::uint16_t channel = 0; channel < 3; ++channel) {
  312. if (!read_real(reader, values, kDevice, channel * 2, 32, true)
  313. || !read_signed(reader,
  314. values,
  315. kDevice,
  316. channel * 2 + 1,
  317. 32,
  318. 32,
  319. (std::numeric_limits<std::int32_t>::min)(),
  320. true)) {
  321. return NativeStatus::malformed;
  322. }
  323. }
  324. return NativeStatus::complete;
  325. }
  326. /**
  327. * Decodes the occupancy block: two booleans then its signed counters.
  328. * @param reader Budget-limited MSB-first reader positioned at the block.
  329. * @param values Receives every decoded field value.
  330. * @return complete, or the status that stopped the block.
  331. */
  332. [[nodiscard]] NativeStatus decode_occupancy(Reader& reader, Values& values) noexcept {
  333. return read_bool(reader, values, kOccupancy, 0, false)
  334. && read_bool(reader, values, kOccupancy, 1, false)
  335. && read_signed(reader,
  336. values,
  337. kOccupancy,
  338. 2,
  339. 32,
  340. 32,
  341. (std::numeric_limits<std::int32_t>::min)(),
  342. false)
  343. && read_signed(reader,
  344. values,
  345. kOccupancy,
  346. 3,
  347. 32,
  348. 32,
  349. (std::numeric_limits<std::int32_t>::min)(),
  350. false)
  351. ? NativeStatus::complete
  352. : NativeStatus::malformed;
  353. }
  354. /**
  355. * Decodes the scene block and its authored event and entry lists.
  356. * @param reader Budget-limited MSB-first reader positioned at the block.
  357. * @param values Receives every decoded field value.
  358. * @return complete, or the status that stopped the block.
  359. */
  360. [[nodiscard]] NativeStatus decode_scene(Reader& reader, Values& values) noexcept {
  361. if (!read_signed(
  362. reader, values, kScene, 0, 32, 32, (std::numeric_limits<std::int32_t>::min)(), false)
  363. || !read_bool(reader, values, kScene, 1, false)
  364. || !read_signed(reader, values, kScene, 2, 31, 32, 0, true)
  365. || !read_signed(reader, values, kScene, 3, 2, 8, 1, false)) {
  366. return NativeStatus::malformed;
  367. }
  368. std::uint64_t count = 0;
  369. const auto at = static_cast<std::uint32_t>(reader.position());
  370. if (!reader.read(6, count)) {
  371. return NativeStatus::malformed;
  372. }
  373. if (count > 32) {
  374. return NativeStatus::unsafeCount;
  375. }
  376. values.put(kSceneList, 0, 0, at, 6, ValueKind::unsignedInteger, count, 0, 0.0F, true);
  377. for (std::uint32_t index = 0; index < count; ++index) {
  378. if (!read_unsigned(reader, values, kSceneEvents, 0, 32, false, index)) {
  379. return NativeStatus::malformed;
  380. }
  381. }
  382. return NativeStatus::complete;
  383. }
  384. /**
  385. * Decodes the squad block, its counts, member list and real values.
  386. * @param reader Budget-limited MSB-first reader positioned at the block.
  387. * @param values Receives every decoded field value.
  388. * @return complete, or the status that stopped the block.
  389. */
  390. [[nodiscard]] NativeStatus decode_squad(Reader& reader, Values& values) noexcept {
  391. if (!read_signed(reader, values, kSquad, 0, 31, 32, 0, true)
  392. || !read_signed(reader, values, kSquad, 1, 31, 32, 0, true)
  393. || !read_signed(reader, values, kSquad, 2, 31, 32, 0, true)
  394. || !read_signed(reader, values, kSquad, 3, 6, 32, 0, true)
  395. || !read_real(reader, values, kSquad, 4, 7, true, 0, 1157562368U)
  396. || !read_signed(reader, values, kSquad, 5, 31, 32, 0, true)
  397. || !read_signed(reader, values, kSquad, 6, 2, 8, 1, false)
  398. || !read_signed(reader, values, kSquad, 7, 3, 8, 1, false)
  399. || !read_bool(reader, values, kSquad, 8, false)
  400. || !read_bool(reader, values, kSquad, 9, false)
  401. || !read_bool(reader, values, kSquad, 10, false)) {
  402. return NativeStatus::malformed;
  403. }
  404. bool exists = false;
  405. if (!present(reader, true, exists)) {
  406. return NativeStatus::malformed;
  407. }
  408. if (exists) {
  409. std::uint64_t count = 0;
  410. const auto at = static_cast<std::uint32_t>(reader.position());
  411. if (!reader.read(4, count)) {
  412. return NativeStatus::malformed;
  413. }
  414. if (count > 8) {
  415. return NativeStatus::unsafeCount;
  416. }
  417. values.put(kSquadList, 0, 0, at, 4, ValueKind::unsignedInteger, count, 0, 0.0F, true);
  418. for (std::uint32_t index = 0; index < count; ++index) {
  419. if (!read_signed(reader,
  420. values,
  421. kSquadCounts,
  422. 0,
  423. 32,
  424. 32,
  425. (std::numeric_limits<std::int32_t>::min)(),
  426. false,
  427. index)) {
  428. return NativeStatus::malformed;
  429. }
  430. }
  431. }
  432. if (!present(reader, true, exists)) {
  433. return NativeStatus::malformed;
  434. }
  435. if (exists) {
  436. for (std::uint32_t index = 0; index < 24; ++index) {
  437. if (!read_real(reader, values, kSquadReals, 0, 7, true, index, 1157562368U)) {
  438. return NativeStatus::malformed;
  439. }
  440. }
  441. }
  442. return NativeStatus::complete;
  443. }
  444. /**
  445. * Decodes the objective block and its task list.
  446. * @param reader Budget-limited MSB-first reader positioned at the block.
  447. * @param values Receives every decoded field value.
  448. * @return complete, or the status that stopped the block.
  449. */
  450. [[nodiscard]] NativeStatus decode_objective(Reader& reader, Values& values) noexcept {
  451. bool exists = false;
  452. if (!present(reader, true, exists)) {
  453. return NativeStatus::malformed;
  454. }
  455. if (exists) {
  456. for (std::uint32_t block = 0; block < 24; ++block) {
  457. if (!read_signed(reader, values, kObjectiveBlock, 0, 7, 8, 0, true, block)
  458. || !read_unsigned(reader, values, kObjectiveBlock, 1, 1, false, block)) {
  459. return NativeStatus::malformed;
  460. }
  461. bool tasks = false;
  462. if (!present(reader, true, tasks)) {
  463. return NativeStatus::malformed;
  464. }
  465. if (!tasks) {
  466. continue;
  467. }
  468. for (std::uint32_t task = 0; task < 24; ++task) {
  469. if (!read_signed(
  470. reader, values, kObjectiveTasks, 0, 7, 8, 0, true, block * 24 + task)) {
  471. return NativeStatus::malformed;
  472. }
  473. }
  474. }
  475. }
  476. return read_signed(reader, values, kObjective, 1, 31, 32, 0, true)
  477. && read_unsigned(reader, values, kObjective, 2, 32, true)
  478. ? NativeStatus::complete
  479. : NativeStatus::malformed;
  480. }
  481. /**
  482. * Decodes one object block, its spawn mask and its reply list.
  483. * @param reader Budget-limited MSB-first reader positioned at the block.
  484. * @param values Receives every decoded field value.
  485. * @return complete, or the status that stopped the block.
  486. */
  487. [[nodiscard]] NativeStatus decode_object(Reader& reader, Values& values) noexcept {
  488. if (!read_signed(
  489. reader, values, kObject, 0, 32, 32, (std::numeric_limits<std::int32_t>::min)(), false)
  490. || !read_bool(reader, values, kObject, 1, false)
  491. || !read_bool(reader, values, kObject, 2, false)
  492. || !read_signed(reader,
  493. values,
  494. kObject,
  495. 3,
  496. 32,
  497. 32,
  498. (std::numeric_limits<std::int32_t>::min)(),
  499. false)) {
  500. return NativeStatus::malformed;
  501. }
  502. for (std::uint32_t index = 0; index < 2; ++index) {
  503. if (!read_unsigned(reader, values, kObjectSpawnMask, 0, 32, false, index)) {
  504. return NativeStatus::malformed;
  505. }
  506. }
  507. std::uint64_t count = 0;
  508. const auto at = static_cast<std::uint32_t>(reader.position());
  509. if (!reader.read(2, count)) {
  510. return NativeStatus::malformed;
  511. }
  512. values.put(kObjectReplies, 0, 0, at, 2, ValueKind::unsignedInteger, count, 0, 0.0F, true);
  513. for (std::uint32_t index = 0; index < count; ++index) {
  514. std::uint64_t exists = 0, schema = 0;
  515. if (!reader.read(1, exists)) return NativeStatus::malformed;
  516. if (!exists) continue;
  517. if (!reader.read(32, schema)) return NativeStatus::malformed;
  518. if (schema == kInteractionReply) {
  519. // The interaction latch and the revision that set it.
  520. if (!read_bool(reader, values, kInteractionReply, 0, false, index)
  521. || !read_signed(reader, values, kInteractionReply, 1, 32, 32,
  522. (std::numeric_limits<std::int32_t>::min)(), false, index))
  523. return NativeStatus::malformed;
  524. } else if (schema == kOwnershipReply) {
  525. // The owner key is always written, zero when nobody holds the object.
  526. if (!read_bool(reader, values, kOwnershipReply, 0, false, index)
  527. || !read_unsigned(reader, values, kOwnershipReply, 1, 64, false, index))
  528. return NativeStatus::malformed;
  529. } else return NativeStatus::unsupported;
  530. }
  531. return NativeStatus::complete;
  532. }
  533. /**
  534. * Decodes the combatant block: the accepted spawn and event generations, the atom runner's lane
  535. * cursor and accepted program generation, the eight keyed-lane generations with their result bits,
  536. * then the dependency subscription and the two actor latches.
  537. * @param reader Budget-limited MSB-first reader positioned at the block.
  538. * @param values Receives every decoded field value.
  539. * @return complete, or the status that stopped the block.
  540. */
  541. [[nodiscard]] NativeStatus decode_combatant(Reader& reader, Values& values) noexcept {
  542. if (!read_signed(reader, values, kCombatant, 0, 31, 32, 0, true)
  543. || !read_real(reader, values, kCombatant, 1, 9, true, 0, kSpatialMaximumBits)
  544. || !read_signed(reader, values, kCombatant, 2, 31, 32, 0, true)) {
  545. return NativeStatus::malformed;
  546. }
  547. bool exists = false;
  548. if (!present(reader, true, exists)) {
  549. return NativeStatus::malformed;
  550. }
  551. if (exists
  552. && (!read_signed(reader, values, kCombatantAtoms, 0, 6, 32, 0, true)
  553. || !read_signed(reader, values, kCombatantAtoms, 1, 31, 32, 0, true)
  554. || !read_signed(reader, values, kCombatantAtoms, 2, 31, 32, 0, true)
  555. || !read_bool(reader, values, kCombatantAtoms, 3, false))) {
  556. return NativeStatus::malformed;
  557. }
  558. if (!present(reader, true, exists)) {
  559. return NativeStatus::malformed;
  560. }
  561. if (exists) {
  562. bool lanes = false;
  563. if (!present(reader, true, lanes)) {
  564. return NativeStatus::malformed;
  565. }
  566. for (std::uint32_t index = 0; lanes && index < 8; ++index) {
  567. if (!read_signed(reader, values, kCombatantLanes, 0, 31, 32, 0, true, index)) {
  568. return NativeStatus::malformed;
  569. }
  570. }
  571. if (!read_unsigned(reader, values, kCombatantKeyed, 1, 32, true)) {
  572. return NativeStatus::malformed;
  573. }
  574. }
  575. if (!read_signed(reader, values, kCombatant, 5, 31, 32, 0, true)
  576. || !read_signed(reader, values, kCombatant, 6, 2, 8, 1, false)
  577. || !read_signed(reader, values, kCombatant, 7, 31, 32, 0, true)
  578. || !read_real(reader, values, kCombatant, 8, 7, true, 0, kUnitMaximumBits)
  579. || !read_real(reader, values, kCombatant, 9, 7, true, 0, kUnitMaximumBits)
  580. || !read_bool(reader, values, kCombatant, 10, false)
  581. || !read_bool(reader, values, kCombatant, 11, false)) {
  582. return NativeStatus::malformed;
  583. }
  584. return NativeStatus::complete;
  585. }
  586. /**
  587. * Decodes the type-13 participation body. The whole body is read before its Ghost flag counts,
  588. * because a player mid-load publishes a body with the flag but without a settled actor.
  589. */
  590. [[nodiscard]] NativeStatus decode_player(Reader& reader, Values& values) noexcept {
  591. constexpr auto signedBias = (std::numeric_limits<std::int32_t>::min)();
  592. if (!read_signed(reader, values, kPlayerState, 0, 32, 32, signedBias, true)
  593. || !read_unsigned(reader, values, kPlayerState, 1, 32, true)) {
  594. return NativeStatus::malformed;
  595. }
  596. for (std::uint16_t ordinal = 2; ordinal <= 5; ++ordinal) {
  597. if (!read_bool(reader, values, kPlayerState, ordinal, false)) return NativeStatus::malformed;
  598. }
  599. if (!read_signed(reader, values, kPlayerState, 6, 3, 8, 1, false)
  600. || !read_signed(reader, values, kPlayerState, 7, 2, 8, 1, false)) {
  601. return NativeStatus::malformed;
  602. }
  603. std::uint64_t count = 0;
  604. if (!reader.read(3, count)) return NativeStatus::malformed;
  605. if (count > kPlayerScalarCountMaximum) return NativeStatus::unsafeCount;
  606. for (unsigned index = 0; index < count; ++index) {
  607. if (!read_unsigned(reader, values, kPlayerScalars, 0, 32, false, index)
  608. || !read_real(reader, values, kPlayerScalars, 1, 32, false, index)) {
  609. return NativeStatus::malformed;
  610. }
  611. }
  612. if (!read_real(reader, values, kPlayerTail, 1, 32, false)
  613. || !read_signed(reader, values, kPlayerTail, 2, 5, 32, 1, false)
  614. || !read_signed(reader, values, kPlayerTail, 3, 32, 32, signedBias, true)) {
  615. return NativeStatus::malformed;
  616. }
  617. for (std::uint16_t ordinal = 4; ordinal <= 6; ++ordinal) {
  618. if (!read_bool(reader, values, kPlayerTail, ordinal, false)) return NativeStatus::malformed;
  619. }
  620. if (!read_unsigned(reader, values, kPlayerIdentity, 0, 64, true)
  621. || !read_unsigned(reader, values, kPlayerIdentity, 1, 5, false)
  622. || !read_signed(reader, values, kPlayerIdentity, 2, 6, 8, 3, false)) {
  623. return NativeStatus::malformed;
  624. }
  625. if (!reader.read(6, count)) return NativeStatus::malformed;
  626. if (count > kPlayerKeyCountMaximum) return NativeStatus::unsafeCount;
  627. for (unsigned index = 0; index < count; ++index) {
  628. if (!read_unsigned(reader, values, kPlayerKeys, 0, 32, false, index)) {
  629. return NativeStatus::malformed;
  630. }
  631. }
  632. if (!reader.read(6, count)) return NativeStatus::malformed;
  633. if (count > kPlayerKeyCountMaximum) return NativeStatus::unsafeCount;
  634. for (unsigned index = 0; index < count; ++index) {
  635. if (!read_unsigned(reader, values, kPlayerPairs, 0, 32, true, index)
  636. || !read_unsigned(reader, values, kPlayerPairs, 1, 64, true, index)) {
  637. return NativeStatus::malformed;
  638. }
  639. }
  640. if (!read_bool(reader, values, kPlayerFlags, 0, false)
  641. || !read_unsigned(reader, values, kPlayerFlags, 1, 4, false)
  642. || !read_unsigned(reader, values, kPlayerFlags, 2, 16, true)
  643. || !read_unsigned(reader, values, kPlayerFlags, 3, 16, true)) {
  644. return NativeStatus::malformed;
  645. }
  646. bool exists = false;
  647. if (!present(reader, true, exists)) return NativeStatus::malformed;
  648. if (exists && !read_unsigned(reader, values, kPlayerOptional, 0, 32, false)) {
  649. return NativeStatus::malformed;
  650. }
  651. return read_bool(reader, values, kPlayerFlags, 5, false)
  652. && read_signed(reader, values, kPlayerFlags, 6, 8, 8, 128, false)
  653. && read_signed(reader, values, kPlayer, 4, 32, 32, signedBias, false)
  654. ? NativeStatus::complete
  655. : NativeStatus::malformed;
  656. }
  657. /** Decodes one root body of the given schema; the status names how far it got. */
  658. [[nodiscard]] NativeStatus
  659. decode_body(std::uint32_t schema, Reader& reader, Values& values) noexcept {
  660. std::uint64_t root = 0;
  661. if (!reader.read(1, root)) {
  662. return NativeStatus::malformed;
  663. }
  664. if (root == 0) {
  665. return NativeStatus::complete;
  666. }
  667. switch (schema) {
  668. case kPlayer:
  669. return decode_player(reader, values);
  670. case kDamage:
  671. // Three mandatory fields: health, shield, then the echoed Auth revision.
  672. return read_real(reader, values, schema, 0, 32, false)
  673. && read_real(reader, values, schema, 1, 32, false)
  674. && read_signed(reader, values, schema, 2, 32, 32,
  675. (std::numeric_limits<std::int32_t>::min)(), false)
  676. ? NativeStatus::complete : NativeStatus::malformed;
  677. case kGhostLink:
  678. // Three mandatory fields: active, elapsed over duration, accepted Auth generation.
  679. return read_bool(reader, values, kGhostLink, 0, false)
  680. && read_real(reader, values, kGhostLink, 1, 32, false)
  681. && read_signed(reader, values, kGhostLink, 2, 32, 32,
  682. (std::numeric_limits<std::int32_t>::min)(), false)
  683. ? NativeStatus::complete : NativeStatus::malformed;
  684. case kDevice:
  685. return decode_device(reader, values);
  686. case kScene:
  687. return decode_scene(reader, values);
  688. case kSquad:
  689. return decode_squad(reader, values);
  690. case kObjective:
  691. return decode_objective(reader, values);
  692. case kOccupancy:
  693. return decode_occupancy(reader, values);
  694. case kObject:
  695. return decode_object(reader, values);
  696. case kCombatant:
  697. return decode_combatant(reader, values);
  698. default:
  699. return NativeStatus::unsupported;
  700. }
  701. }
  702. [[nodiscard]] bool skip_group(Reader& reader) noexcept {
  703. if (reader.left() == 0 || !reader.skip(reader.left() - 1)) {
  704. return false;
  705. }
  706. std::uint64_t end = 0;
  707. return reader.read(1, end) && end == 0 && reader.left() == 0;
  708. }
  709. void finish(SenseUpdate& update,
  710. bits::Reader& reader,
  711. std::size_t total,
  712. DecodeStatus status,
  713. std::size_t& consumed) noexcept {
  714. update.decoded.status = status;
  715. update.decoded.bitsConsumed = total - reader.remaining_bits();
  716. update.decoded.bitsRemaining = reader.remaining_bits();
  717. consumed = update.decoded.bitsConsumed;
  718. }
  719. } // namespace
  720. /**
  721. * Decodes one sense update: its epoch pair, then each present sensor block.
  722. * @param input Complete sense-update payload.
  723. * @param resolver Native layout lookup for object schemas.
  724. * @param update Cleared first. Receives the epoch, the blocks and a decode status.
  725. * @param consumed Receives the bits read.
  726. * @return True when the epoch prefix and the root marker were valid.
  727. */
  728. bool decode_sense_update(std::span<const std::byte> input,
  729. const Resolver& resolver,
  730. SenseUpdate& update,
  731. std::size_t& consumed) noexcept {
  732. update = {};
  733. consumed = 0;
  734. if (input.size() > kOuterByteCapacity) {
  735. return false;
  736. }
  737. const std::size_t total = input.size() * encoding::kBitsPerByte;
  738. bits::Reader reader(input);
  739. std::uint64_t literal = 0, root = 0;
  740. if (!reader.read(kEpochFieldWidth, update.epoch.first)
  741. || !reader.read(kEpochFieldWidth, update.epoch.second) || !reader.read(1, literal)
  742. || literal != 0 || !reader.read(1, root)) {
  743. finish(update, reader, total, DecodeStatus::malformed, consumed);
  744. return false;
  745. }
  746. update.tailBits = static_cast<std::uint32_t>(reader.remaining_bits() + 1);
  747. if (root != 0) {
  748. finish(update, reader, total, DecodeStatus::schemaUnavailable, consumed);
  749. return true;
  750. }
  751. bool partial = false;
  752. for (;;) {
  753. std::uint64_t groupPresent = 0;
  754. if (!reader.read(1, groupPresent)) {
  755. finish(update, reader, total, DecodeStatus::malformed, consumed);
  756. return false;
  757. }
  758. if (groupPresent == 0) {
  759. break;
  760. }
  761. std::uint64_t groupKey = 0, groupBits = 0;
  762. if (!reader.read(32, groupKey) || !reader.read(32, groupBits)
  763. || groupBits > kGroupByteCapacity * 8 || groupBits > reader.remaining_bits()) {
  764. finish(update, reader, total, DecodeStatus::malformed, consumed);
  765. return false;
  766. }
  767. ++update.decoded.groupsSeen;
  768. GroupTarget group{};
  769. const TargetStatus groupStatus =
  770. resolver.resolveGroup == nullptr
  771. ? TargetStatus::targetUnavailable
  772. : resolver.resolveGroup(
  773. resolver.context, static_cast<std::uint32_t>(groupKey), group);
  774. Reader body(reader, static_cast<std::size_t>(groupBits), total);
  775. if (groupStatus != TargetStatus::resolved) {
  776. if (!skip_group(body)) {
  777. finish(update, reader, total, DecodeStatus::malformed, consumed);
  778. return false;
  779. }
  780. ++update.decoded.groupsSkipped;
  781. partial = true;
  782. continue;
  783. }
  784. bool skipped = false, hasObject = false;
  785. while (!skipped) {
  786. std::uint64_t objectPresent = 0;
  787. if (!body.read(1, objectPresent)) {
  788. finish(update, reader, total, DecodeStatus::malformed, consumed);
  789. return false;
  790. }
  791. if (objectPresent == 0) {
  792. if (!hasObject || body.left() != 0) {
  793. finish(update, reader, total, DecodeStatus::malformed, consumed);
  794. return false;
  795. }
  796. ++update.decoded.groupsDecoded;
  797. break;
  798. }
  799. hasObject = true;
  800. ++update.decoded.objectsSeen;
  801. std::uint64_t objectKey = 0, typeRaw = 0, indexRaw = 0;
  802. if (!body.read(kKeyWidth, objectKey) || objectKey != groupKey
  803. || !body.read(kTypeWidth, typeRaw) || typeRaw < kTypeBias
  804. || !body.read(kIndexWidth, indexRaw) || indexRaw < kIndexBias) {
  805. finish(update, reader, total, DecodeStatus::malformed, consumed);
  806. return false;
  807. }
  808. const auto type = static_cast<std::uint8_t>(typeRaw - kTypeBias);
  809. const auto index = static_cast<std::uint16_t>(indexRaw - kIndexBias);
  810. if (!update.hasFirstObject) {
  811. update.firstGroupBits = static_cast<std::uint32_t>(groupBits);
  812. update.firstRegistryKey = static_cast<std::uint32_t>(groupKey);
  813. update.firstSlotType = type;
  814. update.firstSlotIndex = index;
  815. update.hasFirstObject = true;
  816. }
  817. DecodedObject* retained = nullptr;
  818. if (update.decoded.objectCount < update.decoded.objects.size()) {
  819. retained = &update.decoded.objects[update.decoded.objectCount++];
  820. retained->registryKey = static_cast<std::uint32_t>(groupKey);
  821. retained->objectTag = group.objectTag;
  822. retained->objectRow = group.objectRow;
  823. retained->slotType = type;
  824. retained->slotIndex = index;
  825. retained->firstValue = static_cast<std::uint32_t>(update.decoded.valueCount);
  826. } else {
  827. update.decoded.objectsTruncated = true;
  828. }
  829. SlotTarget slot{};
  830. const TargetStatus slotStatus =
  831. resolver.resolveSlot == nullptr
  832. ? TargetStatus::targetUnavailable
  833. : resolver.resolveSlot(resolver.context, group, type, index, slot);
  834. if (retained != nullptr) {
  835. retained->slotRow = slot.slotRow;
  836. retained->senseSchema = slot.senseSchema;
  837. retained->schemaRow = slot.senseSchema;
  838. }
  839. if (slotStatus != TargetStatus::resolved) {
  840. if (retained != nullptr) {
  841. retained->status = slotStatus == TargetStatus::schemaUnavailable
  842. ? ObjectStatus::schemaUnavailable
  843. : ObjectStatus::targetUnavailable;
  844. }
  845. if (!skip_group(body)) {
  846. finish(update, reader, total, DecodeStatus::malformed, consumed);
  847. return false;
  848. }
  849. skipped = true;
  850. partial = true;
  851. ++update.decoded.groupsSkipped;
  852. continue;
  853. }
  854. const std::size_t start = body.position();
  855. Values values(update.decoded, retained);
  856. const NativeStatus status = decode_body(slot.senseSchema, body, values);
  857. if (retained != nullptr) {
  858. retained->deltaBits = static_cast<std::uint32_t>(body.position() - start);
  859. retained->valueCount =
  860. static_cast<std::uint32_t>(update.decoded.valueCount - retained->firstValue);
  861. retained->status = status == NativeStatus::complete ? ObjectStatus::decoded
  862. : status == NativeStatus::unsafeCount ? ObjectStatus::unsafeCount
  863. : status == NativeStatus::unsupported
  864. ? ObjectStatus::unsupportedField
  865. : ObjectStatus::malformed;
  866. }
  867. if (status == NativeStatus::malformed) {
  868. finish(update, reader, total, DecodeStatus::malformed, consumed);
  869. return false;
  870. }
  871. if (status != NativeStatus::complete) {
  872. if (!skip_group(body)) {
  873. finish(update, reader, total, DecodeStatus::malformed, consumed);
  874. return false;
  875. }
  876. skipped = true;
  877. partial = true;
  878. ++update.decoded.groupsSkipped;
  879. continue;
  880. }
  881. std::uint64_t generation = 0;
  882. if (!body.read(32, generation)) {
  883. finish(update, reader, total, DecodeStatus::malformed, consumed);
  884. return false;
  885. }
  886. if (retained != nullptr) {
  887. retained->generationPlusOne = static_cast<std::uint32_t>(generation);
  888. retained->hasGeneration = true;
  889. retained->status = ObjectStatus::decoded;
  890. }
  891. ++update.decoded.objectsDecoded;
  892. }
  893. }
  894. std::uint64_t tail = 0;
  895. if (!reader.read(1, tail) || tail != 0 || reader.remaining_bits() > 7) {
  896. finish(update, reader, total, DecodeStatus::malformed, consumed);
  897. return false;
  898. }
  899. update.decoded.paddingBits = static_cast<std::uint8_t>(reader.remaining_bits());
  900. std::uint64_t padding = 0;
  901. if (!reader.read(update.decoded.paddingBits, padding) || padding != 0) {
  902. finish(update, reader, total, DecodeStatus::malformed, consumed);
  903. return false;
  904. }
  905. finish(
  906. update, reader, total, partial ? DecodeStatus::partial : DecodeStatus::complete, consumed);
  907. return true;
  908. }
  909. /** @return Stable log spelling for one packet decode status. */
  910. const char* decode_status_name(DecodeStatus status) noexcept {
  911. switch (status) {
  912. case DecodeStatus::complete:
  913. return "complete";
  914. case DecodeStatus::partial:
  915. return "partial";
  916. case DecodeStatus::schemaUnavailable:
  917. return "unsupported_native_layout";
  918. case DecodeStatus::malformed:
  919. return "malformed";
  920. }
  921. return "unknown";
  922. }
  923. /** @return Stable log spelling for one object decode status. */
  924. const char* object_status_name(ObjectStatus status) noexcept {
  925. switch (status) {
  926. case ObjectStatus::decoded:
  927. return "decoded";
  928. case ObjectStatus::targetUnavailable:
  929. return "target_unavailable";
  930. case ObjectStatus::schemaUnavailable:
  931. case ObjectStatus::unsupportedField:
  932. return "unsupported_native_layout";
  933. case ObjectStatus::unsafeCount:
  934. return "unsafe_count";
  935. case ObjectStatus::malformed:
  936. return "malformed";
  937. }
  938. return "unknown";
  939. }
  940. } // namespace sunrise::middleware::bap::activity_message::sense_update