@moqtap/codec 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +100 -99
  3. package/dist/{chunk-RZHAPEXO.js → chunk-2A57DRXV.js} +36 -10
  4. package/dist/{chunk-73MWUKSJ.js → chunk-2UTVXWFF.js} +190 -102
  5. package/dist/{chunk-JTVCOMBI.cjs → chunk-3XKO6PCR.cjs} +290 -183
  6. package/dist/{chunk-ACQ4CUJP.cjs → chunk-4BDEU3D4.cjs} +237 -158
  7. package/dist/{chunk-4N4INRE7.cjs → chunk-4HBKHNU2.cjs} +144 -110
  8. package/dist/{chunk-2ZT6CVSE.js → chunk-4IVZZOY3.js} +269 -162
  9. package/dist/{chunk-GLBQDG4L.cjs → chunk-5O764MBD.cjs} +508 -117
  10. package/dist/chunk-7KBAWOBA.js +1212 -0
  11. package/dist/{chunk-JSQM2MG3.js → chunk-7QOPNSDF.js} +44 -12
  12. package/dist/{chunk-SYHW3FLI.cjs → chunk-7RE6KSIY.cjs} +28 -8
  13. package/dist/{chunk-YG5KJESI.js → chunk-AY6IAHUM.js} +28 -8
  14. package/dist/{chunk-EFM5T7OM.js → chunk-BLQDWOSG.js} +36 -10
  15. package/dist/{chunk-UYXTY6ZQ.cjs → chunk-E65QKRSN.cjs} +20 -12
  16. package/dist/{chunk-BISI45MN.cjs → chunk-EAHE3IOG.cjs} +44 -12
  17. package/dist/{chunk-PZBPH2D7.js → chunk-GCBFHZW6.js} +216 -137
  18. package/dist/{chunk-GXEW4COZ.cjs → chunk-H5NSL4MO.cjs} +36 -10
  19. package/dist/chunk-HZHSO7EW.cjs +1212 -0
  20. package/dist/{chunk-KZCYQ7ED.cjs → chunk-IILNSDEQ.cjs} +69 -41
  21. package/dist/{chunk-4XYGE53S.cjs → chunk-J3XCPBW3.cjs} +36 -10
  22. package/dist/{chunk-6AEHWULA.cjs → chunk-JKOEJZ5B.cjs} +28 -8
  23. package/dist/{chunk-RUPCJTC3.cjs → chunk-JL3NEW3O.cjs} +23 -1
  24. package/dist/{chunk-G7GI7LJA.js → chunk-LORZMJJB.js} +36 -10
  25. package/dist/{chunk-DUBCL3WF.cjs → chunk-LV5C6MEC.cjs} +36 -10
  26. package/dist/{chunk-ENURAVHI.cjs → chunk-MYXAD5JC.cjs} +44 -12
  27. package/dist/{chunk-FXZ2MYKJ.js → chunk-MZ7HUCGJ.js} +20 -12
  28. package/dist/{chunk-S74DWJE2.cjs → chunk-OKG2HT25.cjs} +277 -88
  29. package/dist/{chunk-BGWGVINJ.cjs → chunk-PKEOQSSZ.cjs} +144 -110
  30. package/dist/{chunk-2GODRVT5.js → chunk-Q46ZURKX.js} +325 -48
  31. package/dist/{chunk-UR6JKS56.js → chunk-Q7IGWV3P.js} +41 -9
  32. package/dist/{chunk-XSNX2IUJ.js → chunk-RW4UG7CN.js} +121 -87
  33. package/dist/{chunk-DWK5ZQZ4.js → chunk-RZTLQAKF.js} +28 -8
  34. package/dist/{chunk-UNS34PTA.cjs → chunk-S6IPIN66.cjs} +44 -12
  35. package/dist/{chunk-YIG2C3LF.cjs → chunk-SDWRXXOO.cjs} +214 -126
  36. package/dist/{chunk-CEH7ESNC.js → chunk-SHMA4PBY.js} +121 -87
  37. package/dist/{chunk-MC7W6PMI.js → chunk-U3ZVLT5L.js} +483 -135
  38. package/dist/{chunk-VJUUZ4W2.cjs → chunk-UJU63EFY.cjs} +374 -97
  39. package/dist/{chunk-7L43FE6P.js → chunk-VOU7PNHI.js} +23 -1
  40. package/dist/{chunk-E6E3NQYU.js → chunk-WRHGCVYN.js} +44 -12
  41. package/dist/{chunk-FPISPJ5N.cjs → chunk-XNWYLVGU.cjs} +529 -181
  42. package/dist/{chunk-U3IPZYPX.js → chunk-XS77RBY7.js} +228 -39
  43. package/dist/{chunk-JGG7CMSZ.cjs → chunk-XZE5R57R.cjs} +144 -110
  44. package/dist/{chunk-77MNXX3M.js → chunk-Y6KCSM3V.js} +121 -87
  45. package/dist/{chunk-TLYNOOQP.cjs → chunk-YTPZZI2M.cjs} +41 -9
  46. package/dist/{chunk-7DUBLRXC.js → chunk-YWRCSQBA.js} +44 -12
  47. package/dist/{chunk-MRJWLGYH.js → chunk-Z3VKP3PJ.js} +69 -41
  48. package/dist/{chunk-E6P74GDT.js → chunk-Z6U26IRI.js} +464 -73
  49. package/dist/{codec-FvGCxIhr.d.ts → codec-25u4_1HS.d.ts} +4 -4
  50. package/dist/{codec-DRcsBCsb.d.ts → codec-3Ppy_5Gd.d.ts} +4 -4
  51. package/dist/{codec-BdVMRMOI.d.ts → codec-BB0U8MF2.d.cts} +4 -4
  52. package/dist/{codec-B2cH-f5V.d.cts → codec-BHHfBTnV.d.ts} +4 -4
  53. package/dist/{codec-B5K73Bdj.d.ts → codec-BN6jk0Td.d.cts} +4 -4
  54. package/dist/{codec-R8GrCPt2.d.ts → codec-BU0gaSZm.d.ts} +4 -4
  55. package/dist/{codec-Bq-tLtfP.d.ts → codec-C-Yk2RNa.d.ts} +4 -4
  56. package/dist/codec-CFWQY9Lj.d.cts +18 -0
  57. package/dist/{codec-CPlK3Pi5.d.ts → codec-COy4uuPO.d.cts} +4 -4
  58. package/dist/codec-CewFCsEy.d.ts +18 -0
  59. package/dist/{codec-KXHvXZVb.d.cts → codec-Ck7ZwFF1.d.cts} +4 -4
  60. package/dist/{codec-DZhZSIii.d.cts → codec-D2QVSH9D.d.ts} +4 -4
  61. package/dist/{codec-BwFgpeQu.d.ts → codec-DDUBJGn0.d.cts} +4 -4
  62. package/dist/{codec-BFeliJFc.d.ts → codec-DNfml-se.d.ts} +4 -4
  63. package/dist/{codec-C4n1PS09.d.cts → codec-DoOGjjDq.d.cts} +4 -4
  64. package/dist/{codec-Bap882Fh.d.cts → codec-J7ekOSMc.d.ts} +4 -4
  65. package/dist/{codec-SKBeHQk7.d.ts → codec-R9TJCq-E.d.cts} +4 -4
  66. package/dist/{codec-DNUIgLqc.d.cts → codec-ZwV-Njt6.d.ts} +4 -4
  67. package/dist/{codec-HgBgHkFI.d.cts → codec-j819z_hL.d.cts} +4 -4
  68. package/dist/{codec-DY4QH364.d.cts → codec-w8z2j_uo.d.cts} +4 -4
  69. package/dist/{codec-CPvPq0sb.d.cts → codec-wtt6WF1K.d.ts} +4 -4
  70. package/dist/{codec-BUMjz0J4.d.cts → codec-z6_2PSzi.d.cts} +4 -4
  71. package/dist/{draft7-session.cjs → draft07-session.cjs} +2 -2
  72. package/dist/draft07-session.d.cts +8 -0
  73. package/dist/draft07-session.d.ts +8 -0
  74. package/dist/{draft7-session.js → draft07-session.js} +1 -1
  75. package/dist/draft07.cjs +129 -0
  76. package/dist/draft07.d.cts +67 -0
  77. package/dist/draft07.d.ts +67 -0
  78. package/dist/draft07.js +129 -0
  79. package/dist/draft08-session.cjs +6 -0
  80. package/dist/draft08-session.d.cts +8 -0
  81. package/dist/draft08-session.d.ts +8 -0
  82. package/dist/{draft8-session.js → draft08-session.js} +1 -1
  83. package/dist/draft08.cjs +119 -0
  84. package/dist/{draft8.d.cts → draft08.d.cts} +15 -13
  85. package/dist/{draft8.d.ts → draft08.d.ts} +15 -13
  86. package/dist/{draft8.js → draft08.js} +7 -4
  87. package/dist/draft09-session.cjs +6 -0
  88. package/dist/draft09-session.d.cts +8 -0
  89. package/dist/draft09-session.d.ts +8 -0
  90. package/dist/{draft9-session.js → draft09-session.js} +1 -1
  91. package/dist/draft09.cjs +119 -0
  92. package/dist/{draft9.d.cts → draft09.d.cts} +15 -13
  93. package/dist/{draft9.d.ts → draft09.d.ts} +15 -13
  94. package/dist/{draft9.js → draft09.js} +7 -4
  95. package/dist/draft10-session.cjs +2 -2
  96. package/dist/draft10-session.d.cts +6 -6
  97. package/dist/draft10-session.d.ts +6 -6
  98. package/dist/draft10-session.js +1 -1
  99. package/dist/draft10.cjs +8 -5
  100. package/dist/draft10.d.cts +14 -12
  101. package/dist/draft10.d.ts +14 -12
  102. package/dist/draft10.js +16 -13
  103. package/dist/draft11-session.cjs +2 -2
  104. package/dist/draft11-session.d.cts +6 -6
  105. package/dist/draft11-session.d.ts +6 -6
  106. package/dist/draft11-session.js +1 -1
  107. package/dist/draft11.cjs +8 -5
  108. package/dist/draft11.d.cts +14 -12
  109. package/dist/draft11.d.ts +14 -12
  110. package/dist/draft11.js +16 -13
  111. package/dist/draft12-session.cjs +2 -2
  112. package/dist/draft12-session.d.cts +6 -6
  113. package/dist/draft12-session.d.ts +6 -6
  114. package/dist/draft12-session.js +1 -1
  115. package/dist/draft12.cjs +8 -5
  116. package/dist/draft12.d.cts +16 -14
  117. package/dist/draft12.d.ts +16 -14
  118. package/dist/draft12.js +16 -13
  119. package/dist/draft13-session.cjs +2 -2
  120. package/dist/draft13-session.d.cts +6 -6
  121. package/dist/draft13-session.d.ts +6 -6
  122. package/dist/draft13-session.js +1 -1
  123. package/dist/draft13.cjs +8 -5
  124. package/dist/draft13.d.cts +16 -14
  125. package/dist/draft13.d.ts +16 -14
  126. package/dist/draft13.js +16 -13
  127. package/dist/draft14-session.cjs +2 -2
  128. package/dist/draft14-session.d.cts +6 -6
  129. package/dist/draft14-session.d.ts +6 -6
  130. package/dist/draft14-session.js +1 -1
  131. package/dist/draft14.cjs +14 -5
  132. package/dist/draft14.d.cts +14 -12
  133. package/dist/draft14.d.ts +14 -12
  134. package/dist/draft14.js +13 -4
  135. package/dist/draft15-session.cjs +2 -2
  136. package/dist/draft15-session.d.cts +6 -6
  137. package/dist/draft15-session.d.ts +6 -6
  138. package/dist/draft15-session.js +1 -1
  139. package/dist/draft15.cjs +8 -5
  140. package/dist/draft15.d.cts +14 -12
  141. package/dist/draft15.d.ts +14 -12
  142. package/dist/draft15.js +16 -13
  143. package/dist/draft16-session.cjs +2 -2
  144. package/dist/draft16-session.d.cts +6 -6
  145. package/dist/draft16-session.d.ts +6 -6
  146. package/dist/draft16-session.js +1 -1
  147. package/dist/draft16.cjs +8 -5
  148. package/dist/draft16.d.cts +14 -12
  149. package/dist/draft16.d.ts +14 -12
  150. package/dist/draft16.js +16 -13
  151. package/dist/draft17-session.cjs +2 -2
  152. package/dist/draft17-session.d.cts +7 -7
  153. package/dist/draft17-session.d.ts +7 -7
  154. package/dist/draft17-session.js +1 -1
  155. package/dist/draft17.cjs +8 -5
  156. package/dist/draft17.d.cts +11 -9
  157. package/dist/draft17.d.ts +11 -9
  158. package/dist/draft17.js +16 -13
  159. package/dist/index.cjs +52 -74
  160. package/dist/index.d.cts +41 -60
  161. package/dist/index.d.ts +41 -60
  162. package/dist/index.js +40 -62
  163. package/dist/{session-types-CJIFbTPd.d.ts → session-types-C7UONex5.d.cts} +28 -27
  164. package/dist/{session-types-Cbq8IGCP.d.cts → session-types-X-IYEGoG.d.ts} +28 -27
  165. package/dist/session.cjs +46 -13
  166. package/dist/session.d.cts +29 -11
  167. package/dist/session.d.ts +29 -11
  168. package/dist/session.js +46 -13
  169. package/dist/{types-DxSFvL2b.d.cts → types--Q7_DcvP.d.cts} +43 -39
  170. package/dist/{types-DxSFvL2b.d.ts → types--Q7_DcvP.d.ts} +43 -39
  171. package/dist/{types-B0FT5Qs2.d.cts → types-0IWbU9Z_.d.cts} +36 -36
  172. package/dist/{types-B0FT5Qs2.d.ts → types-0IWbU9Z_.d.ts} +36 -36
  173. package/dist/{types-gQsr0AAA.d.cts → types-B3g5G9KP.d.cts} +36 -36
  174. package/dist/{types-gQsr0AAA.d.ts → types-B3g5G9KP.d.ts} +36 -36
  175. package/dist/{types-Pme7sua0.d.cts → types-BFpFNM_m.d.cts} +57 -32
  176. package/dist/{types-Pme7sua0.d.ts → types-BFpFNM_m.d.ts} +57 -32
  177. package/dist/{types-8gUGeMgs.d.cts → types-Br7fm2mf.d.cts} +48 -26
  178. package/dist/{types-8gUGeMgs.d.ts → types-Br7fm2mf.d.ts} +48 -26
  179. package/dist/{types-BeAVNU-F.d.cts → types-C2qKTRR_.d.cts} +50 -45
  180. package/dist/{types-BeAVNU-F.d.ts → types-C2qKTRR_.d.ts} +50 -45
  181. package/dist/{types-DKpsfD3i.d.cts → types-DEaypVsD.d.cts} +115 -55
  182. package/dist/{types-DKpsfD3i.d.ts → types-DEaypVsD.d.ts} +115 -55
  183. package/dist/types-Dl4IaAHR.d.cts +282 -0
  184. package/dist/types-Dl4IaAHR.d.ts +282 -0
  185. package/dist/{types-CDa7F5ct.d.cts → types-DrQpTW1G.d.cts} +58 -50
  186. package/dist/{types-CDa7F5ct.d.ts → types-DrQpTW1G.d.ts} +58 -50
  187. package/dist/types-DuIO7cWK.d.cts +25 -0
  188. package/dist/types-DuIO7cWK.d.ts +25 -0
  189. package/dist/{types-B9A2g05r.d.cts → types-DuxfOYiO.d.cts} +47 -31
  190. package/dist/{types-B9A2g05r.d.ts → types-DuxfOYiO.d.ts} +47 -31
  191. package/dist/{types-D1dI_oTX.d.cts → types-jV1yDDBA.d.cts} +36 -36
  192. package/dist/{types-D1dI_oTX.d.ts → types-jV1yDDBA.d.ts} +36 -36
  193. package/package.json +192 -192
  194. package/src/core/buffer-reader.ts +130 -130
  195. package/src/core/buffer-writer.ts +100 -100
  196. package/src/core/errors.ts +1 -1
  197. package/src/core/hex.ts +21 -21
  198. package/src/core/session-types.ts +61 -59
  199. package/src/core/types.ts +18 -361
  200. package/src/drafts/draft07/codec.ts +1058 -938
  201. package/src/drafts/draft07/data-streams.ts +240 -240
  202. package/src/drafts/draft07/index.ts +124 -89
  203. package/src/drafts/draft07/messages.ts +76 -42
  204. package/src/drafts/draft07/rules.ts +107 -101
  205. package/src/drafts/draft07/session-fsm.ts +315 -287
  206. package/src/drafts/draft07/session.ts +8 -6
  207. package/src/drafts/draft07/types.ts +406 -72
  208. package/src/drafts/draft07/varint.ts +51 -51
  209. package/src/drafts/draft08/codec.ts +985 -953
  210. package/src/drafts/draft08/data-streams.ts +363 -359
  211. package/src/drafts/draft08/index.ts +10 -9
  212. package/src/drafts/draft08/messages.ts +59 -59
  213. package/src/drafts/draft08/rules.ts +73 -73
  214. package/src/drafts/draft08/session-fsm.ts +335 -303
  215. package/src/drafts/draft08/session.ts +6 -7
  216. package/src/drafts/draft08/types.ts +380 -384
  217. package/src/drafts/draft09/codec.ts +977 -945
  218. package/src/drafts/draft09/data-streams.ts +336 -332
  219. package/src/drafts/draft09/index.ts +10 -9
  220. package/src/drafts/draft09/messages.ts +59 -59
  221. package/src/drafts/draft09/rules.ts +73 -73
  222. package/src/drafts/draft09/session-fsm.ts +335 -303
  223. package/src/drafts/draft09/session.ts +6 -7
  224. package/src/drafts/draft09/types.ts +380 -384
  225. package/src/drafts/draft10/codec.ts +977 -945
  226. package/src/drafts/draft10/data-streams.ts +336 -332
  227. package/src/drafts/draft10/index.ts +10 -9
  228. package/src/drafts/draft10/messages.ts +59 -59
  229. package/src/drafts/draft10/rules.ts +73 -73
  230. package/src/drafts/draft10/session-fsm.ts +335 -303
  231. package/src/drafts/draft10/session.ts +6 -7
  232. package/src/drafts/draft10/types.ts +380 -384
  233. package/src/drafts/draft11/codec.ts +1054 -988
  234. package/src/drafts/draft11/data-streams.ts +316 -269
  235. package/src/drafts/draft11/index.ts +10 -9
  236. package/src/drafts/draft11/messages.ts +60 -59
  237. package/src/drafts/draft11/rules.ts +73 -73
  238. package/src/drafts/draft11/session-fsm.ts +359 -333
  239. package/src/drafts/draft11/session.ts +6 -7
  240. package/src/drafts/draft11/types.ts +385 -381
  241. package/src/drafts/draft12/codec.ts +1178 -1122
  242. package/src/drafts/draft12/data-streams.ts +324 -275
  243. package/src/drafts/draft12/index.ts +10 -9
  244. package/src/drafts/draft12/messages.ts +67 -66
  245. package/src/drafts/draft12/rules.ts +79 -79
  246. package/src/drafts/draft12/session-fsm.ts +384 -358
  247. package/src/drafts/draft12/session.ts +6 -7
  248. package/src/drafts/draft12/types.ts +424 -419
  249. package/src/drafts/draft13/codec.ts +1296 -1206
  250. package/src/drafts/draft13/data-streams.ts +326 -275
  251. package/src/drafts/draft13/index.ts +10 -9
  252. package/src/drafts/draft13/messages.ts +73 -68
  253. package/src/drafts/draft13/rules.ts +81 -81
  254. package/src/drafts/draft13/session-fsm.ts +392 -366
  255. package/src/drafts/draft13/session.ts +6 -7
  256. package/src/drafts/draft13/types.ts +447 -438
  257. package/src/drafts/draft14/codec.ts +1347 -1043
  258. package/src/drafts/draft14/data-streams.ts +831 -813
  259. package/src/drafts/draft14/index.ts +17 -9
  260. package/src/drafts/draft14/messages.ts +65 -65
  261. package/src/drafts/draft14/rules.ts +81 -81
  262. package/src/drafts/draft14/session-fsm.ts +415 -405
  263. package/src/drafts/draft14/session.ts +6 -7
  264. package/src/drafts/draft14/types.ts +451 -381
  265. package/src/drafts/draft15/codec.ts +1138 -978
  266. package/src/drafts/draft15/data-streams.ts +842 -794
  267. package/src/drafts/draft15/index.ts +10 -9
  268. package/src/drafts/draft15/messages.ts +54 -53
  269. package/src/drafts/draft15/rules.ts +67 -67
  270. package/src/drafts/draft15/session-fsm.ts +319 -299
  271. package/src/drafts/draft15/session.ts +6 -7
  272. package/src/drafts/draft15/types.ts +357 -339
  273. package/src/drafts/draft16/codec.ts +1242 -966
  274. package/src/drafts/draft16/data-streams.ts +835 -789
  275. package/src/drafts/draft16/index.ts +10 -9
  276. package/src/drafts/draft16/messages.ts +56 -55
  277. package/src/drafts/draft16/rules.ts +69 -69
  278. package/src/drafts/draft16/session-fsm.ts +319 -299
  279. package/src/drafts/draft16/session.ts +6 -7
  280. package/src/drafts/draft16/types.ts +386 -357
  281. package/src/drafts/draft17/codec.ts +1209 -971
  282. package/src/drafts/draft17/data-streams.ts +969 -758
  283. package/src/drafts/draft17/index.ts +9 -7
  284. package/src/drafts/draft17/messages.ts +43 -42
  285. package/src/drafts/draft17/rules.ts +58 -58
  286. package/src/drafts/draft17/session-fsm.ts +248 -216
  287. package/src/drafts/draft17/session.ts +5 -5
  288. package/src/drafts/draft17/types.ts +337 -313
  289. package/src/index.ts +85 -274
  290. package/src/session.ts +63 -25
  291. package/dist/chunk-FZDIEHQL.cjs +0 -1042
  292. package/dist/chunk-HDWJ2GDE.js +0 -24
  293. package/dist/chunk-KNDYS3DK.cjs +0 -24
  294. package/dist/chunk-N2KBF5Q2.js +0 -1042
  295. package/dist/draft7-session.d.cts +0 -7
  296. package/dist/draft7-session.d.ts +0 -7
  297. package/dist/draft7.cjs +0 -72
  298. package/dist/draft7.d.cts +0 -148
  299. package/dist/draft7.d.ts +0 -148
  300. package/dist/draft7.js +0 -72
  301. package/dist/draft8-session.cjs +0 -6
  302. package/dist/draft8-session.d.cts +0 -8
  303. package/dist/draft8-session.d.ts +0 -8
  304. package/dist/draft8.cjs +0 -116
  305. package/dist/draft9-session.cjs +0 -6
  306. package/dist/draft9-session.d.cts +0 -8
  307. package/dist/draft9-session.d.ts +0 -8
  308. package/dist/draft9.cjs +0 -116
  309. package/dist/types-QNXoxC9Y.d.cts +0 -236
  310. package/dist/types-QNXoxC9Y.d.ts +0 -236
  311. package/src/drafts/draft07/announce-fsm.ts +0 -2
  312. package/src/drafts/draft07/parameters.ts +0 -12
  313. package/src/drafts/draft07/subscription-fsm.ts +0 -3
@@ -1,945 +1,977 @@
1
- import { bytesToHex, hexToBytes } from "../../core/hex.js";
2
- import { BufferReader } from "../../core/buffer-reader.js";
3
- import { BufferWriter } from "../../core/buffer-writer.js";
4
- import type { BaseCodec, DecodeResult } from "../../core/types.js";
5
- import { DecodeError } from "../../core/types.js";
6
- import {
7
- MESSAGE_ID_MAP,
8
- MSG_ANNOUNCE,
9
- MSG_ANNOUNCE_CANCEL,
10
- MSG_ANNOUNCE_ERROR,
11
- MSG_ANNOUNCE_OK,
12
- MSG_CLIENT_SETUP,
13
- MSG_FETCH,
14
- MSG_FETCH_CANCEL,
15
- MSG_FETCH_ERROR,
16
- MSG_FETCH_OK,
17
- MSG_GOAWAY,
18
- MSG_MAX_SUBSCRIBE_ID,
19
- MSG_SERVER_SETUP,
20
- MSG_SUBSCRIBE,
21
- MSG_SUBSCRIBE_ANNOUNCES,
22
- MSG_SUBSCRIBE_ANNOUNCES_ERROR,
23
- MSG_SUBSCRIBE_ANNOUNCES_OK,
24
- MSG_SUBSCRIBE_DONE,
25
- MSG_SUBSCRIBE_ERROR,
26
- MSG_SUBSCRIBE_OK,
27
- MSG_SUBSCRIBE_UPDATE,
28
- MSG_SUBSCRIBES_BLOCKED,
29
- MSG_TRACK_STATUS,
30
- MSG_TRACK_STATUS_REQUEST,
31
- MSG_UNANNOUNCE,
32
- MSG_UNSUBSCRIBE,
33
- MSG_UNSUBSCRIBE_ANNOUNCES,
34
- PARAM_AUTHORIZATION_INFO,
35
- PARAM_DELIVERY_TIMEOUT,
36
- PARAM_MAX_CACHE_DURATION,
37
- SETUP_PARAM_MAX_SUBSCRIBE_ID,
38
- SETUP_PARAM_PATH,
39
- } from "./messages.js";
40
- import type {
41
- DatagramObject,
42
- DatagramStatusObject,
43
- Draft10DataStream,
44
- Draft10Fetch,
45
- Draft10Message,
46
- Draft10Params,
47
- Draft10SetupParams,
48
- FetchStream,
49
- JoiningFetch,
50
- StandaloneFetch,
51
- SubgroupStream,
52
- UnknownParam,
53
- } from "./types.js";
54
-
55
- const textEncoder = /* @__PURE__ */ new TextEncoder();
56
- const textDecoder = /* @__PURE__ */ new TextDecoder();
57
-
58
- // ─── Setup Parameter Encoding/Decoding (all type+length+value) ──────────────
59
-
60
- function encodeSetupParams(params: Draft10SetupParams, w: BufferWriter): void {
61
- let count = 0;
62
- if (params.path !== undefined) count++;
63
- if (params.max_subscribe_id !== undefined) count++;
64
- if (params.unknown) count += params.unknown.length;
65
-
66
- w.writeVarInt(count);
67
-
68
- if (params.path !== undefined) {
69
- w.writeVarInt(SETUP_PARAM_PATH);
70
- const encoded = textEncoder.encode(params.path);
71
- w.writeVarInt(encoded.byteLength);
72
- w.writeBytes(encoded);
73
- }
74
- if (params.max_subscribe_id !== undefined) {
75
- w.writeVarInt(SETUP_PARAM_MAX_SUBSCRIBE_ID);
76
- const tmpW = new BufferWriter(16);
77
- tmpW.writeVarInt(params.max_subscribe_id);
78
- const raw = tmpW.finish();
79
- w.writeVarInt(raw.byteLength);
80
- w.writeBytes(raw);
81
- }
82
- if (params.unknown) {
83
- for (const u of params.unknown) {
84
- w.writeVarInt(BigInt(u.id));
85
- const raw = hexToBytes(u.raw_hex);
86
- w.writeVarInt(raw.byteLength);
87
- w.writeBytes(raw);
88
- }
89
- }
90
- }
91
-
92
- function decodeSetupParams(r: BufferReader): Draft10SetupParams {
93
- const count = Number(r.readVarInt());
94
- const result: Draft10SetupParams = {};
95
- const unknown: UnknownParam[] = [];
96
-
97
- for (let i = 0; i < count; i++) {
98
- const paramType = r.readVarInt();
99
- const length = Number(r.readVarInt());
100
-
101
- if (paramType === SETUP_PARAM_PATH) {
102
- const bytes = r.readBytes(length);
103
- result.path = textDecoder.decode(bytes);
104
- } else if (paramType === SETUP_PARAM_MAX_SUBSCRIBE_ID) {
105
- const blob = r.readBytes(length);
106
- const tmpReader = new BufferReader(blob);
107
- result.max_subscribe_id = tmpReader.readVarInt();
108
- } else {
109
- const bytes = r.readBytes(length);
110
- unknown.push({ id: `0x${paramType.toString(16)}`, length, raw_hex: bytesToHex(bytes) });
111
- }
112
- }
113
-
114
- if (unknown.length > 0) result.unknown = unknown;
115
- return result;
116
- }
117
-
118
- // ─── Version-Specific Parameter Encoding/Decoding (all type+length+value) ────
119
-
120
- function encodeParams(params: Draft10Params, w: BufferWriter): void {
121
- let count = params.unknown ? params.unknown.length : 0;
122
- if (params.authorization_info !== undefined) count++;
123
- if (params.delivery_timeout !== undefined) count++;
124
- if (params.max_cache_duration !== undefined) count++;
125
- w.writeVarInt(count);
126
-
127
- if (params.authorization_info !== undefined) {
128
- w.writeVarInt(PARAM_AUTHORIZATION_INFO);
129
- const encoded = textEncoder.encode(params.authorization_info);
130
- w.writeVarInt(encoded.byteLength);
131
- w.writeBytes(encoded);
132
- }
133
- if (params.delivery_timeout !== undefined) {
134
- w.writeVarInt(PARAM_DELIVERY_TIMEOUT);
135
- const tmpW = new BufferWriter(16);
136
- tmpW.writeVarInt(params.delivery_timeout);
137
- const raw = tmpW.finish();
138
- w.writeVarInt(raw.byteLength);
139
- w.writeBytes(raw);
140
- }
141
- if (params.max_cache_duration !== undefined) {
142
- w.writeVarInt(PARAM_MAX_CACHE_DURATION);
143
- const tmpW = new BufferWriter(16);
144
- tmpW.writeVarInt(params.max_cache_duration);
145
- const raw = tmpW.finish();
146
- w.writeVarInt(raw.byteLength);
147
- w.writeBytes(raw);
148
- }
149
- if (params.unknown) {
150
- for (const u of params.unknown) {
151
- w.writeVarInt(BigInt(u.id));
152
- const raw = hexToBytes(u.raw_hex);
153
- w.writeVarInt(raw.byteLength);
154
- w.writeBytes(raw);
155
- }
156
- }
157
- }
158
-
159
- function decodeParams(r: BufferReader): Draft10Params {
160
- const count = Number(r.readVarInt());
161
- const result: Draft10Params = {};
162
- const unknown: UnknownParam[] = [];
163
-
164
- for (let i = 0; i < count; i++) {
165
- const paramType = r.readVarInt();
166
- const length = Number(r.readVarInt());
167
-
168
- if (paramType === PARAM_AUTHORIZATION_INFO) {
169
- const bytes = r.readBytes(length);
170
- result.authorization_info = textDecoder.decode(bytes);
171
- } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
172
- const blob = r.readBytes(length);
173
- const tmpReader = new BufferReader(blob);
174
- result.delivery_timeout = tmpReader.readVarInt();
175
- } else if (paramType === PARAM_MAX_CACHE_DURATION) {
176
- const blob = r.readBytes(length);
177
- const tmpReader = new BufferReader(blob);
178
- result.max_cache_duration = tmpReader.readVarInt();
179
- } else {
180
- const bytes = r.readBytes(length);
181
- unknown.push({ id: `0x${paramType.toString(16)}`, length, raw_hex: bytesToHex(bytes) });
182
- }
183
- }
184
-
185
- if (unknown.length > 0) result.unknown = unknown;
186
- return result;
187
- }
188
-
189
- // ─── Payload Encoders ──────────────────────────────────────────────────────────
190
-
191
- function encodeClientSetupPayload(
192
- msg: Draft10Message & { type: "client_setup" },
193
- w: BufferWriter,
194
- ): void {
195
- w.writeVarInt(msg.supported_versions.length);
196
- for (const v of msg.supported_versions) w.writeVarInt(v);
197
- encodeSetupParams(msg.parameters, w);
198
- }
199
-
200
- function encodeServerSetupPayload(
201
- msg: Draft10Message & { type: "server_setup" },
202
- w: BufferWriter,
203
- ): void {
204
- w.writeVarInt(msg.selected_version);
205
- encodeSetupParams(msg.parameters, w);
206
- }
207
-
208
- function encodeSubscribePayload(
209
- msg: Draft10Message & { type: "subscribe" },
210
- w: BufferWriter,
211
- ): void {
212
- w.writeVarInt(msg.subscribe_id);
213
- w.writeVarInt(msg.track_alias);
214
- w.writeTuple(msg.track_namespace);
215
- w.writeString(msg.track_name);
216
- w.writeUint8(msg.subscriber_priority);
217
- w.writeUint8(msg.group_order);
218
- w.writeVarInt(msg.filter_type);
219
- const ft = Number(msg.filter_type);
220
- if (ft === 3 || ft === 4) {
221
- w.writeVarInt(msg.start_group!);
222
- w.writeVarInt(msg.start_object!);
223
- }
224
- if (ft === 4) {
225
- w.writeVarInt(msg.end_group!);
226
- }
227
- encodeParams(msg.parameters, w);
228
- }
229
-
230
- function encodeSubscribeOkPayload(
231
- msg: Draft10Message & { type: "subscribe_ok" },
232
- w: BufferWriter,
233
- ): void {
234
- w.writeVarInt(msg.subscribe_id);
235
- w.writeVarInt(msg.expires);
236
- w.writeUint8(msg.group_order);
237
- w.writeUint8(msg.content_exists);
238
- if (msg.content_exists === 1) {
239
- w.writeVarInt(msg.largest_group_id!);
240
- w.writeVarInt(msg.largest_object_id!);
241
- }
242
- encodeParams(msg.parameters, w);
243
- }
244
-
245
- function encodeSubscribeErrorPayload(
246
- msg: Draft10Message & { type: "subscribe_error" },
247
- w: BufferWriter,
248
- ): void {
249
- w.writeVarInt(msg.subscribe_id);
250
- w.writeVarInt(msg.error_code);
251
- w.writeString(msg.reason_phrase);
252
- w.writeVarInt(msg.track_alias);
253
- }
254
-
255
- function encodeSubscribeUpdatePayload(
256
- msg: Draft10Message & { type: "subscribe_update" },
257
- w: BufferWriter,
258
- ): void {
259
- w.writeVarInt(msg.subscribe_id);
260
- w.writeVarInt(msg.start_group);
261
- w.writeVarInt(msg.start_object);
262
- w.writeVarInt(msg.end_group);
263
- w.writeUint8(msg.subscriber_priority);
264
- encodeParams(msg.parameters, w);
265
- }
266
-
267
- function encodeSubscribeDonePayload(
268
- msg: Draft10Message & { type: "subscribe_done" },
269
- w: BufferWriter,
270
- ): void {
271
- w.writeVarInt(msg.subscribe_id);
272
- w.writeVarInt(msg.status_code);
273
- w.writeVarInt(msg.stream_count);
274
- w.writeString(msg.reason_phrase);
275
- }
276
-
277
- function encodeUnsubscribePayload(
278
- msg: Draft10Message & { type: "unsubscribe" },
279
- w: BufferWriter,
280
- ): void {
281
- w.writeVarInt(msg.subscribe_id);
282
- }
283
-
284
- function encodeAnnouncePayload(msg: Draft10Message & { type: "announce" }, w: BufferWriter): void {
285
- w.writeTuple(msg.track_namespace);
286
- encodeParams(msg.parameters, w);
287
- }
288
-
289
- function encodeAnnounceOkPayload(
290
- msg: Draft10Message & { type: "announce_ok" },
291
- w: BufferWriter,
292
- ): void {
293
- w.writeTuple(msg.track_namespace);
294
- }
295
-
296
- function encodeAnnounceErrorPayload(
297
- msg: Draft10Message & { type: "announce_error" },
298
- w: BufferWriter,
299
- ): void {
300
- w.writeTuple(msg.track_namespace);
301
- w.writeVarInt(msg.error_code);
302
- w.writeString(msg.reason_phrase);
303
- }
304
-
305
- function encodeUnannouncePayload(
306
- msg: Draft10Message & { type: "unannounce" },
307
- w: BufferWriter,
308
- ): void {
309
- w.writeTuple(msg.track_namespace);
310
- }
311
-
312
- function encodeAnnounceCancelPayload(
313
- msg: Draft10Message & { type: "announce_cancel" },
314
- w: BufferWriter,
315
- ): void {
316
- w.writeTuple(msg.track_namespace);
317
- w.writeVarInt(msg.error_code);
318
- w.writeString(msg.reason_phrase);
319
- }
320
-
321
- function encodeSubscribeAnnouncesPayload(
322
- msg: Draft10Message & { type: "subscribe_announces" },
323
- w: BufferWriter,
324
- ): void {
325
- w.writeTuple(msg.track_namespace_prefix);
326
- encodeParams(msg.parameters, w);
327
- }
328
-
329
- function encodeSubscribeAnnouncesOkPayload(
330
- msg: Draft10Message & { type: "subscribe_announces_ok" },
331
- w: BufferWriter,
332
- ): void {
333
- w.writeTuple(msg.track_namespace_prefix);
334
- }
335
-
336
- function encodeSubscribeAnnouncesErrorPayload(
337
- msg: Draft10Message & { type: "subscribe_announces_error" },
338
- w: BufferWriter,
339
- ): void {
340
- w.writeTuple(msg.track_namespace_prefix);
341
- w.writeVarInt(msg.error_code);
342
- w.writeString(msg.reason_phrase);
343
- }
344
-
345
- function encodeUnsubscribeAnnouncesPayload(
346
- msg: Draft10Message & { type: "unsubscribe_announces" },
347
- w: BufferWriter,
348
- ): void {
349
- w.writeTuple(msg.track_namespace_prefix);
350
- }
351
-
352
- function encodeFetchPayload(msg: Draft10Message & { type: "fetch" }, w: BufferWriter): void {
353
- w.writeVarInt(msg.subscribe_id);
354
- w.writeUint8(msg.subscriber_priority);
355
- w.writeUint8(msg.group_order);
356
- w.writeVarInt(msg.fetch_type);
357
- const ft = Number(msg.fetch_type);
358
- if (ft === 1 && msg.standalone) {
359
- w.writeTuple(msg.standalone.track_namespace);
360
- w.writeString(msg.standalone.track_name);
361
- w.writeVarInt(msg.standalone.start_group);
362
- w.writeVarInt(msg.standalone.start_object);
363
- w.writeVarInt(msg.standalone.end_group);
364
- w.writeVarInt(msg.standalone.end_object);
365
- } else if (ft === 2 && msg.joining) {
366
- w.writeVarInt(msg.joining.joining_subscribe_id);
367
- w.writeVarInt(msg.joining.preceding_group_offset);
368
- }
369
- encodeParams(msg.parameters, w);
370
- }
371
-
372
- function encodeFetchOkPayload(msg: Draft10Message & { type: "fetch_ok" }, w: BufferWriter): void {
373
- w.writeVarInt(msg.subscribe_id);
374
- w.writeUint8(msg.group_order);
375
- w.writeUint8(msg.end_of_track);
376
- w.writeVarInt(msg.largest_group_id);
377
- w.writeVarInt(msg.largest_object_id);
378
- encodeParams(msg.parameters, w);
379
- }
380
-
381
- function encodeFetchErrorPayload(
382
- msg: Draft10Message & { type: "fetch_error" },
383
- w: BufferWriter,
384
- ): void {
385
- w.writeVarInt(msg.subscribe_id);
386
- w.writeVarInt(msg.error_code);
387
- w.writeString(msg.reason_phrase);
388
- }
389
-
390
- function encodeFetchCancelPayload(
391
- msg: Draft10Message & { type: "fetch_cancel" },
392
- w: BufferWriter,
393
- ): void {
394
- w.writeVarInt(msg.subscribe_id);
395
- }
396
-
397
- function encodeTrackStatusRequestPayload(
398
- msg: Draft10Message & { type: "track_status_request" },
399
- w: BufferWriter,
400
- ): void {
401
- w.writeTuple(msg.track_namespace);
402
- w.writeString(msg.track_name);
403
- }
404
-
405
- function encodeTrackStatusPayload(
406
- msg: Draft10Message & { type: "track_status" },
407
- w: BufferWriter,
408
- ): void {
409
- w.writeTuple(msg.track_namespace);
410
- w.writeString(msg.track_name);
411
- w.writeVarInt(msg.status_code);
412
- w.writeVarInt(msg.last_group_id);
413
- w.writeVarInt(msg.last_object_id);
414
- }
415
-
416
- function encodeGoAwayPayload(msg: Draft10Message & { type: "goaway" }, w: BufferWriter): void {
417
- w.writeString(msg.new_session_uri);
418
- }
419
-
420
- function encodeMaxSubscribeIdPayload(
421
- msg: Draft10Message & { type: "max_subscribe_id" },
422
- w: BufferWriter,
423
- ): void {
424
- w.writeVarInt(msg.subscribe_id);
425
- }
426
-
427
- function encodeSubscribesBlockedPayload(
428
- msg: Draft10Message & { type: "subscribes_blocked" },
429
- w: BufferWriter,
430
- ): void {
431
- w.writeVarInt(msg.maximum_subscribe_id);
432
- }
433
-
434
- // ─── Payload Decoders ──────────────────────────────────────────────────────────
435
-
436
- function decodeClientSetupPayload(r: BufferReader): Draft10Message {
437
- const numVersions = Number(r.readVarInt());
438
- if (numVersions === 0) {
439
- throw new DecodeError("CONSTRAINT_VIOLATION", "supported_versions must not be empty", r.offset);
440
- }
441
- const supported_versions: bigint[] = [];
442
- for (let i = 0; i < numVersions; i++) supported_versions.push(r.readVarInt());
443
- const parameters = decodeSetupParams(r);
444
- return { type: "client_setup", supported_versions, parameters };
445
- }
446
-
447
- function decodeServerSetupPayload(r: BufferReader): Draft10Message {
448
- const selected_version = r.readVarInt();
449
- const parameters = decodeSetupParams(r);
450
- return { type: "server_setup", selected_version, parameters };
451
- }
452
-
453
- function decodeSubscribePayload(r: BufferReader): Draft10Message {
454
- const subscribe_id = r.readVarInt();
455
- const track_alias = r.readVarInt();
456
- const track_namespace = r.readTuple();
457
- const track_name = r.readString();
458
- const subscriber_priority = r.readUint8();
459
- const group_order = r.readUint8();
460
- const filter_type = r.readVarInt();
461
- const ft = Number(filter_type);
462
- // Draft-09 removed LatestGroup (filter_type=1), valid values are 2-4
463
- if (ft < 2 || ft > 4) {
464
- throw new DecodeError("CONSTRAINT_VIOLATION", `Invalid filter_type: ${ft}`, r.offset);
465
- }
466
- let start_group: bigint | undefined;
467
- let start_object: bigint | undefined;
468
- let end_group: bigint | undefined;
469
- if (ft === 3 || ft === 4) {
470
- start_group = r.readVarInt();
471
- start_object = r.readVarInt();
472
- }
473
- if (ft === 4) {
474
- end_group = r.readVarInt();
475
- }
476
- const parameters = decodeParams(r);
477
- const msg: Record<string, unknown> = {
478
- type: "subscribe",
479
- subscribe_id,
480
- track_alias,
481
- track_namespace,
482
- track_name,
483
- subscriber_priority,
484
- group_order,
485
- filter_type,
486
- parameters,
487
- };
488
- if (start_group !== undefined) msg.start_group = start_group;
489
- if (start_object !== undefined) msg.start_object = start_object;
490
- if (end_group !== undefined) msg.end_group = end_group;
491
- return msg as unknown as Draft10Message;
492
- }
493
-
494
- function decodeSubscribeOkPayload(r: BufferReader): Draft10Message {
495
- const subscribe_id = r.readVarInt();
496
- const expires = r.readVarInt();
497
- const group_order = r.readUint8();
498
- const content_exists = r.readUint8();
499
- let largest_group_id: bigint | undefined;
500
- let largest_object_id: bigint | undefined;
501
- if (content_exists === 1) {
502
- largest_group_id = r.readVarInt();
503
- largest_object_id = r.readVarInt();
504
- }
505
- const parameters = decodeParams(r);
506
- const msg: Record<string, unknown> = {
507
- type: "subscribe_ok",
508
- subscribe_id,
509
- expires,
510
- group_order,
511
- content_exists,
512
- parameters,
513
- };
514
- if (largest_group_id !== undefined) msg.largest_group_id = largest_group_id;
515
- if (largest_object_id !== undefined) msg.largest_object_id = largest_object_id;
516
- return msg as unknown as Draft10Message;
517
- }
518
-
519
- function decodeSubscribeErrorPayload(r: BufferReader): Draft10Message {
520
- const subscribe_id = r.readVarInt();
521
- const error_code = r.readVarInt();
522
- const reason_phrase = r.readString();
523
- const track_alias = r.readVarInt();
524
- return { type: "subscribe_error", subscribe_id, error_code, reason_phrase, track_alias };
525
- }
526
-
527
- function decodeSubscribeUpdatePayload(r: BufferReader): Draft10Message {
528
- const subscribe_id = r.readVarInt();
529
- const start_group = r.readVarInt();
530
- const start_object = r.readVarInt();
531
- const end_group = r.readVarInt();
532
- const subscriber_priority = r.readUint8();
533
- const parameters = decodeParams(r);
534
- return {
535
- type: "subscribe_update",
536
- subscribe_id,
537
- start_group,
538
- start_object,
539
- end_group,
540
- subscriber_priority,
541
- parameters,
542
- };
543
- }
544
-
545
- function decodeSubscribeDonePayload(r: BufferReader): Draft10Message {
546
- const subscribe_id = r.readVarInt();
547
- const status_code = r.readVarInt();
548
- const stream_count = r.readVarInt();
549
- const reason_phrase = r.readString();
550
- return { type: "subscribe_done", subscribe_id, status_code, stream_count, reason_phrase };
551
- }
552
-
553
- function decodeUnsubscribePayload(r: BufferReader): Draft10Message {
554
- const subscribe_id = r.readVarInt();
555
- return { type: "unsubscribe", subscribe_id };
556
- }
557
-
558
- function decodeAnnouncePayload(r: BufferReader): Draft10Message {
559
- const track_namespace = r.readTuple();
560
- const parameters = decodeParams(r);
561
- return { type: "announce", track_namespace, parameters };
562
- }
563
-
564
- function decodeAnnounceOkPayload(r: BufferReader): Draft10Message {
565
- const track_namespace = r.readTuple();
566
- return { type: "announce_ok", track_namespace };
567
- }
568
-
569
- function decodeAnnounceErrorPayload(r: BufferReader): Draft10Message {
570
- const track_namespace = r.readTuple();
571
- const error_code = r.readVarInt();
572
- const reason_phrase = r.readString();
573
- return { type: "announce_error", track_namespace, error_code, reason_phrase };
574
- }
575
-
576
- function decodeUnannouncePayload(r: BufferReader): Draft10Message {
577
- const track_namespace = r.readTuple();
578
- return { type: "unannounce", track_namespace };
579
- }
580
-
581
- function decodeAnnounceCancelPayload(r: BufferReader): Draft10Message {
582
- const track_namespace = r.readTuple();
583
- const error_code = r.readVarInt();
584
- const reason_phrase = r.readString();
585
- return { type: "announce_cancel", track_namespace, error_code, reason_phrase };
586
- }
587
-
588
- function decodeSubscribeAnnouncesPayload(r: BufferReader): Draft10Message {
589
- const track_namespace_prefix = r.readTuple();
590
- const parameters = decodeParams(r);
591
- return { type: "subscribe_announces", track_namespace_prefix, parameters };
592
- }
593
-
594
- function decodeSubscribeAnnouncesOkPayload(r: BufferReader): Draft10Message {
595
- const track_namespace_prefix = r.readTuple();
596
- return { type: "subscribe_announces_ok", track_namespace_prefix };
597
- }
598
-
599
- function decodeSubscribeAnnouncesErrorPayload(r: BufferReader): Draft10Message {
600
- const track_namespace_prefix = r.readTuple();
601
- const error_code = r.readVarInt();
602
- const reason_phrase = r.readString();
603
- return { type: "subscribe_announces_error", track_namespace_prefix, error_code, reason_phrase };
604
- }
605
-
606
- function decodeUnsubscribeAnnouncesPayload(r: BufferReader): Draft10Message {
607
- const track_namespace_prefix = r.readTuple();
608
- return { type: "unsubscribe_announces", track_namespace_prefix };
609
- }
610
-
611
- function decodeFetchPayload(r: BufferReader): Draft10Message {
612
- const subscribe_id = r.readVarInt();
613
- const subscriber_priority = r.readUint8();
614
- const group_order = r.readUint8();
615
- const fetch_type = r.readVarInt();
616
- const ft = Number(fetch_type);
617
-
618
- if (ft < 1 || ft > 2) {
619
- throw new DecodeError("CONSTRAINT_VIOLATION", `Invalid fetch_type: ${ft}`, r.offset);
620
- }
621
-
622
- let standalone: StandaloneFetch | undefined;
623
- let joining: JoiningFetch | undefined;
624
-
625
- if (ft === 1) {
626
- const track_namespace = r.readTuple();
627
- const track_name = r.readString();
628
- const start_group = r.readVarInt();
629
- const start_object = r.readVarInt();
630
- const end_group = r.readVarInt();
631
- const end_object = r.readVarInt();
632
- standalone = { track_namespace, track_name, start_group, start_object, end_group, end_object };
633
- } else {
634
- const joining_subscribe_id = r.readVarInt();
635
- const preceding_group_offset = r.readVarInt();
636
- joining = { joining_subscribe_id, preceding_group_offset };
637
- }
638
-
639
- const parameters = decodeParams(r);
640
- return {
641
- type: "fetch",
642
- subscribe_id,
643
- subscriber_priority,
644
- group_order,
645
- fetch_type,
646
- standalone,
647
- joining,
648
- parameters,
649
- } as Draft10Fetch;
650
- }
651
-
652
- function decodeFetchOkPayload(r: BufferReader): Draft10Message {
653
- const subscribe_id = r.readVarInt();
654
- const group_order = r.readUint8();
655
- const end_of_track = r.readUint8();
656
- const largest_group_id = r.readVarInt();
657
- const largest_object_id = r.readVarInt();
658
- const parameters = decodeParams(r);
659
- return {
660
- type: "fetch_ok",
661
- subscribe_id,
662
- group_order,
663
- end_of_track,
664
- largest_group_id,
665
- largest_object_id,
666
- parameters,
667
- };
668
- }
669
-
670
- function decodeFetchErrorPayload(r: BufferReader): Draft10Message {
671
- const subscribe_id = r.readVarInt();
672
- const error_code = r.readVarInt();
673
- const reason_phrase = r.readString();
674
- return { type: "fetch_error", subscribe_id, error_code, reason_phrase };
675
- }
676
-
677
- function decodeFetchCancelPayload(r: BufferReader): Draft10Message {
678
- const subscribe_id = r.readVarInt();
679
- return { type: "fetch_cancel", subscribe_id };
680
- }
681
-
682
- function decodeTrackStatusRequestPayload(r: BufferReader): Draft10Message {
683
- const track_namespace = r.readTuple();
684
- const track_name = r.readString();
685
- return { type: "track_status_request", track_namespace, track_name };
686
- }
687
-
688
- function decodeTrackStatusPayload(r: BufferReader): Draft10Message {
689
- const track_namespace = r.readTuple();
690
- const track_name = r.readString();
691
- const status_code = r.readVarInt();
692
- const last_group_id = r.readVarInt();
693
- const last_object_id = r.readVarInt();
694
- return {
695
- type: "track_status",
696
- track_namespace,
697
- track_name,
698
- status_code,
699
- last_group_id,
700
- last_object_id,
701
- };
702
- }
703
-
704
- function decodeGoAwayPayload(r: BufferReader): Draft10Message {
705
- const new_session_uri = r.readString();
706
- return { type: "goaway", new_session_uri };
707
- }
708
-
709
- function decodeMaxSubscribeIdPayload(r: BufferReader): Draft10Message {
710
- const subscribe_id = r.readVarInt();
711
- return { type: "max_subscribe_id", subscribe_id };
712
- }
713
-
714
- function decodeSubscribesBlockedPayload(r: BufferReader): Draft10Message {
715
- const maximum_subscribe_id = r.readVarInt();
716
- return { type: "subscribes_blocked", maximum_subscribe_id };
717
- }
718
-
719
- // ─── Payload dispatch tables ───────────────────────────────────────────────────
720
-
721
- const payloadDecoders: ReadonlyMap<bigint, (r: BufferReader) => Draft10Message> = new Map([
722
- [MSG_CLIENT_SETUP, decodeClientSetupPayload],
723
- [MSG_SERVER_SETUP, decodeServerSetupPayload],
724
- [MSG_SUBSCRIBE, decodeSubscribePayload],
725
- [MSG_SUBSCRIBE_OK, decodeSubscribeOkPayload],
726
- [MSG_SUBSCRIBE_ERROR, decodeSubscribeErrorPayload],
727
- [MSG_SUBSCRIBE_UPDATE, decodeSubscribeUpdatePayload],
728
- [MSG_SUBSCRIBE_DONE, decodeSubscribeDonePayload],
729
- [MSG_UNSUBSCRIBE, decodeUnsubscribePayload],
730
- [MSG_ANNOUNCE, decodeAnnouncePayload],
731
- [MSG_ANNOUNCE_OK, decodeAnnounceOkPayload],
732
- [MSG_ANNOUNCE_ERROR, decodeAnnounceErrorPayload],
733
- [MSG_UNANNOUNCE, decodeUnannouncePayload],
734
- [MSG_ANNOUNCE_CANCEL, decodeAnnounceCancelPayload],
735
- [MSG_SUBSCRIBE_ANNOUNCES, decodeSubscribeAnnouncesPayload],
736
- [MSG_SUBSCRIBE_ANNOUNCES_OK, decodeSubscribeAnnouncesOkPayload],
737
- [MSG_SUBSCRIBE_ANNOUNCES_ERROR, decodeSubscribeAnnouncesErrorPayload],
738
- [MSG_UNSUBSCRIBE_ANNOUNCES, decodeUnsubscribeAnnouncesPayload],
739
- [MSG_FETCH, decodeFetchPayload],
740
- [MSG_FETCH_OK, decodeFetchOkPayload],
741
- [MSG_FETCH_ERROR, decodeFetchErrorPayload],
742
- [MSG_FETCH_CANCEL, decodeFetchCancelPayload],
743
- [MSG_TRACK_STATUS_REQUEST, decodeTrackStatusRequestPayload],
744
- [MSG_TRACK_STATUS, decodeTrackStatusPayload],
745
- [MSG_GOAWAY, decodeGoAwayPayload],
746
- [MSG_MAX_SUBSCRIBE_ID, decodeMaxSubscribeIdPayload],
747
- [MSG_SUBSCRIBES_BLOCKED, decodeSubscribesBlockedPayload],
748
- ]);
749
-
750
- // ─── Public API ────────────────────────────────────────────────────────────────
751
-
752
- export function encodeMessage(message: Draft10Message): Uint8Array {
753
- const typeId = MESSAGE_ID_MAP.get(message.type);
754
- if (typeId === undefined) throw new Error(`Unknown message type: ${message.type}`);
755
-
756
- const payloadWriter = new BufferWriter();
757
- encodePayload(message, payloadWriter);
758
- const payload = payloadWriter.finishView();
759
-
760
- const writer = new BufferWriter(payload.byteLength + 16);
761
- writer.writeVarInt(typeId);
762
- writer.writeVarInt(payload.byteLength);
763
- writer.writeBytes(payload);
764
- return writer.finish();
765
- }
766
-
767
- function encodePayload(msg: Draft10Message, w: BufferWriter): void {
768
- switch (msg.type) {
769
- case "client_setup":
770
- return encodeClientSetupPayload(msg, w);
771
- case "server_setup":
772
- return encodeServerSetupPayload(msg, w);
773
- case "subscribe":
774
- return encodeSubscribePayload(msg, w);
775
- case "subscribe_ok":
776
- return encodeSubscribeOkPayload(msg, w);
777
- case "subscribe_error":
778
- return encodeSubscribeErrorPayload(msg, w);
779
- case "subscribe_update":
780
- return encodeSubscribeUpdatePayload(msg, w);
781
- case "subscribe_done":
782
- return encodeSubscribeDonePayload(msg, w);
783
- case "unsubscribe":
784
- return encodeUnsubscribePayload(msg, w);
785
- case "announce":
786
- return encodeAnnouncePayload(msg, w);
787
- case "announce_ok":
788
- return encodeAnnounceOkPayload(msg, w);
789
- case "announce_error":
790
- return encodeAnnounceErrorPayload(msg, w);
791
- case "unannounce":
792
- return encodeUnannouncePayload(msg, w);
793
- case "announce_cancel":
794
- return encodeAnnounceCancelPayload(msg, w);
795
- case "subscribe_announces":
796
- return encodeSubscribeAnnouncesPayload(msg, w);
797
- case "subscribe_announces_ok":
798
- return encodeSubscribeAnnouncesOkPayload(msg, w);
799
- case "subscribe_announces_error":
800
- return encodeSubscribeAnnouncesErrorPayload(msg, w);
801
- case "unsubscribe_announces":
802
- return encodeUnsubscribeAnnouncesPayload(msg, w);
803
- case "fetch":
804
- return encodeFetchPayload(msg, w);
805
- case "fetch_ok":
806
- return encodeFetchOkPayload(msg, w);
807
- case "fetch_error":
808
- return encodeFetchErrorPayload(msg, w);
809
- case "fetch_cancel":
810
- return encodeFetchCancelPayload(msg, w);
811
- case "track_status_request":
812
- return encodeTrackStatusRequestPayload(msg, w);
813
- case "track_status":
814
- return encodeTrackStatusPayload(msg, w);
815
- case "goaway":
816
- return encodeGoAwayPayload(msg, w);
817
- case "max_subscribe_id":
818
- return encodeMaxSubscribeIdPayload(msg, w);
819
- case "subscribes_blocked":
820
- return encodeSubscribesBlockedPayload(msg, w);
821
- default: {
822
- const _exhaustive: never = msg;
823
- throw new Error(`Unhandled message type: ${(_exhaustive as Draft10Message).type}`);
824
- }
825
- }
826
- }
827
-
828
- export function decodeMessage(bytes: Uint8Array): DecodeResult<Draft10Message> {
829
- try {
830
- const reader = new BufferReader(bytes);
831
- const typeId = reader.readVarInt();
832
- const payloadLength = Number(reader.readVarInt());
833
- const payloadBytes = reader.readBytes(payloadLength);
834
- const payloadReader = new BufferReader(payloadBytes);
835
-
836
- const decoder = payloadDecoders.get(typeId);
837
- if (!decoder) {
838
- return {
839
- ok: false,
840
- error: new DecodeError(
841
- "UNKNOWN_MESSAGE_TYPE",
842
- `Unknown message type ID: 0x${typeId.toString(16)}`,
843
- 0,
844
- ),
845
- };
846
- }
847
-
848
- const message = decoder(payloadReader);
849
- return { ok: true, value: message, bytesRead: reader.offset };
850
- } catch (e) {
851
- if (e instanceof DecodeError) return { ok: false, error: e };
852
- throw e;
853
- }
854
- }
855
-
856
- export {
857
- decodeDataStream,
858
- decodeDatagram,
859
- decodeDatagramStatus,
860
- decodeFetchStream,
861
- decodeSubgroupStream,
862
- encodeDatagram,
863
- encodeDatagramStatus,
864
- encodeFetchStream,
865
- encodeSubgroupStream,
866
- } from "./data-streams.js";
867
- import {
868
- decodeDataStream,
869
- decodeDatagram,
870
- decodeDatagramStatus,
871
- decodeFetchStream,
872
- decodeSubgroupStream,
873
- encodeDatagram,
874
- encodeDatagramStatus,
875
- encodeFetchStream,
876
- encodeSubgroupStream,
877
- } from "./data-streams.js";
878
-
879
- export function createStreamDecoder(): TransformStream<Uint8Array, Draft10Message> {
880
- let buffer = new Uint8Array(0);
881
- let offset = 0;
882
- return new TransformStream<Uint8Array, Draft10Message>({
883
- transform(chunk, controller) {
884
- if (offset > 0) {
885
- buffer = buffer.subarray(offset);
886
- offset = 0;
887
- }
888
- const newBuffer = new Uint8Array(buffer.length + chunk.length);
889
- newBuffer.set(buffer, 0);
890
- newBuffer.set(chunk, buffer.length);
891
- buffer = newBuffer;
892
- while (offset < buffer.length) {
893
- const result = decodeMessage(buffer.subarray(offset));
894
- if (!result.ok) {
895
- if (result.error.code === "UNEXPECTED_END") break;
896
- controller.error(result.error);
897
- return;
898
- }
899
- controller.enqueue(result.value);
900
- offset += result.bytesRead;
901
- }
902
- },
903
- flush(controller) {
904
- if (offset < buffer.length)
905
- controller.error(new DecodeError("UNEXPECTED_END", "Stream ended with incomplete data", 0));
906
- },
907
- });
908
- }
909
-
910
- // ─── Codec Factory ─────────────────────────────────────────────────────────────
911
-
912
- export interface Draft10Codec extends BaseCodec<Draft10Message> {
913
- readonly draft: "draft-ietf-moq-transport-10";
914
- encodeSubgroupStream(stream: SubgroupStream): Uint8Array;
915
- encodeDatagram(dg: DatagramObject): Uint8Array;
916
- encodeDatagramStatus(dg: DatagramStatusObject): Uint8Array;
917
- encodeFetchStream(stream: FetchStream): Uint8Array;
918
- decodeSubgroupStream(bytes: Uint8Array): DecodeResult<SubgroupStream>;
919
- decodeDatagram(bytes: Uint8Array): DecodeResult<DatagramObject>;
920
- decodeDatagramStatus(bytes: Uint8Array): DecodeResult<DatagramStatusObject>;
921
- decodeFetchStream(bytes: Uint8Array): DecodeResult<FetchStream>;
922
- decodeDataStream(
923
- streamType: "subgroup" | "datagram" | "datagram_status" | "fetch",
924
- bytes: Uint8Array,
925
- ): DecodeResult<Draft10DataStream>;
926
- createStreamDecoder(): TransformStream<Uint8Array, Draft10Message>;
927
- }
928
-
929
- export function createDraft10Codec(): Draft10Codec {
930
- return {
931
- draft: "draft-ietf-moq-transport-10",
932
- encodeMessage,
933
- decodeMessage,
934
- encodeSubgroupStream,
935
- encodeDatagram,
936
- encodeDatagramStatus,
937
- encodeFetchStream,
938
- decodeSubgroupStream,
939
- decodeDatagram,
940
- decodeDatagramStatus,
941
- decodeFetchStream,
942
- decodeDataStream,
943
- createStreamDecoder,
944
- };
945
- }
1
+ import { BufferReader } from '../../core/buffer-reader.js'
2
+ import { BufferWriter } from '../../core/buffer-writer.js'
3
+ import { bytesToHex, hexToBytes } from '../../core/hex.js'
4
+ import type { BaseCodec, DecodeResult } from '../../core/types.js'
5
+ import { DecodeError } from '../../core/types.js'
6
+ import {
7
+ decodeDatagram,
8
+ decodeDatagramStatus,
9
+ decodeDataStream,
10
+ decodeFetchStream,
11
+ decodeSubgroupStream,
12
+ encodeDatagram,
13
+ encodeDatagramStatus,
14
+ encodeFetchStream,
15
+ encodeSubgroupStream,
16
+ } from './data-streams.js'
17
+ import {
18
+ MESSAGE_ID_MAP,
19
+ MSG_ANNOUNCE,
20
+ MSG_ANNOUNCE_CANCEL,
21
+ MSG_ANNOUNCE_ERROR,
22
+ MSG_ANNOUNCE_OK,
23
+ MSG_CLIENT_SETUP,
24
+ MSG_FETCH,
25
+ MSG_FETCH_CANCEL,
26
+ MSG_FETCH_ERROR,
27
+ MSG_FETCH_OK,
28
+ MSG_GOAWAY,
29
+ MSG_MAX_SUBSCRIBE_ID,
30
+ MSG_SERVER_SETUP,
31
+ MSG_SUBSCRIBE,
32
+ MSG_SUBSCRIBE_ANNOUNCES,
33
+ MSG_SUBSCRIBE_ANNOUNCES_ERROR,
34
+ MSG_SUBSCRIBE_ANNOUNCES_OK,
35
+ MSG_SUBSCRIBE_DONE,
36
+ MSG_SUBSCRIBE_ERROR,
37
+ MSG_SUBSCRIBE_OK,
38
+ MSG_SUBSCRIBE_UPDATE,
39
+ MSG_SUBSCRIBES_BLOCKED,
40
+ MSG_TRACK_STATUS,
41
+ MSG_TRACK_STATUS_REQUEST,
42
+ MSG_UNANNOUNCE,
43
+ MSG_UNSUBSCRIBE,
44
+ MSG_UNSUBSCRIBE_ANNOUNCES,
45
+ PARAM_AUTHORIZATION_INFO,
46
+ PARAM_DELIVERY_TIMEOUT,
47
+ PARAM_MAX_CACHE_DURATION,
48
+ SETUP_PARAM_MAX_SUBSCRIBE_ID,
49
+ SETUP_PARAM_PATH,
50
+ } from './messages.js'
51
+ import type {
52
+ DatagramObject,
53
+ DatagramStatusObject,
54
+ Draft10DataStream,
55
+ Draft10Fetch,
56
+ Draft10Message,
57
+ Draft10Params,
58
+ Draft10SetupParams,
59
+ FetchStream,
60
+ JoiningFetch,
61
+ StandaloneFetch,
62
+ SubgroupStream,
63
+ UnknownParam,
64
+ } from './types.js'
65
+
66
+ const textEncoder = /* @__PURE__ */ new TextEncoder()
67
+ const textDecoder = /* @__PURE__ */ new TextDecoder()
68
+
69
+ // ─── Setup Parameter Encoding/Decoding (all type+length+value) ──────────────
70
+
71
+ function encodeSetupParams(params: Draft10SetupParams, w: BufferWriter): void {
72
+ let count = 0
73
+ if (params.path !== undefined) count++
74
+ if (params.max_subscribe_id !== undefined) count++
75
+ if (params.unknown) count += params.unknown.length
76
+
77
+ w.writeVarInt(count)
78
+
79
+ if (params.path !== undefined) {
80
+ w.writeVarInt(SETUP_PARAM_PATH)
81
+ const encoded = textEncoder.encode(params.path)
82
+ w.writeVarInt(encoded.byteLength)
83
+ w.writeBytes(encoded)
84
+ }
85
+ if (params.max_subscribe_id !== undefined) {
86
+ w.writeVarInt(SETUP_PARAM_MAX_SUBSCRIBE_ID)
87
+ const tmpW = new BufferWriter(16)
88
+ tmpW.writeVarInt(params.max_subscribe_id)
89
+ const raw = tmpW.finish()
90
+ w.writeVarInt(raw.byteLength)
91
+ w.writeBytes(raw)
92
+ }
93
+ if (params.unknown) {
94
+ for (const u of params.unknown) {
95
+ w.writeVarInt(BigInt(u.id))
96
+ const raw = hexToBytes(u.raw_hex)
97
+ w.writeVarInt(raw.byteLength)
98
+ w.writeBytes(raw)
99
+ }
100
+ }
101
+ }
102
+
103
+ function decodeSetupParams(r: BufferReader): Draft10SetupParams {
104
+ const count = Number(r.readVarInt())
105
+ const result: Draft10SetupParams = {}
106
+ const unknown: UnknownParam[] = []
107
+
108
+ for (let i = 0; i < count; i++) {
109
+ const paramType = r.readVarInt()
110
+ const length = Number(r.readVarInt())
111
+
112
+ if (paramType === SETUP_PARAM_PATH) {
113
+ const bytes = r.readBytes(length)
114
+ result.path = textDecoder.decode(bytes)
115
+ } else if (paramType === SETUP_PARAM_MAX_SUBSCRIBE_ID) {
116
+ const blob = r.readBytes(length)
117
+ const tmpReader = new BufferReader(blob)
118
+ result.max_subscribe_id = tmpReader.readVarInt()
119
+ } else {
120
+ const bytes = r.readBytes(length)
121
+ unknown.push({
122
+ id: `0x${paramType.toString(16)}`,
123
+ length,
124
+ raw_hex: bytesToHex(bytes),
125
+ })
126
+ }
127
+ }
128
+
129
+ if (unknown.length > 0) result.unknown = unknown
130
+ return result
131
+ }
132
+
133
+ // ─── Version-Specific Parameter Encoding/Decoding (all type+length+value) ────
134
+
135
+ function encodeParams(params: Draft10Params, w: BufferWriter): void {
136
+ let count = params.unknown ? params.unknown.length : 0
137
+ if (params.authorization_info !== undefined) count++
138
+ if (params.delivery_timeout !== undefined) count++
139
+ if (params.max_cache_duration !== undefined) count++
140
+ w.writeVarInt(count)
141
+
142
+ if (params.authorization_info !== undefined) {
143
+ w.writeVarInt(PARAM_AUTHORIZATION_INFO)
144
+ const encoded = textEncoder.encode(params.authorization_info)
145
+ w.writeVarInt(encoded.byteLength)
146
+ w.writeBytes(encoded)
147
+ }
148
+ if (params.delivery_timeout !== undefined) {
149
+ w.writeVarInt(PARAM_DELIVERY_TIMEOUT)
150
+ const tmpW = new BufferWriter(16)
151
+ tmpW.writeVarInt(params.delivery_timeout)
152
+ const raw = tmpW.finish()
153
+ w.writeVarInt(raw.byteLength)
154
+ w.writeBytes(raw)
155
+ }
156
+ if (params.max_cache_duration !== undefined) {
157
+ w.writeVarInt(PARAM_MAX_CACHE_DURATION)
158
+ const tmpW = new BufferWriter(16)
159
+ tmpW.writeVarInt(params.max_cache_duration)
160
+ const raw = tmpW.finish()
161
+ w.writeVarInt(raw.byteLength)
162
+ w.writeBytes(raw)
163
+ }
164
+ if (params.unknown) {
165
+ for (const u of params.unknown) {
166
+ w.writeVarInt(BigInt(u.id))
167
+ const raw = hexToBytes(u.raw_hex)
168
+ w.writeVarInt(raw.byteLength)
169
+ w.writeBytes(raw)
170
+ }
171
+ }
172
+ }
173
+
174
+ function decodeParams(r: BufferReader): Draft10Params {
175
+ const count = Number(r.readVarInt())
176
+ const result: Draft10Params = {}
177
+ const unknown: UnknownParam[] = []
178
+
179
+ for (let i = 0; i < count; i++) {
180
+ const paramType = r.readVarInt()
181
+ const length = Number(r.readVarInt())
182
+
183
+ if (paramType === PARAM_AUTHORIZATION_INFO) {
184
+ const bytes = r.readBytes(length)
185
+ result.authorization_info = textDecoder.decode(bytes)
186
+ } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
187
+ const blob = r.readBytes(length)
188
+ const tmpReader = new BufferReader(blob)
189
+ result.delivery_timeout = tmpReader.readVarInt()
190
+ } else if (paramType === PARAM_MAX_CACHE_DURATION) {
191
+ const blob = r.readBytes(length)
192
+ const tmpReader = new BufferReader(blob)
193
+ result.max_cache_duration = tmpReader.readVarInt()
194
+ } else {
195
+ const bytes = r.readBytes(length)
196
+ unknown.push({
197
+ id: `0x${paramType.toString(16)}`,
198
+ length,
199
+ raw_hex: bytesToHex(bytes),
200
+ })
201
+ }
202
+ }
203
+
204
+ if (unknown.length > 0) result.unknown = unknown
205
+ return result
206
+ }
207
+
208
+ // ─── Payload Encoders ──────────────────────────────────────────────────────────
209
+
210
+ function encodeClientSetupPayload(
211
+ msg: Draft10Message & { type: 'client_setup' },
212
+ w: BufferWriter,
213
+ ): void {
214
+ w.writeVarInt(msg.supported_versions.length)
215
+ for (const v of msg.supported_versions) w.writeVarInt(v)
216
+ encodeSetupParams(msg.parameters, w)
217
+ }
218
+
219
+ function encodeServerSetupPayload(
220
+ msg: Draft10Message & { type: 'server_setup' },
221
+ w: BufferWriter,
222
+ ): void {
223
+ w.writeVarInt(msg.selected_version)
224
+ encodeSetupParams(msg.parameters, w)
225
+ }
226
+
227
+ function encodeSubscribePayload(
228
+ msg: Draft10Message & { type: 'subscribe' },
229
+ w: BufferWriter,
230
+ ): void {
231
+ w.writeVarInt(msg.subscribe_id)
232
+ w.writeVarInt(msg.track_alias)
233
+ w.writeTuple(msg.track_namespace)
234
+ w.writeString(msg.track_name)
235
+ w.writeUint8(msg.subscriber_priority)
236
+ w.writeUint8(msg.group_order)
237
+ w.writeVarInt(msg.filter_type)
238
+ const ft = Number(msg.filter_type)
239
+ if (ft === 3 || ft === 4) {
240
+ w.writeVarInt(msg.start_group!)
241
+ w.writeVarInt(msg.start_object!)
242
+ }
243
+ if (ft === 4) {
244
+ w.writeVarInt(msg.end_group!)
245
+ }
246
+ encodeParams(msg.parameters, w)
247
+ }
248
+
249
+ function encodeSubscribeOkPayload(
250
+ msg: Draft10Message & { type: 'subscribe_ok' },
251
+ w: BufferWriter,
252
+ ): void {
253
+ w.writeVarInt(msg.subscribe_id)
254
+ w.writeVarInt(msg.expires)
255
+ w.writeUint8(msg.group_order)
256
+ w.writeUint8(msg.content_exists)
257
+ if (msg.content_exists === 1) {
258
+ w.writeVarInt(msg.largest_group_id!)
259
+ w.writeVarInt(msg.largest_object_id!)
260
+ }
261
+ encodeParams(msg.parameters, w)
262
+ }
263
+
264
+ function encodeSubscribeErrorPayload(
265
+ msg: Draft10Message & { type: 'subscribe_error' },
266
+ w: BufferWriter,
267
+ ): void {
268
+ w.writeVarInt(msg.subscribe_id)
269
+ w.writeVarInt(msg.error_code)
270
+ w.writeString(msg.reason_phrase)
271
+ w.writeVarInt(msg.track_alias)
272
+ }
273
+
274
+ function encodeSubscribeUpdatePayload(
275
+ msg: Draft10Message & { type: 'subscribe_update' },
276
+ w: BufferWriter,
277
+ ): void {
278
+ w.writeVarInt(msg.subscribe_id)
279
+ w.writeVarInt(msg.start_group)
280
+ w.writeVarInt(msg.start_object)
281
+ w.writeVarInt(msg.end_group)
282
+ w.writeUint8(msg.subscriber_priority)
283
+ encodeParams(msg.parameters, w)
284
+ }
285
+
286
+ function encodeSubscribeDonePayload(
287
+ msg: Draft10Message & { type: 'subscribe_done' },
288
+ w: BufferWriter,
289
+ ): void {
290
+ w.writeVarInt(msg.subscribe_id)
291
+ w.writeVarInt(msg.status_code)
292
+ w.writeVarInt(msg.stream_count)
293
+ w.writeString(msg.reason_phrase)
294
+ }
295
+
296
+ function encodeUnsubscribePayload(
297
+ msg: Draft10Message & { type: 'unsubscribe' },
298
+ w: BufferWriter,
299
+ ): void {
300
+ w.writeVarInt(msg.subscribe_id)
301
+ }
302
+
303
+ function encodeAnnouncePayload(msg: Draft10Message & { type: 'announce' }, w: BufferWriter): void {
304
+ w.writeTuple(msg.track_namespace)
305
+ encodeParams(msg.parameters, w)
306
+ }
307
+
308
+ function encodeAnnounceOkPayload(
309
+ msg: Draft10Message & { type: 'announce_ok' },
310
+ w: BufferWriter,
311
+ ): void {
312
+ w.writeTuple(msg.track_namespace)
313
+ }
314
+
315
+ function encodeAnnounceErrorPayload(
316
+ msg: Draft10Message & { type: 'announce_error' },
317
+ w: BufferWriter,
318
+ ): void {
319
+ w.writeTuple(msg.track_namespace)
320
+ w.writeVarInt(msg.error_code)
321
+ w.writeString(msg.reason_phrase)
322
+ }
323
+
324
+ function encodeUnannouncePayload(
325
+ msg: Draft10Message & { type: 'unannounce' },
326
+ w: BufferWriter,
327
+ ): void {
328
+ w.writeTuple(msg.track_namespace)
329
+ }
330
+
331
+ function encodeAnnounceCancelPayload(
332
+ msg: Draft10Message & { type: 'announce_cancel' },
333
+ w: BufferWriter,
334
+ ): void {
335
+ w.writeTuple(msg.track_namespace)
336
+ w.writeVarInt(msg.error_code)
337
+ w.writeString(msg.reason_phrase)
338
+ }
339
+
340
+ function encodeSubscribeAnnouncesPayload(
341
+ msg: Draft10Message & { type: 'subscribe_announces' },
342
+ w: BufferWriter,
343
+ ): void {
344
+ w.writeTuple(msg.track_namespace_prefix)
345
+ encodeParams(msg.parameters, w)
346
+ }
347
+
348
+ function encodeSubscribeAnnouncesOkPayload(
349
+ msg: Draft10Message & { type: 'subscribe_announces_ok' },
350
+ w: BufferWriter,
351
+ ): void {
352
+ w.writeTuple(msg.track_namespace_prefix)
353
+ }
354
+
355
+ function encodeSubscribeAnnouncesErrorPayload(
356
+ msg: Draft10Message & { type: 'subscribe_announces_error' },
357
+ w: BufferWriter,
358
+ ): void {
359
+ w.writeTuple(msg.track_namespace_prefix)
360
+ w.writeVarInt(msg.error_code)
361
+ w.writeString(msg.reason_phrase)
362
+ }
363
+
364
+ function encodeUnsubscribeAnnouncesPayload(
365
+ msg: Draft10Message & { type: 'unsubscribe_announces' },
366
+ w: BufferWriter,
367
+ ): void {
368
+ w.writeTuple(msg.track_namespace_prefix)
369
+ }
370
+
371
+ function encodeFetchPayload(msg: Draft10Message & { type: 'fetch' }, w: BufferWriter): void {
372
+ w.writeVarInt(msg.subscribe_id)
373
+ w.writeUint8(msg.subscriber_priority)
374
+ w.writeUint8(msg.group_order)
375
+ w.writeVarInt(msg.fetch_type)
376
+ const ft = Number(msg.fetch_type)
377
+ if (ft === 1 && msg.standalone) {
378
+ w.writeTuple(msg.standalone.track_namespace)
379
+ w.writeString(msg.standalone.track_name)
380
+ w.writeVarInt(msg.standalone.start_group)
381
+ w.writeVarInt(msg.standalone.start_object)
382
+ w.writeVarInt(msg.standalone.end_group)
383
+ w.writeVarInt(msg.standalone.end_object)
384
+ } else if (ft === 2 && msg.joining) {
385
+ w.writeVarInt(msg.joining.joining_subscribe_id)
386
+ w.writeVarInt(msg.joining.preceding_group_offset)
387
+ }
388
+ encodeParams(msg.parameters, w)
389
+ }
390
+
391
+ function encodeFetchOkPayload(msg: Draft10Message & { type: 'fetch_ok' }, w: BufferWriter): void {
392
+ w.writeVarInt(msg.subscribe_id)
393
+ w.writeUint8(msg.group_order)
394
+ w.writeUint8(msg.end_of_track)
395
+ w.writeVarInt(msg.largest_group_id)
396
+ w.writeVarInt(msg.largest_object_id)
397
+ encodeParams(msg.parameters, w)
398
+ }
399
+
400
+ function encodeFetchErrorPayload(
401
+ msg: Draft10Message & { type: 'fetch_error' },
402
+ w: BufferWriter,
403
+ ): void {
404
+ w.writeVarInt(msg.subscribe_id)
405
+ w.writeVarInt(msg.error_code)
406
+ w.writeString(msg.reason_phrase)
407
+ }
408
+
409
+ function encodeFetchCancelPayload(
410
+ msg: Draft10Message & { type: 'fetch_cancel' },
411
+ w: BufferWriter,
412
+ ): void {
413
+ w.writeVarInt(msg.subscribe_id)
414
+ }
415
+
416
+ function encodeTrackStatusRequestPayload(
417
+ msg: Draft10Message & { type: 'track_status_request' },
418
+ w: BufferWriter,
419
+ ): void {
420
+ w.writeTuple(msg.track_namespace)
421
+ w.writeString(msg.track_name)
422
+ }
423
+
424
+ function encodeTrackStatusPayload(
425
+ msg: Draft10Message & { type: 'track_status' },
426
+ w: BufferWriter,
427
+ ): void {
428
+ w.writeTuple(msg.track_namespace)
429
+ w.writeString(msg.track_name)
430
+ w.writeVarInt(msg.status_code)
431
+ w.writeVarInt(msg.last_group_id)
432
+ w.writeVarInt(msg.last_object_id)
433
+ }
434
+
435
+ function encodeGoAwayPayload(msg: Draft10Message & { type: 'goaway' }, w: BufferWriter): void {
436
+ w.writeString(msg.new_session_uri)
437
+ }
438
+
439
+ function encodeMaxSubscribeIdPayload(
440
+ msg: Draft10Message & { type: 'max_subscribe_id' },
441
+ w: BufferWriter,
442
+ ): void {
443
+ w.writeVarInt(msg.subscribe_id)
444
+ }
445
+
446
+ function encodeSubscribesBlockedPayload(
447
+ msg: Draft10Message & { type: 'subscribes_blocked' },
448
+ w: BufferWriter,
449
+ ): void {
450
+ w.writeVarInt(msg.maximum_subscribe_id)
451
+ }
452
+
453
+ // ─── Payload Decoders ──────────────────────────────────────────────────────────
454
+
455
+ function decodeClientSetupPayload(r: BufferReader): Draft10Message {
456
+ const numVersions = Number(r.readVarInt())
457
+ if (numVersions === 0) {
458
+ throw new DecodeError('CONSTRAINT_VIOLATION', 'supported_versions must not be empty', r.offset)
459
+ }
460
+ const supported_versions: bigint[] = []
461
+ for (let i = 0; i < numVersions; i++) supported_versions.push(r.readVarInt())
462
+ const parameters = decodeSetupParams(r)
463
+ return { type: 'client_setup', supported_versions, parameters }
464
+ }
465
+
466
+ function decodeServerSetupPayload(r: BufferReader): Draft10Message {
467
+ const selected_version = r.readVarInt()
468
+ const parameters = decodeSetupParams(r)
469
+ return { type: 'server_setup', selected_version, parameters }
470
+ }
471
+
472
+ function decodeSubscribePayload(r: BufferReader): Draft10Message {
473
+ const subscribe_id = r.readVarInt()
474
+ const track_alias = r.readVarInt()
475
+ const track_namespace = r.readTuple()
476
+ const track_name = r.readString()
477
+ const subscriber_priority = r.readUint8()
478
+ const group_order = r.readUint8()
479
+ const filter_type = r.readVarInt()
480
+ const ft = Number(filter_type)
481
+ // Draft-09 removed LatestGroup (filter_type=1), valid values are 2-4
482
+ if (ft < 2 || ft > 4) {
483
+ throw new DecodeError('CONSTRAINT_VIOLATION', `Invalid filter_type: ${ft}`, r.offset)
484
+ }
485
+ let start_group: bigint | undefined
486
+ let start_object: bigint | undefined
487
+ let end_group: bigint | undefined
488
+ if (ft === 3 || ft === 4) {
489
+ start_group = r.readVarInt()
490
+ start_object = r.readVarInt()
491
+ }
492
+ if (ft === 4) {
493
+ end_group = r.readVarInt()
494
+ }
495
+ const parameters = decodeParams(r)
496
+ const msg: Record<string, unknown> = {
497
+ type: 'subscribe',
498
+ subscribe_id,
499
+ track_alias,
500
+ track_namespace,
501
+ track_name,
502
+ subscriber_priority,
503
+ group_order,
504
+ filter_type,
505
+ parameters,
506
+ }
507
+ if (start_group !== undefined) msg.start_group = start_group
508
+ if (start_object !== undefined) msg.start_object = start_object
509
+ if (end_group !== undefined) msg.end_group = end_group
510
+ return msg as unknown as Draft10Message
511
+ }
512
+
513
+ function decodeSubscribeOkPayload(r: BufferReader): Draft10Message {
514
+ const subscribe_id = r.readVarInt()
515
+ const expires = r.readVarInt()
516
+ const group_order = r.readUint8()
517
+ const content_exists = r.readUint8()
518
+ let largest_group_id: bigint | undefined
519
+ let largest_object_id: bigint | undefined
520
+ if (content_exists === 1) {
521
+ largest_group_id = r.readVarInt()
522
+ largest_object_id = r.readVarInt()
523
+ }
524
+ const parameters = decodeParams(r)
525
+ const msg: Record<string, unknown> = {
526
+ type: 'subscribe_ok',
527
+ subscribe_id,
528
+ expires,
529
+ group_order,
530
+ content_exists,
531
+ parameters,
532
+ }
533
+ if (largest_group_id !== undefined) msg.largest_group_id = largest_group_id
534
+ if (largest_object_id !== undefined) msg.largest_object_id = largest_object_id
535
+ return msg as unknown as Draft10Message
536
+ }
537
+
538
+ function decodeSubscribeErrorPayload(r: BufferReader): Draft10Message {
539
+ const subscribe_id = r.readVarInt()
540
+ const error_code = r.readVarInt()
541
+ const reason_phrase = r.readString()
542
+ const track_alias = r.readVarInt()
543
+ return {
544
+ type: 'subscribe_error',
545
+ subscribe_id,
546
+ error_code,
547
+ reason_phrase,
548
+ track_alias,
549
+ }
550
+ }
551
+
552
+ function decodeSubscribeUpdatePayload(r: BufferReader): Draft10Message {
553
+ const subscribe_id = r.readVarInt()
554
+ const start_group = r.readVarInt()
555
+ const start_object = r.readVarInt()
556
+ const end_group = r.readVarInt()
557
+ const subscriber_priority = r.readUint8()
558
+ const parameters = decodeParams(r)
559
+ return {
560
+ type: 'subscribe_update',
561
+ subscribe_id,
562
+ start_group,
563
+ start_object,
564
+ end_group,
565
+ subscriber_priority,
566
+ parameters,
567
+ }
568
+ }
569
+
570
+ function decodeSubscribeDonePayload(r: BufferReader): Draft10Message {
571
+ const subscribe_id = r.readVarInt()
572
+ const status_code = r.readVarInt()
573
+ const stream_count = r.readVarInt()
574
+ const reason_phrase = r.readString()
575
+ return {
576
+ type: 'subscribe_done',
577
+ subscribe_id,
578
+ status_code,
579
+ stream_count,
580
+ reason_phrase,
581
+ }
582
+ }
583
+
584
+ function decodeUnsubscribePayload(r: BufferReader): Draft10Message {
585
+ const subscribe_id = r.readVarInt()
586
+ return { type: 'unsubscribe', subscribe_id }
587
+ }
588
+
589
+ function decodeAnnouncePayload(r: BufferReader): Draft10Message {
590
+ const track_namespace = r.readTuple()
591
+ const parameters = decodeParams(r)
592
+ return { type: 'announce', track_namespace, parameters }
593
+ }
594
+
595
+ function decodeAnnounceOkPayload(r: BufferReader): Draft10Message {
596
+ const track_namespace = r.readTuple()
597
+ return { type: 'announce_ok', track_namespace }
598
+ }
599
+
600
+ function decodeAnnounceErrorPayload(r: BufferReader): Draft10Message {
601
+ const track_namespace = r.readTuple()
602
+ const error_code = r.readVarInt()
603
+ const reason_phrase = r.readString()
604
+ return { type: 'announce_error', track_namespace, error_code, reason_phrase }
605
+ }
606
+
607
+ function decodeUnannouncePayload(r: BufferReader): Draft10Message {
608
+ const track_namespace = r.readTuple()
609
+ return { type: 'unannounce', track_namespace }
610
+ }
611
+
612
+ function decodeAnnounceCancelPayload(r: BufferReader): Draft10Message {
613
+ const track_namespace = r.readTuple()
614
+ const error_code = r.readVarInt()
615
+ const reason_phrase = r.readString()
616
+ return { type: 'announce_cancel', track_namespace, error_code, reason_phrase }
617
+ }
618
+
619
+ function decodeSubscribeAnnouncesPayload(r: BufferReader): Draft10Message {
620
+ const track_namespace_prefix = r.readTuple()
621
+ const parameters = decodeParams(r)
622
+ return { type: 'subscribe_announces', track_namespace_prefix, parameters }
623
+ }
624
+
625
+ function decodeSubscribeAnnouncesOkPayload(r: BufferReader): Draft10Message {
626
+ const track_namespace_prefix = r.readTuple()
627
+ return { type: 'subscribe_announces_ok', track_namespace_prefix }
628
+ }
629
+
630
+ function decodeSubscribeAnnouncesErrorPayload(r: BufferReader): Draft10Message {
631
+ const track_namespace_prefix = r.readTuple()
632
+ const error_code = r.readVarInt()
633
+ const reason_phrase = r.readString()
634
+ return {
635
+ type: 'subscribe_announces_error',
636
+ track_namespace_prefix,
637
+ error_code,
638
+ reason_phrase,
639
+ }
640
+ }
641
+
642
+ function decodeUnsubscribeAnnouncesPayload(r: BufferReader): Draft10Message {
643
+ const track_namespace_prefix = r.readTuple()
644
+ return { type: 'unsubscribe_announces', track_namespace_prefix }
645
+ }
646
+
647
+ function decodeFetchPayload(r: BufferReader): Draft10Message {
648
+ const subscribe_id = r.readVarInt()
649
+ const subscriber_priority = r.readUint8()
650
+ const group_order = r.readUint8()
651
+ const fetch_type = r.readVarInt()
652
+ const ft = Number(fetch_type)
653
+
654
+ if (ft < 1 || ft > 2) {
655
+ throw new DecodeError('CONSTRAINT_VIOLATION', `Invalid fetch_type: ${ft}`, r.offset)
656
+ }
657
+
658
+ let standalone: StandaloneFetch | undefined
659
+ let joining: JoiningFetch | undefined
660
+
661
+ if (ft === 1) {
662
+ const track_namespace = r.readTuple()
663
+ const track_name = r.readString()
664
+ const start_group = r.readVarInt()
665
+ const start_object = r.readVarInt()
666
+ const end_group = r.readVarInt()
667
+ const end_object = r.readVarInt()
668
+ standalone = {
669
+ track_namespace,
670
+ track_name,
671
+ start_group,
672
+ start_object,
673
+ end_group,
674
+ end_object,
675
+ }
676
+ } else {
677
+ const joining_subscribe_id = r.readVarInt()
678
+ const preceding_group_offset = r.readVarInt()
679
+ joining = { joining_subscribe_id, preceding_group_offset }
680
+ }
681
+
682
+ const parameters = decodeParams(r)
683
+ return {
684
+ type: 'fetch',
685
+ subscribe_id,
686
+ subscriber_priority,
687
+ group_order,
688
+ fetch_type,
689
+ standalone,
690
+ joining,
691
+ parameters,
692
+ } as Draft10Fetch
693
+ }
694
+
695
+ function decodeFetchOkPayload(r: BufferReader): Draft10Message {
696
+ const subscribe_id = r.readVarInt()
697
+ const group_order = r.readUint8()
698
+ const end_of_track = r.readUint8()
699
+ const largest_group_id = r.readVarInt()
700
+ const largest_object_id = r.readVarInt()
701
+ const parameters = decodeParams(r)
702
+ return {
703
+ type: 'fetch_ok',
704
+ subscribe_id,
705
+ group_order,
706
+ end_of_track,
707
+ largest_group_id,
708
+ largest_object_id,
709
+ parameters,
710
+ }
711
+ }
712
+
713
+ function decodeFetchErrorPayload(r: BufferReader): Draft10Message {
714
+ const subscribe_id = r.readVarInt()
715
+ const error_code = r.readVarInt()
716
+ const reason_phrase = r.readString()
717
+ return { type: 'fetch_error', subscribe_id, error_code, reason_phrase }
718
+ }
719
+
720
+ function decodeFetchCancelPayload(r: BufferReader): Draft10Message {
721
+ const subscribe_id = r.readVarInt()
722
+ return { type: 'fetch_cancel', subscribe_id }
723
+ }
724
+
725
+ function decodeTrackStatusRequestPayload(r: BufferReader): Draft10Message {
726
+ const track_namespace = r.readTuple()
727
+ const track_name = r.readString()
728
+ return { type: 'track_status_request', track_namespace, track_name }
729
+ }
730
+
731
+ function decodeTrackStatusPayload(r: BufferReader): Draft10Message {
732
+ const track_namespace = r.readTuple()
733
+ const track_name = r.readString()
734
+ const status_code = r.readVarInt()
735
+ const last_group_id = r.readVarInt()
736
+ const last_object_id = r.readVarInt()
737
+ return {
738
+ type: 'track_status',
739
+ track_namespace,
740
+ track_name,
741
+ status_code,
742
+ last_group_id,
743
+ last_object_id,
744
+ }
745
+ }
746
+
747
+ function decodeGoAwayPayload(r: BufferReader): Draft10Message {
748
+ const new_session_uri = r.readString()
749
+ return { type: 'goaway', new_session_uri }
750
+ }
751
+
752
+ function decodeMaxSubscribeIdPayload(r: BufferReader): Draft10Message {
753
+ const subscribe_id = r.readVarInt()
754
+ return { type: 'max_subscribe_id', subscribe_id }
755
+ }
756
+
757
+ function decodeSubscribesBlockedPayload(r: BufferReader): Draft10Message {
758
+ const maximum_subscribe_id = r.readVarInt()
759
+ return { type: 'subscribes_blocked', maximum_subscribe_id }
760
+ }
761
+
762
+ // ─── Payload dispatch tables ───────────────────────────────────────────────────
763
+
764
+ const payloadDecoders: ReadonlyMap<bigint, (r: BufferReader) => Draft10Message> = new Map([
765
+ [MSG_CLIENT_SETUP, decodeClientSetupPayload],
766
+ [MSG_SERVER_SETUP, decodeServerSetupPayload],
767
+ [MSG_SUBSCRIBE, decodeSubscribePayload],
768
+ [MSG_SUBSCRIBE_OK, decodeSubscribeOkPayload],
769
+ [MSG_SUBSCRIBE_ERROR, decodeSubscribeErrorPayload],
770
+ [MSG_SUBSCRIBE_UPDATE, decodeSubscribeUpdatePayload],
771
+ [MSG_SUBSCRIBE_DONE, decodeSubscribeDonePayload],
772
+ [MSG_UNSUBSCRIBE, decodeUnsubscribePayload],
773
+ [MSG_ANNOUNCE, decodeAnnouncePayload],
774
+ [MSG_ANNOUNCE_OK, decodeAnnounceOkPayload],
775
+ [MSG_ANNOUNCE_ERROR, decodeAnnounceErrorPayload],
776
+ [MSG_UNANNOUNCE, decodeUnannouncePayload],
777
+ [MSG_ANNOUNCE_CANCEL, decodeAnnounceCancelPayload],
778
+ [MSG_SUBSCRIBE_ANNOUNCES, decodeSubscribeAnnouncesPayload],
779
+ [MSG_SUBSCRIBE_ANNOUNCES_OK, decodeSubscribeAnnouncesOkPayload],
780
+ [MSG_SUBSCRIBE_ANNOUNCES_ERROR, decodeSubscribeAnnouncesErrorPayload],
781
+ [MSG_UNSUBSCRIBE_ANNOUNCES, decodeUnsubscribeAnnouncesPayload],
782
+ [MSG_FETCH, decodeFetchPayload],
783
+ [MSG_FETCH_OK, decodeFetchOkPayload],
784
+ [MSG_FETCH_ERROR, decodeFetchErrorPayload],
785
+ [MSG_FETCH_CANCEL, decodeFetchCancelPayload],
786
+ [MSG_TRACK_STATUS_REQUEST, decodeTrackStatusRequestPayload],
787
+ [MSG_TRACK_STATUS, decodeTrackStatusPayload],
788
+ [MSG_GOAWAY, decodeGoAwayPayload],
789
+ [MSG_MAX_SUBSCRIBE_ID, decodeMaxSubscribeIdPayload],
790
+ [MSG_SUBSCRIBES_BLOCKED, decodeSubscribesBlockedPayload],
791
+ ])
792
+
793
+ // ─── Public API ────────────────────────────────────────────────────────────────
794
+
795
+ export function encodeMessage(message: Draft10Message): Uint8Array {
796
+ const typeId = MESSAGE_ID_MAP.get(message.type)
797
+ if (typeId === undefined) throw new Error(`Unknown message type: ${message.type}`)
798
+
799
+ const payloadWriter = new BufferWriter()
800
+ encodePayload(message, payloadWriter)
801
+ const payload = payloadWriter.finishView()
802
+
803
+ const writer = new BufferWriter(payload.byteLength + 16)
804
+ writer.writeVarInt(typeId)
805
+ writer.writeVarInt(payload.byteLength)
806
+ writer.writeBytes(payload)
807
+ return writer.finish()
808
+ }
809
+
810
+ function encodePayload(msg: Draft10Message, w: BufferWriter): void {
811
+ switch (msg.type) {
812
+ case 'client_setup':
813
+ return encodeClientSetupPayload(msg, w)
814
+ case 'server_setup':
815
+ return encodeServerSetupPayload(msg, w)
816
+ case 'subscribe':
817
+ return encodeSubscribePayload(msg, w)
818
+ case 'subscribe_ok':
819
+ return encodeSubscribeOkPayload(msg, w)
820
+ case 'subscribe_error':
821
+ return encodeSubscribeErrorPayload(msg, w)
822
+ case 'subscribe_update':
823
+ return encodeSubscribeUpdatePayload(msg, w)
824
+ case 'subscribe_done':
825
+ return encodeSubscribeDonePayload(msg, w)
826
+ case 'unsubscribe':
827
+ return encodeUnsubscribePayload(msg, w)
828
+ case 'announce':
829
+ return encodeAnnouncePayload(msg, w)
830
+ case 'announce_ok':
831
+ return encodeAnnounceOkPayload(msg, w)
832
+ case 'announce_error':
833
+ return encodeAnnounceErrorPayload(msg, w)
834
+ case 'unannounce':
835
+ return encodeUnannouncePayload(msg, w)
836
+ case 'announce_cancel':
837
+ return encodeAnnounceCancelPayload(msg, w)
838
+ case 'subscribe_announces':
839
+ return encodeSubscribeAnnouncesPayload(msg, w)
840
+ case 'subscribe_announces_ok':
841
+ return encodeSubscribeAnnouncesOkPayload(msg, w)
842
+ case 'subscribe_announces_error':
843
+ return encodeSubscribeAnnouncesErrorPayload(msg, w)
844
+ case 'unsubscribe_announces':
845
+ return encodeUnsubscribeAnnouncesPayload(msg, w)
846
+ case 'fetch':
847
+ return encodeFetchPayload(msg, w)
848
+ case 'fetch_ok':
849
+ return encodeFetchOkPayload(msg, w)
850
+ case 'fetch_error':
851
+ return encodeFetchErrorPayload(msg, w)
852
+ case 'fetch_cancel':
853
+ return encodeFetchCancelPayload(msg, w)
854
+ case 'track_status_request':
855
+ return encodeTrackStatusRequestPayload(msg, w)
856
+ case 'track_status':
857
+ return encodeTrackStatusPayload(msg, w)
858
+ case 'goaway':
859
+ return encodeGoAwayPayload(msg, w)
860
+ case 'max_subscribe_id':
861
+ return encodeMaxSubscribeIdPayload(msg, w)
862
+ case 'subscribes_blocked':
863
+ return encodeSubscribesBlockedPayload(msg, w)
864
+ default: {
865
+ const _exhaustive: never = msg
866
+ throw new Error(`Unhandled message type: ${(_exhaustive as Draft10Message).type}`)
867
+ }
868
+ }
869
+ }
870
+
871
+ export function decodeMessage(bytes: Uint8Array): DecodeResult<Draft10Message> {
872
+ try {
873
+ const reader = new BufferReader(bytes)
874
+ const typeId = reader.readVarInt()
875
+ const payloadLength = Number(reader.readVarInt())
876
+ const payloadBytes = reader.readBytes(payloadLength)
877
+ const payloadReader = new BufferReader(payloadBytes)
878
+
879
+ const decoder = payloadDecoders.get(typeId)
880
+ if (!decoder) {
881
+ return {
882
+ ok: false,
883
+ error: new DecodeError(
884
+ 'UNKNOWN_MESSAGE_TYPE',
885
+ `Unknown message type ID: 0x${typeId.toString(16)}`,
886
+ 0,
887
+ ),
888
+ }
889
+ }
890
+
891
+ const message = decoder(payloadReader)
892
+ return { ok: true, value: message, bytesRead: reader.offset }
893
+ } catch (e) {
894
+ if (e instanceof DecodeError) return { ok: false, error: e }
895
+ throw e
896
+ }
897
+ }
898
+
899
+ export {
900
+ decodeDatagram,
901
+ decodeDatagramStatus,
902
+ decodeDataStream,
903
+ decodeFetchStream,
904
+ decodeSubgroupStream,
905
+ encodeDatagram,
906
+ encodeDatagramStatus,
907
+ encodeFetchStream,
908
+ encodeSubgroupStream,
909
+ } from './data-streams.js'
910
+
911
+ export function createStreamDecoder(): TransformStream<Uint8Array, Draft10Message> {
912
+ let buffer = new Uint8Array(0)
913
+ let offset = 0
914
+ return new TransformStream<Uint8Array, Draft10Message>({
915
+ transform(chunk, controller) {
916
+ if (offset > 0) {
917
+ buffer = buffer.subarray(offset)
918
+ offset = 0
919
+ }
920
+ const newBuffer = new Uint8Array(buffer.length + chunk.length)
921
+ newBuffer.set(buffer, 0)
922
+ newBuffer.set(chunk, buffer.length)
923
+ buffer = newBuffer
924
+ while (offset < buffer.length) {
925
+ const result = decodeMessage(buffer.subarray(offset))
926
+ if (!result.ok) {
927
+ if (result.error.code === 'UNEXPECTED_END') break
928
+ controller.error(result.error)
929
+ return
930
+ }
931
+ controller.enqueue(result.value)
932
+ offset += result.bytesRead
933
+ }
934
+ },
935
+ flush(controller) {
936
+ if (offset < buffer.length)
937
+ controller.error(new DecodeError('UNEXPECTED_END', 'Stream ended with incomplete data', 0))
938
+ },
939
+ })
940
+ }
941
+
942
+ // ─── Codec Factory ─────────────────────────────────────────────────────────────
943
+
944
+ export interface Draft10Codec extends BaseCodec<Draft10Message> {
945
+ readonly draft: '10'
946
+ encodeSubgroupStream(stream: SubgroupStream): Uint8Array
947
+ encodeDatagram(dg: DatagramObject): Uint8Array
948
+ encodeDatagramStatus(dg: DatagramStatusObject): Uint8Array
949
+ encodeFetchStream(stream: FetchStream): Uint8Array
950
+ decodeSubgroupStream(bytes: Uint8Array): DecodeResult<SubgroupStream>
951
+ decodeDatagram(bytes: Uint8Array): DecodeResult<DatagramObject>
952
+ decodeDatagramStatus(bytes: Uint8Array): DecodeResult<DatagramStatusObject>
953
+ decodeFetchStream(bytes: Uint8Array): DecodeResult<FetchStream>
954
+ decodeDataStream(
955
+ streamType: 'subgroup' | 'datagram' | 'datagram_status' | 'fetch',
956
+ bytes: Uint8Array,
957
+ ): DecodeResult<Draft10DataStream>
958
+ createStreamDecoder(): TransformStream<Uint8Array, Draft10Message>
959
+ }
960
+
961
+ export function createDraft10Codec(): Draft10Codec {
962
+ return {
963
+ draft: '10',
964
+ encodeMessage,
965
+ decodeMessage,
966
+ encodeSubgroupStream,
967
+ encodeDatagram,
968
+ encodeDatagramStatus,
969
+ encodeFetchStream,
970
+ decodeSubgroupStream,
971
+ decodeDatagram,
972
+ decodeDatagramStatus,
973
+ decodeFetchStream,
974
+ decodeDataStream,
975
+ createStreamDecoder,
976
+ }
977
+ }