@norskvideo/moq-net 0.1.2 → 0.1.4

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 (310) hide show
  1. package/README.md +1 -0
  2. package/announced.d.ts +111 -21
  3. package/announced.d.ts.map +1 -1
  4. package/announced.js +213 -40
  5. package/announced.js.map +1 -1
  6. package/broadcast.d.ts +80 -25
  7. package/broadcast.d.ts.map +1 -1
  8. package/broadcast.js +270 -49
  9. package/broadcast.js.map +1 -1
  10. package/connection/accept.d.ts +6 -0
  11. package/connection/accept.d.ts.map +1 -1
  12. package/connection/accept.js +42 -13
  13. package/connection/accept.js.map +1 -1
  14. package/connection/browser.d.ts +5 -0
  15. package/connection/browser.d.ts.map +1 -0
  16. package/connection/browser.js +31 -0
  17. package/connection/browser.js.map +1 -0
  18. package/connection/connect.d.ts +43 -1
  19. package/connection/connect.d.ts.map +1 -1
  20. package/connection/connect.js +118 -123
  21. package/connection/connect.js.map +1 -1
  22. package/connection/established.d.ts +43 -16
  23. package/connection/established.d.ts.map +1 -1
  24. package/connection/established.js.map +1 -1
  25. package/connection/handshake.d.ts +12 -1
  26. package/connection/handshake.d.ts.map +1 -1
  27. package/connection/handshake.js +30 -14
  28. package/connection/handshake.js.map +1 -1
  29. package/connection/index.d.ts +8 -0
  30. package/connection/index.d.ts.map +1 -1
  31. package/connection/index.js +6 -0
  32. package/connection/index.js.map +1 -1
  33. package/connection/reload.d.ts +66 -9
  34. package/connection/reload.d.ts.map +1 -1
  35. package/connection/reload.js +192 -66
  36. package/connection/reload.js.map +1 -1
  37. package/connection/stats.d.ts +92 -0
  38. package/connection/stats.d.ts.map +1 -0
  39. package/connection/stats.js +35 -0
  40. package/connection/stats.js.map +1 -0
  41. package/connection/transport.d.ts +10 -0
  42. package/connection/transport.d.ts.map +1 -0
  43. package/connection/transport.js +12 -0
  44. package/connection/transport.js.map +1 -0
  45. package/consume.d.ts +44 -0
  46. package/consume.d.ts.map +1 -0
  47. package/consume.js +60 -0
  48. package/consume.js.map +1 -0
  49. package/datagram.d.ts +23 -0
  50. package/datagram.d.ts.map +1 -0
  51. package/datagram.js +3 -0
  52. package/datagram.js.map +1 -0
  53. package/error.d.ts +76 -0
  54. package/error.d.ts.map +1 -0
  55. package/error.js +107 -0
  56. package/error.js.map +1 -0
  57. package/group.d.ts +143 -38
  58. package/group.d.ts.map +1 -1
  59. package/group.js +270 -68
  60. package/group.js.map +1 -1
  61. package/ietf/adapter.d.ts +2 -2
  62. package/ietf/adapter.d.ts.map +1 -1
  63. package/ietf/adapter.js +20 -10
  64. package/ietf/adapter.js.map +1 -1
  65. package/ietf/aliases.d.ts +73 -5
  66. package/ietf/aliases.d.ts.map +1 -1
  67. package/ietf/aliases.js +121 -14
  68. package/ietf/aliases.js.map +1 -1
  69. package/ietf/cluster.d.ts +141 -0
  70. package/ietf/cluster.d.ts.map +1 -0
  71. package/ietf/cluster.js +204 -0
  72. package/ietf/cluster.js.map +1 -0
  73. package/ietf/connection.d.ts +39 -6
  74. package/ietf/connection.d.ts.map +1 -1
  75. package/ietf/connection.js +73 -12
  76. package/ietf/connection.js.map +1 -1
  77. package/ietf/fetch.d.ts +17 -0
  78. package/ietf/fetch.d.ts.map +1 -1
  79. package/ietf/fetch.js +21 -0
  80. package/ietf/fetch.js.map +1 -1
  81. package/ietf/filter.d.ts +87 -0
  82. package/ietf/filter.d.ts.map +1 -0
  83. package/ietf/filter.js +292 -0
  84. package/ietf/filter.js.map +1 -0
  85. package/ietf/index.d.ts +2 -0
  86. package/ietf/index.d.ts.map +1 -1
  87. package/ietf/index.js +3 -0
  88. package/ietf/index.js.map +1 -1
  89. package/ietf/namespace.d.ts +6 -0
  90. package/ietf/namespace.d.ts.map +1 -1
  91. package/ietf/namespace.js +27 -2
  92. package/ietf/namespace.js.map +1 -1
  93. package/ietf/object.d.ts +54 -6
  94. package/ietf/object.d.ts.map +1 -1
  95. package/ietf/object.js +178 -25
  96. package/ietf/object.js.map +1 -1
  97. package/ietf/parameters.d.ts +35 -10
  98. package/ietf/parameters.d.ts.map +1 -1
  99. package/ietf/parameters.js +236 -45
  100. package/ietf/parameters.js.map +1 -1
  101. package/ietf/priority.d.ts +5 -0
  102. package/ietf/priority.d.ts.map +1 -0
  103. package/ietf/priority.js +10 -0
  104. package/ietf/priority.js.map +1 -0
  105. package/ietf/properties.d.ts +13 -2
  106. package/ietf/properties.d.ts.map +1 -1
  107. package/ietf/properties.js +65 -8
  108. package/ietf/properties.js.map +1 -1
  109. package/ietf/publish.d.ts.map +1 -1
  110. package/ietf/publish.js +13 -3
  111. package/ietf/publish.js.map +1 -1
  112. package/ietf/publish_namespace.d.ts +16 -2
  113. package/ietf/publish_namespace.d.ts.map +1 -1
  114. package/ietf/publish_namespace.js +25 -6
  115. package/ietf/publish_namespace.js.map +1 -1
  116. package/ietf/publisher.d.ts +40 -7
  117. package/ietf/publisher.d.ts.map +1 -1
  118. package/ietf/publisher.js +751 -134
  119. package/ietf/publisher.js.map +1 -1
  120. package/ietf/request.js +1 -1
  121. package/ietf/request.js.map +1 -1
  122. package/ietf/solicit.d.ts +41 -0
  123. package/ietf/solicit.d.ts.map +1 -0
  124. package/ietf/solicit.js +47 -0
  125. package/ietf/solicit.js.map +1 -0
  126. package/ietf/subscribe.d.ts +41 -2
  127. package/ietf/subscribe.d.ts.map +1 -1
  128. package/ietf/subscribe.js +103 -22
  129. package/ietf/subscribe.js.map +1 -1
  130. package/ietf/subscribe_namespace.d.ts +21 -7
  131. package/ietf/subscribe_namespace.d.ts.map +1 -1
  132. package/ietf/subscribe_namespace.js +31 -14
  133. package/ietf/subscribe_namespace.js.map +1 -1
  134. package/ietf/subscriber.d.ts +20 -7
  135. package/ietf/subscriber.d.ts.map +1 -1
  136. package/ietf/subscriber.js +512 -142
  137. package/ietf/subscriber.js.map +1 -1
  138. package/ietf/version.d.ts +7 -1
  139. package/ietf/version.d.ts.map +1 -1
  140. package/ietf/version.js +7 -0
  141. package/ietf/version.js.map +1 -1
  142. package/index.d.ts +10 -5
  143. package/index.d.ts.map +1 -1
  144. package/index.js +10 -5
  145. package/index.js.map +1 -1
  146. package/internal.d.ts +29 -0
  147. package/internal.d.ts.map +1 -0
  148. package/internal.js +8 -0
  149. package/internal.js.map +1 -0
  150. package/lite/announce.d.ts +62 -15
  151. package/lite/announce.d.ts.map +1 -1
  152. package/lite/announce.js +230 -94
  153. package/lite/announce.js.map +1 -1
  154. package/lite/connection.d.ts +69 -20
  155. package/lite/connection.d.ts.map +1 -1
  156. package/lite/connection.js +128 -81
  157. package/lite/connection.js.map +1 -1
  158. package/lite/datagram.d.ts +23 -0
  159. package/lite/datagram.d.ts.map +1 -0
  160. package/lite/datagram.js +57 -0
  161. package/lite/datagram.js.map +1 -0
  162. package/lite/datagram_stream.d.ts +8 -0
  163. package/lite/datagram_stream.d.ts.map +1 -0
  164. package/lite/datagram_stream.js +44 -0
  165. package/lite/datagram_stream.js.map +1 -0
  166. package/lite/fetch.d.ts.map +1 -1
  167. package/lite/fetch.js +2 -2
  168. package/lite/fetch.js.map +1 -1
  169. package/lite/index.d.ts +3 -0
  170. package/lite/index.d.ts.map +1 -1
  171. package/lite/index.js +3 -0
  172. package/lite/index.js.map +1 -1
  173. package/lite/priority.d.ts +67 -0
  174. package/lite/priority.d.ts.map +1 -0
  175. package/lite/priority.js +114 -0
  176. package/lite/priority.js.map +1 -0
  177. package/lite/probe.d.ts +18 -2
  178. package/lite/probe.d.ts.map +1 -1
  179. package/lite/probe.js +24 -22
  180. package/lite/probe.js.map +1 -1
  181. package/lite/publisher.d.ts +14 -7
  182. package/lite/publisher.d.ts.map +1 -1
  183. package/lite/publisher.js +406 -84
  184. package/lite/publisher.js.map +1 -1
  185. package/lite/setup.d.ts +83 -6
  186. package/lite/setup.d.ts.map +1 -1
  187. package/lite/setup.js +203 -31
  188. package/lite/setup.js.map +1 -1
  189. package/lite/stream.d.ts +12 -3
  190. package/lite/stream.d.ts.map +1 -1
  191. package/lite/stream.js +7 -4
  192. package/lite/stream.js.map +1 -1
  193. package/lite/subscribe.d.ts +37 -23
  194. package/lite/subscribe.d.ts.map +1 -1
  195. package/lite/subscribe.js +70 -55
  196. package/lite/subscribe.js.map +1 -1
  197. package/lite/subscriber.d.ts +29 -23
  198. package/lite/subscriber.d.ts.map +1 -1
  199. package/lite/subscriber.js +689 -112
  200. package/lite/subscriber.js.map +1 -1
  201. package/lite/track.d.ts +25 -13
  202. package/lite/track.d.ts.map +1 -1
  203. package/lite/track.js +60 -35
  204. package/lite/track.js.map +1 -1
  205. package/lite/version.d.ts +39 -4
  206. package/lite/version.d.ts.map +1 -1
  207. package/lite/version.js +139 -17
  208. package/lite/version.js.map +1 -1
  209. package/mock.d.ts +53 -3
  210. package/mock.d.ts.map +1 -1
  211. package/mock.js +110 -21
  212. package/mock.js.map +1 -1
  213. package/{lite/origin.d.ts → origin.d.ts} +25 -1
  214. package/origin.d.ts.map +1 -0
  215. package/{lite/origin.js → origin.js} +25 -1
  216. package/origin.js.map +1 -0
  217. package/package.json +6 -4
  218. package/path.d.ts +67 -0
  219. package/path.d.ts.map +1 -1
  220. package/path.js +128 -0
  221. package/path.js.map +1 -1
  222. package/stream.d.ts +94 -4
  223. package/stream.d.ts.map +1 -1
  224. package/stream.js +128 -17
  225. package/stream.js.map +1 -1
  226. package/time.d.ts +109 -86
  227. package/time.d.ts.map +1 -1
  228. package/time.js +80 -30
  229. package/time.js.map +1 -1
  230. package/track.d.ts +298 -47
  231. package/track.d.ts.map +1 -1
  232. package/track.js +721 -109
  233. package/track.js.map +1 -1
  234. package/util/timeout.d.ts +5 -0
  235. package/util/timeout.d.ts.map +1 -0
  236. package/util/timeout.js +18 -0
  237. package/util/timeout.js.map +1 -0
  238. package/util/utf8.d.ts +3 -0
  239. package/util/utf8.d.ts.map +1 -0
  240. package/util/utf8.js +7 -0
  241. package/util/utf8.js.map +1 -0
  242. package/varint.d.ts +14 -3
  243. package/varint.d.ts.map +1 -1
  244. package/varint.js +23 -12
  245. package/varint.js.map +1 -1
  246. package/zod.d.ts +5 -5
  247. package/zod.d.ts.map +1 -1
  248. package/zod.js.map +1 -1
  249. package/bandwidth.d.ts +0 -11
  250. package/bandwidth.d.ts.map +0 -1
  251. package/bandwidth.js +0 -7
  252. package/bandwidth.js.map +0 -1
  253. package/connection/cert.test.d.ts +0 -2
  254. package/connection/cert.test.d.ts.map +0 -1
  255. package/connection/cert.test.js +0 -26
  256. package/connection/cert.test.js.map +0 -1
  257. package/connection/reload.test.d.ts +0 -2
  258. package/connection/reload.test.d.ts.map +0 -1
  259. package/connection/reload.test.js +0 -39
  260. package/connection/reload.test.js.map +0 -1
  261. package/group.test.d.ts +0 -2
  262. package/group.test.d.ts.map +0 -1
  263. package/group.test.js +0 -66
  264. package/group.test.js.map +0 -1
  265. package/ietf/aliases.test.d.ts +0 -2
  266. package/ietf/aliases.test.d.ts.map +0 -1
  267. package/ietf/aliases.test.js +0 -30
  268. package/ietf/aliases.test.js.map +0 -1
  269. package/ietf/ietf.test.d.ts +0 -2
  270. package/ietf/ietf.test.d.ts.map +0 -1
  271. package/ietf/ietf.test.js +0 -873
  272. package/ietf/ietf.test.js.map +0 -1
  273. package/integration.test.d.ts +0 -2
  274. package/integration.test.d.ts.map +0 -1
  275. package/integration.test.js +0 -90
  276. package/integration.test.js.map +0 -1
  277. package/lite/origin.d.ts.map +0 -1
  278. package/lite/origin.js.map +0 -1
  279. package/lite/subscriber.test.d.ts +0 -2
  280. package/lite/subscriber.test.d.ts.map +0 -1
  281. package/lite/subscriber.test.js +0 -30
  282. package/lite/subscriber.test.js.map +0 -1
  283. package/lite/track.test.d.ts +0 -2
  284. package/lite/track.test.d.ts.map +0 -1
  285. package/lite/track.test.js +0 -53
  286. package/lite/track.test.js.map +0 -1
  287. package/path.test.d.ts +0 -2
  288. package/path.test.d.ts.map +0 -1
  289. package/path.test.js +0 -169
  290. package/path.test.js.map +0 -1
  291. package/stream.test.d.ts +0 -2
  292. package/stream.test.d.ts.map +0 -1
  293. package/stream.test.js +0 -210
  294. package/stream.test.js.map +0 -1
  295. package/track.test.d.ts +0 -2
  296. package/track.test.d.ts.map +0 -1
  297. package/track.test.js +0 -56
  298. package/track.test.js.map +0 -1
  299. package/util/error.d.ts +0 -3
  300. package/util/error.d.ts.map +0 -1
  301. package/util/error.js +0 -9
  302. package/util/error.js.map +0 -1
  303. package/util/index.d.ts +0 -2
  304. package/util/index.d.ts.map +0 -1
  305. package/util/index.js +0 -3
  306. package/util/index.js.map +0 -1
  307. package/varint.test.d.ts +0 -2
  308. package/varint.test.d.ts.map +0 -1
  309. package/varint.test.js +0 -106
  310. package/varint.test.js.map +0 -1
package/ietf/fetch.js CHANGED
@@ -1,5 +1,26 @@
1
1
  /* @ts-self-types="./fetch.d.ts" */
2
2
  import * as Message from "./message.js";
3
+ /**
4
+ * The header that begins a fetch stream (draft-20 section 11.4.4), naming the request it
5
+ * answers. Written by the publisher when serving a subscription's fill.
6
+ */
7
+ export class FetchHeader {
8
+ /** The uni stream type, not a control message id. */
9
+ static type = 0x5;
10
+ /** The SUBSCRIBE (or FETCH) request this stream carries objects for. */
11
+ requestId;
12
+ constructor({ requestId }) {
13
+ this.requestId = requestId;
14
+ }
15
+ /** Write the header, which the stream type must already precede. */
16
+ async encode(w, _version) {
17
+ await w.u62(this.requestId);
18
+ }
19
+ /** Read the header, with the stream type already consumed. */
20
+ static async decode(r, _version) {
21
+ return new FetchHeader({ requestId: await r.u62() });
22
+ }
23
+ }
3
24
  export class Fetch {
4
25
  static id = 0x16;
5
26
  requestId;
package/ietf/fetch.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/ietf/fetch.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport type { IetfVersion } from \"./version.ts\";\n\nexport class Fetch {\n\tstatic id = 0x16;\n\n\trequestId: bigint;\n\ttrackNamespace: Path.Valid;\n\ttrackName: string;\n\tsubscriberPriority: number;\n\tgroupOrder: number;\n\tstartGroup: bigint;\n\tstartObject: bigint;\n\tendGroup: bigint;\n\tendObject: bigint;\n\n\tconstructor({\n\t\trequestId,\n\t\ttrackNamespace,\n\t\ttrackName,\n\t\tsubscriberPriority,\n\t\tgroupOrder,\n\t\tstartGroup,\n\t\tstartObject,\n\t\tendGroup,\n\t\tendObject,\n\t}: {\n\t\trequestId: bigint;\n\t\ttrackNamespace: Path.Valid;\n\t\ttrackName: string;\n\t\tsubscriberPriority: number;\n\t\tgroupOrder: number;\n\t\tstartGroup: bigint;\n\t\tstartObject: bigint;\n\t\tendGroup: bigint;\n\t\tendObject: bigint;\n\t}) {\n\t\tthis.requestId = requestId;\n\t\tthis.trackNamespace = trackNamespace;\n\t\tthis.trackName = trackName;\n\t\tthis.subscriberPriority = subscriberPriority;\n\t\tthis.groupOrder = groupOrder;\n\t\tthis.startGroup = startGroup;\n\t\tthis.startObject = startObject;\n\t\tthis.endGroup = endGroup;\n\t\tthis.endObject = endObject;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<Fetch> {\n\t\treturn Message.decode(r, Fetch.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<Fetch> {\n\t\tthrow new Error(\"FETCH messages are not supported\");\n\t}\n}\n\nexport class FetchOk {\n\tstatic id = 0x18;\n\n\trequestId: bigint | undefined;\n\n\tconstructor({ requestId }: { requestId?: bigint }) {\n\t\tthis.requestId = requestId;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_OK messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchOk> {\n\t\treturn Message.decode(r, FetchOk.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchOk> {\n\t\tthrow new Error(\"FETCH_OK messages are not supported\");\n\t}\n}\n\nexport class FetchError {\n\tstatic id = 0x19;\n\n\trequestId: bigint;\n\terrorCode: number;\n\treasonPhrase: string;\n\n\tconstructor({\n\t\trequestId,\n\t\terrorCode,\n\t\treasonPhrase,\n\t}: { requestId: bigint; errorCode: number; reasonPhrase: string }) {\n\t\tthis.requestId = requestId;\n\t\tthis.errorCode = errorCode;\n\t\tthis.reasonPhrase = reasonPhrase;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_ERROR messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchError> {\n\t\treturn Message.decode(r, FetchError.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchError> {\n\t\tthrow new Error(\"FETCH_ERROR messages are not supported\");\n\t}\n}\n\n// Removed in d17\nexport class FetchCancel {\n\tstatic id = 0x17;\n\n\trequestId: bigint;\n\n\tconstructor({ requestId }: { requestId: bigint }) {\n\t\tthis.requestId = requestId;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_CANCEL messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchCancel> {\n\t\treturn Message.decode(r, FetchCancel.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchCancel> {\n\t\tthrow new Error(\"FETCH_CANCEL messages are not supported\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/ietf/fetch.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport type { IetfVersion } from \"./version.ts\";\n\n/**\n * The header that begins a fetch stream (draft-20 section 11.4.4), naming the request it\n * answers. Written by the publisher when serving a subscription's fill.\n */\nexport class FetchHeader {\n\t/** The uni stream type, not a control message id. */\n\tstatic type = 0x5;\n\n\t/** The SUBSCRIBE (or FETCH) request this stream carries objects for. */\n\trequestId: bigint;\n\n\tconstructor({ requestId }: { requestId: bigint }) {\n\t\tthis.requestId = requestId;\n\t}\n\n\t/** Write the header, which the stream type must already precede. */\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\tawait w.u62(this.requestId);\n\t}\n\n\t/** Read the header, with the stream type already consumed. */\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchHeader> {\n\t\treturn new FetchHeader({ requestId: await r.u62() });\n\t}\n}\n\nexport class Fetch {\n\tstatic id = 0x16;\n\n\trequestId: bigint;\n\ttrackNamespace: Path.Valid;\n\ttrackName: string;\n\tsubscriberPriority: number;\n\tgroupOrder: number;\n\tstartGroup: bigint;\n\tstartObject: bigint;\n\tendGroup: bigint;\n\tendObject: bigint;\n\n\tconstructor({\n\t\trequestId,\n\t\ttrackNamespace,\n\t\ttrackName,\n\t\tsubscriberPriority,\n\t\tgroupOrder,\n\t\tstartGroup,\n\t\tstartObject,\n\t\tendGroup,\n\t\tendObject,\n\t}: {\n\t\trequestId: bigint;\n\t\ttrackNamespace: Path.Valid;\n\t\ttrackName: string;\n\t\tsubscriberPriority: number;\n\t\tgroupOrder: number;\n\t\tstartGroup: bigint;\n\t\tstartObject: bigint;\n\t\tendGroup: bigint;\n\t\tendObject: bigint;\n\t}) {\n\t\tthis.requestId = requestId;\n\t\tthis.trackNamespace = trackNamespace;\n\t\tthis.trackName = trackName;\n\t\tthis.subscriberPriority = subscriberPriority;\n\t\tthis.groupOrder = groupOrder;\n\t\tthis.startGroup = startGroup;\n\t\tthis.startObject = startObject;\n\t\tthis.endGroup = endGroup;\n\t\tthis.endObject = endObject;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<Fetch> {\n\t\treturn Message.decode(r, Fetch.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<Fetch> {\n\t\tthrow new Error(\"FETCH messages are not supported\");\n\t}\n}\n\nexport class FetchOk {\n\tstatic id = 0x18;\n\n\trequestId: bigint | undefined;\n\n\tconstructor({ requestId }: { requestId?: bigint }) {\n\t\tthis.requestId = requestId;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_OK messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchOk> {\n\t\treturn Message.decode(r, FetchOk.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchOk> {\n\t\tthrow new Error(\"FETCH_OK messages are not supported\");\n\t}\n}\n\nexport class FetchError {\n\tstatic id = 0x19;\n\n\trequestId: bigint;\n\terrorCode: number;\n\treasonPhrase: string;\n\n\tconstructor({\n\t\trequestId,\n\t\terrorCode,\n\t\treasonPhrase,\n\t}: { requestId: bigint; errorCode: number; reasonPhrase: string }) {\n\t\tthis.requestId = requestId;\n\t\tthis.errorCode = errorCode;\n\t\tthis.reasonPhrase = reasonPhrase;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_ERROR messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchError> {\n\t\treturn Message.decode(r, FetchError.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchError> {\n\t\tthrow new Error(\"FETCH_ERROR messages are not supported\");\n\t}\n}\n\n// Removed in d17\nexport class FetchCancel {\n\tstatic id = 0x17;\n\n\trequestId: bigint;\n\n\tconstructor({ requestId }: { requestId: bigint }) {\n\t\tthis.requestId = requestId;\n\t}\n\n\tasync #encode(_w: Writer): Promise<void> {\n\t\tthrow new Error(\"FETCH_CANCEL messages are not supported\");\n\t}\n\n\tasync encode(w: Writer, _version: IetfVersion): Promise<void> {\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, _version: IetfVersion): Promise<FetchCancel> {\n\t\treturn Message.decode(r, FetchCancel.#decode);\n\t}\n\n\tstatic async #decode(_r: Reader): Promise<FetchCancel> {\n\t\tthrow new Error(\"FETCH_CANCEL messages are not supported\");\n\t}\n}\n"]}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The Location Filter carried by SUBSCRIBE, and draft-20's fill request.
3
+ *
4
+ * @module
5
+ */
6
+ import type { Reader } from "../stream";
7
+ import { type IetfVersion } from "./version";
8
+ /** Which Objects a subscription delivers. */
9
+ export type Filter =
10
+ /** Every Object in the track, encoded by omitting the parameter. */
11
+ {
12
+ kind: "unfiltered";
13
+ }
14
+ /** The next Object after the live edge, which can begin mid-group. */
15
+ | {
16
+ kind: "nextObject";
17
+ }
18
+ /**
19
+ * The given number of groups back from the next group, always open ended.
20
+ * Zero is the next group and one is the current one.
21
+ */
22
+ | {
23
+ kind: "relative";
24
+ groups: bigint;
25
+ }
26
+ /**
27
+ * An absolute range. `endGroup` is the last group, inclusive; `endObject` further bounds
28
+ * the last object in it, and its absence includes the whole end group.
29
+ */
30
+ | {
31
+ kind: "absolute";
32
+ startGroup: bigint;
33
+ startObject: bigint;
34
+ endGroup?: bigint;
35
+ endObject?: bigint;
36
+ };
37
+ /**
38
+ * Whether this is draft-20 or newer.
39
+ *
40
+ * Draft-20 replaced the Filter Type tag with up to four optional varints, where the number
41
+ * present selects the meaning.
42
+ */
43
+ export declare function isDraft20(version: IetfVersion): boolean;
44
+ /** Encode a filter as its raw parameter value. Unfiltered encodes to zero bytes. */
45
+ export declare function encode(filter: Filter, version: IetfVersion): Uint8Array;
46
+ /** Decode a filter from its raw parameter value. */
47
+ export declare function decode(data: Uint8Array, version: IetfVersion): Filter;
48
+ /**
49
+ * Read the tagged filter draft-14 carries inline in a SUBSCRIBE body, where the fields
50
+ * following the tag have no length to delimit them.
51
+ *
52
+ * Every tag is read, including the absolute forms we do not serve. Rejecting one would tear
53
+ * the session down over a filter the draft lets a subscriber send; what we do with it is
54
+ * decided when the range is resolved.
55
+ */
56
+ export declare function decodeInline(r: Reader): Promise<Filter>;
57
+ /**
58
+ * A draft-20 fill: the backfill a subscriber asks for alongside its subscription.
59
+ *
60
+ * The publisher serves one whose range resolves to a single group, straight from the group
61
+ * cache on a fetch stream. That covers the draft's own current-group join (a Next Object
62
+ * subscription plus a `StartGroup=1` fill). Anything wider is refused by resetting the
63
+ * fetch stream, the draft's fill-failure signal.
64
+ */
65
+ export interface Fill {
66
+ /**
67
+ * The range to fill. `undefined` means the Location Filter was omitted, which inherits
68
+ * the subscription's own filter; `unfiltered` (a zero length filter) means the whole
69
+ * track up to Largest Object.
70
+ */
71
+ filter?: Filter;
72
+ /**
73
+ * Whether the scope carried a Range Filter (0x25-0x28). Those narrow which objects pass,
74
+ * which we do not implement, and serving the unfiltered range instead would deliver
75
+ * objects the peer excluded. Never encoded; we send no range filters.
76
+ */
77
+ rangeFilters: boolean;
78
+ }
79
+ /**
80
+ * Encode FILL_PARAMETERS, whose presence is what requests a backfill.
81
+ *
82
+ * The value is a nested parameter scope, encoded like a message's parameters.
83
+ */
84
+ export declare function encodeFill(fill: Fill, version: IetfVersion): Uint8Array;
85
+ /** Decode FILL_PARAMETERS, returning the range it asks to fill. */
86
+ export declare function decodeFill(data: Uint8Array, version: IetfVersion): Fill;
87
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/ietf/filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,KAAK,WAAW,EAAW,MAAM,cAAc,CAAC;AAEzD,6CAA6C;AAC7C,MAAM,MAAM,MAAM;AACjB,oEAAoE;AAClE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE;AACxB,sEAAsE;GACpE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE;AACxB;;;GAGG;GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACtC;;;GAGG;GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQxG;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAEvD;AAqCD,oFAAoF;AACpF,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,UAAU,CAEvE;AA6DD,oDAAoD;AACpD,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAErE;AAgED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB7D;AAQD;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;CACtB;AAmCD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,UAAU,CAYvE;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAyDvE"}
package/ietf/filter.js ADDED
@@ -0,0 +1,292 @@
1
+ /* @ts-self-types="./filter.d.ts" */
2
+ /**
3
+ * The Location Filter carried by SUBSCRIBE, and draft-20's fill request.
4
+ *
5
+ * @module
6
+ */
7
+ import * as Varint from "../varint.js";
8
+ import { Version } from "./version.js";
9
+ /** The tagged Filter Type of draft-19 and earlier. */
10
+ const TAG_NEXT_GROUP = 0x1n;
11
+ const TAG_LARGEST_OBJECT = 0x2n;
12
+ const TAG_ABSOLUTE_START = 0x3n;
13
+ const TAG_ABSOLUTE_RANGE = 0x4n;
14
+ /**
15
+ * Whether this is draft-20 or newer.
16
+ *
17
+ * Draft-20 replaced the Filter Type tag with up to four optional varints, where the number
18
+ * present selects the meaning.
19
+ */
20
+ export function isDraft20(version) {
21
+ return version === Version.DRAFT_20;
22
+ }
23
+ /**
24
+ * Draft-17 replaced QUIC's two-bit-length varint with a leading-1-bits one. The two agree
25
+ * below 64 and diverge above it, so getting this wrong is invisible until group or object
26
+ * ids grow past that.
27
+ */
28
+ function usesLeadingOnes(version) {
29
+ return version !== Version.DRAFT_14 && version !== Version.DRAFT_15 && version !== Version.DRAFT_16;
30
+ }
31
+ function varint(v, version) {
32
+ return usesLeadingOnes(version) ? Varint.encodeLeadingOnes(v) : Varint.encode(v);
33
+ }
34
+ function unvarint(buf, version) {
35
+ return usesLeadingOnes(version) ? Varint.decodeLeadingOnes(buf) : Varint.decodeBigInt(buf);
36
+ }
37
+ function concat(parts) {
38
+ const total = parts.reduce((n, p) => n + p.length, 0);
39
+ const out = new Uint8Array(total);
40
+ let offset = 0;
41
+ for (const part of parts) {
42
+ out.set(part, offset);
43
+ offset += part.length;
44
+ }
45
+ return out;
46
+ }
47
+ function endDelta(startGroup, endGroup) {
48
+ if (endGroup < startGroup) {
49
+ throw new Error(`filter range runs backwards: ${startGroup} > ${endGroup}`);
50
+ }
51
+ return endGroup - startGroup;
52
+ }
53
+ /** Encode a filter as its raw parameter value. Unfiltered encodes to zero bytes. */
54
+ export function encode(filter, version) {
55
+ return isDraft20(version) ? encodeFields(filter, version) : encodeTag(filter, version);
56
+ }
57
+ function encodeFields(filter, version) {
58
+ switch (filter.kind) {
59
+ case "unfiltered":
60
+ return new Uint8Array();
61
+ case "nextObject":
62
+ return concat([varint(0n, version), varint(0n, version)]);
63
+ case "relative":
64
+ return varint(filter.groups, version);
65
+ case "absolute": {
66
+ // An open ended absolute {0, 0} is defined as equivalent to unfiltered, so it
67
+ // normalizes rather than colliding with the two-zero-field nextObject spelling.
68
+ if (filter.startGroup === 0n && filter.startObject === 0n && filter.endGroup === undefined) {
69
+ return new Uint8Array();
70
+ }
71
+ const parts = [varint(filter.startGroup, version), varint(filter.startObject, version)];
72
+ if (filter.endGroup !== undefined) {
73
+ parts.push(varint(endDelta(filter.startGroup, filter.endGroup), version));
74
+ if (filter.endObject !== undefined) {
75
+ parts.push(varint(filter.endObject, version));
76
+ }
77
+ }
78
+ return concat(parts);
79
+ }
80
+ }
81
+ }
82
+ function encodeTag(filter, version) {
83
+ switch (filter.kind) {
84
+ case "unfiltered":
85
+ // No tag means "everything", which only the absolute spelling can say.
86
+ return concat([varint(TAG_ABSOLUTE_START, version), varint(0n, version), varint(0n, version)]);
87
+ case "nextObject":
88
+ return varint(TAG_LARGEST_OBJECT, version);
89
+ case "relative":
90
+ if (filter.groups !== 0n) {
91
+ // Only draft-20 can name a start further back than the next group without
92
+ // knowing Largest Object, so there is no honest tag to fall back to.
93
+ throw new Error(`relative filter ${filter.groups} needs draft-20`);
94
+ }
95
+ return varint(TAG_NEXT_GROUP, version);
96
+ case "absolute": {
97
+ // Draft-19's AbsoluteRange ends on a group, so an object-bounded range has no
98
+ // spelling. Refuse rather than widen the range the caller asked for.
99
+ if (filter.endObject !== undefined) {
100
+ throw new Error("an object-bounded range needs draft-20");
101
+ }
102
+ const parts = [
103
+ varint(filter.endGroup === undefined ? TAG_ABSOLUTE_START : TAG_ABSOLUTE_RANGE, version),
104
+ varint(filter.startGroup, version),
105
+ varint(filter.startObject, version),
106
+ ];
107
+ if (filter.endGroup !== undefined) {
108
+ parts.push(varint(endDelta(filter.startGroup, filter.endGroup), version));
109
+ }
110
+ return concat(parts);
111
+ }
112
+ }
113
+ }
114
+ /** Decode a filter from its raw parameter value. */
115
+ export function decode(data, version) {
116
+ return isDraft20(version) ? decodeFields(data, version) : decodeTag(data, version);
117
+ }
118
+ function decodeFields(data, version) {
119
+ const fields = [];
120
+ let rest = data;
121
+ while (rest.length > 0) {
122
+ if (fields.length === 4) {
123
+ throw new Error("too many fields in LOCATION_FILTER");
124
+ }
125
+ const [value, next] = unvarint(rest, version);
126
+ fields.push(value);
127
+ rest = next;
128
+ }
129
+ switch (fields.length) {
130
+ case 0:
131
+ return { kind: "unfiltered" };
132
+ case 1:
133
+ return { kind: "relative", groups: fields[0] };
134
+ default: {
135
+ const [startGroup, startObject] = fields;
136
+ // Two zeroes is the Next Object spelling; anything else is an absolute start.
137
+ if (fields.length === 2 && startGroup === 0n && startObject === 0n) {
138
+ return { kind: "nextObject" };
139
+ }
140
+ const endGroup = fields.length >= 3 ? startGroup + fields[2] : undefined;
141
+ const endObject = fields.length === 4 ? fields[3] : undefined;
142
+ return { kind: "absolute", startGroup, startObject, endGroup, endObject };
143
+ }
144
+ }
145
+ }
146
+ function decodeTag(data, version) {
147
+ const [tag, afterTag] = unvarint(data, version);
148
+ const readLocation = (buf) => {
149
+ const [group, afterGroup] = unvarint(buf, version);
150
+ const [object, rest] = unvarint(afterGroup, version);
151
+ return [group, object, rest];
152
+ };
153
+ switch (tag) {
154
+ case TAG_NEXT_GROUP:
155
+ expectEmpty(afterTag);
156
+ return { kind: "relative", groups: 0n };
157
+ case TAG_LARGEST_OBJECT:
158
+ expectEmpty(afterTag);
159
+ return { kind: "nextObject" };
160
+ case TAG_ABSOLUTE_START: {
161
+ const [startGroup, startObject, rest] = readLocation(afterTag);
162
+ expectEmpty(rest);
163
+ return { kind: "absolute", startGroup, startObject };
164
+ }
165
+ case TAG_ABSOLUTE_RANGE: {
166
+ const [startGroup, startObject, afterLocation] = readLocation(afterTag);
167
+ const [delta, rest] = unvarint(afterLocation, version);
168
+ expectEmpty(rest);
169
+ return { kind: "absolute", startGroup, startObject, endGroup: startGroup + delta };
170
+ }
171
+ default:
172
+ throw new Error(`unsupported filter type: ${tag}`);
173
+ }
174
+ }
175
+ /**
176
+ * Read the tagged filter draft-14 carries inline in a SUBSCRIBE body, where the fields
177
+ * following the tag have no length to delimit them.
178
+ *
179
+ * Every tag is read, including the absolute forms we do not serve. Rejecting one would tear
180
+ * the session down over a filter the draft lets a subscriber send; what we do with it is
181
+ * decided when the range is resolved.
182
+ */
183
+ export async function decodeInline(r) {
184
+ const tag = await r.u62();
185
+ switch (tag) {
186
+ case TAG_NEXT_GROUP:
187
+ return { kind: "relative", groups: 0n };
188
+ case TAG_LARGEST_OBJECT:
189
+ return { kind: "nextObject" };
190
+ case TAG_ABSOLUTE_START:
191
+ return { kind: "absolute", startGroup: await r.u62(), startObject: await r.u62() };
192
+ case TAG_ABSOLUTE_RANGE: {
193
+ const startGroup = await r.u62();
194
+ const startObject = await r.u62();
195
+ const delta = await r.u62();
196
+ return { kind: "absolute", startGroup, startObject, endGroup: startGroup + delta };
197
+ }
198
+ default:
199
+ throw new Error(`unsupported filter type: ${tag}`);
200
+ }
201
+ }
202
+ function expectEmpty(rest) {
203
+ if (rest.length !== 0) {
204
+ throw new Error("trailing bytes in LOCATION_FILTER");
205
+ }
206
+ }
207
+ /** LOCATION_FILTER, the only parameter we act on inside a fill. */
208
+ const FILL_LOCATION_FILTER = 0x21n;
209
+ const FILL_ALLOWED = new Map([
210
+ [0x0an, "varint"], // FILL_TIMEOUT
211
+ [0x20n, "byte"], // SUBSCRIBER_PRIORITY, a uint8
212
+ [FILL_LOCATION_FILTER, "bytes"],
213
+ [0x22n, "byte"], // GROUP_ORDER, a uint8
214
+ [0x25n, "bytes"], // SUBGROUP_FILTER
215
+ [0x26n, "bytes"], // OBJECTID_FILTER, length prefixed despite an even id
216
+ [0x27n, "bytes"], // PRIORITY_FILTER
217
+ [0x28n, "bytes"], // OBJECT_PROPERTY_FILTER, likewise
218
+ ]);
219
+ /**
220
+ * Encode FILL_PARAMETERS, whose presence is what requests a backfill.
221
+ *
222
+ * The value is a nested parameter scope, encoded like a message's parameters.
223
+ */
224
+ export function encodeFill(fill, version) {
225
+ // An omitted filter inherits the subscription's, so the scope is empty. An explicit
226
+ // unfiltered still encodes, as a zero length filter meaning the whole track.
227
+ if (fill.filter === undefined) {
228
+ return varint(0n, version);
229
+ }
230
+ return concat([
231
+ varint(1n, version),
232
+ // The first type in a scope is not delta encoded, so this is the raw id.
233
+ varint(FILL_LOCATION_FILTER, version),
234
+ encodeLengthPrefixed(encode(fill.filter, version), version),
235
+ ]);
236
+ }
237
+ /** Decode FILL_PARAMETERS, returning the range it asks to fill. */
238
+ export function decodeFill(data, version) {
239
+ const [count, afterCount] = unvarint(data, version);
240
+ if (count > 64n) {
241
+ throw new Error("too many parameters in FILL_PARAMETERS");
242
+ }
243
+ let rest = afterCount;
244
+ let filter;
245
+ let rangeFilters = false;
246
+ let prev = 0n;
247
+ for (let i = 0n; i < count; i++) {
248
+ const [delta, afterType] = unvarint(rest, version);
249
+ const key = i === 0n ? delta : prev + delta;
250
+ prev = key;
251
+ rest = afterType;
252
+ const framing = FILL_ALLOWED.get(key);
253
+ if (framing === undefined) {
254
+ throw new Error(`parameter ${key} is not allowed inside FILL_PARAMETERS`);
255
+ }
256
+ // A Range Filter changes which objects the fill may contain, so its presence is
257
+ // recorded even though its value is not interpreted.
258
+ rangeFilters ||= key >= 0x25n && key <= 0x28n;
259
+ // The rest are parameters we do not act on, but their bytes still have to be
260
+ // consumed or the remaining keys desync.
261
+ if (framing === "varint") {
262
+ [, rest] = unvarint(rest, version);
263
+ continue;
264
+ }
265
+ if (framing === "byte") {
266
+ if (rest.length < 1)
267
+ throw new Error("truncated value inside FILL_PARAMETERS");
268
+ rest = rest.slice(1);
269
+ continue;
270
+ }
271
+ const [length, afterLength] = unvarint(rest, version);
272
+ if (BigInt(afterLength.length) < length) {
273
+ throw new Error("truncated value inside FILL_PARAMETERS");
274
+ }
275
+ const value = afterLength.slice(0, Number(length));
276
+ rest = afterLength.slice(Number(length));
277
+ if (key === FILL_LOCATION_FILTER) {
278
+ if (filter !== undefined) {
279
+ throw new Error("duplicate LOCATION_FILTER inside FILL_PARAMETERS");
280
+ }
281
+ filter = decode(value, version);
282
+ }
283
+ }
284
+ if (rest.length !== 0) {
285
+ throw new Error("trailing bytes in FILL_PARAMETERS");
286
+ }
287
+ return { filter, rangeFilters };
288
+ }
289
+ function encodeLengthPrefixed(value, version) {
290
+ return concat([varint(BigInt(value.length), version), value]);
291
+ }
292
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/ietf/filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAoB,OAAO,EAAE,MAAM,cAAc,CAAC;AAmBzD,sDAAsD;AACtD,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB;IAC7C,OAAO,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,OAAoB;IAC5C,OAAO,OAAO,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;AACrG,CAAC;AAED,SAAS,MAAM,CAAC,CAAS,EAAE,OAAoB;IAC9C,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,QAAQ,CAAC,GAAe,EAAE,OAAoB;IACtD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,MAAM,CAAC,KAAmB;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,QAAQ,CAAC,UAAkB,EAAE,QAAgB;IACrD,IAAI,QAAQ,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,gCAAgC,UAAU,MAAM,QAAQ,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,QAAQ,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,MAAM,CAAC,MAAc,EAAE,OAAoB;IAC1D,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,YAAY,CAAC,MAAc,EAAE,OAAoB;IACzD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,YAAY;YAChB,OAAO,IAAI,UAAU,EAAE,CAAC;QACzB,KAAK,YAAY;YAChB,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,UAAU;YACd,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvC,KAAK,UAAU,EAAE,CAAC;YACjB,8EAA8E;YAC9E,gFAAgF;YAChF,IAAI,MAAM,CAAC,UAAU,KAAK,EAAE,IAAI,MAAM,CAAC,WAAW,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC5F,OAAO,IAAI,UAAU,EAAE,CAAC;YACzB,CAAC;YACD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YACxF,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACnC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC1E,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;oBACpC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC/C,CAAC;YACF,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,OAAoB;IACtD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,YAAY;YAChB,uEAAuE;YACvE,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAChG,KAAK,YAAY;YAChB,OAAO,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;QAC5C,KAAK,UAAU;YACd,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;gBAC1B,0EAA0E;gBAC1E,qEAAqE;gBACrE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;YACpE,CAAC;YACD,OAAO,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACxC,KAAK,UAAU,EAAE,CAAC;YACjB,8EAA8E;YAC9E,qEAAqE;YACrE,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC3D,CAAC;YACD,MAAM,KAAK,GAAG;gBACb,MAAM,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,EAAE,OAAO,CAAC;gBACxF,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC;gBAClC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC;aACnC,CAAC;YACF,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACnC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3E,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;AACF,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,MAAM,CAAC,IAAgB,EAAE,OAAoB;IAC5D,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,YAAY,CAAC,IAAgB,EAAE,OAAoB;IAC3D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,GAAG,IAAI,CAAC;IACb,CAAC;IAED,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,CAAC;YACL,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAC/B,KAAK,CAAC;YACL,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,SAAS,CAAC;YACT,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC;YACzC,8EAA8E;YAC9E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,KAAK,EAAE,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;gBACpE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACzE,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAC3E,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB,EAAE,OAAoB;IACxD,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEhD,MAAM,YAAY,GAAG,CAAC,GAAe,EAAgC,EAAE;QACtE,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,QAAQ,GAAG,EAAE,CAAC;QACb,KAAK,cAAc;YAClB,WAAW,CAAC,QAAQ,CAAC,CAAC;YACtB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACzC,KAAK,kBAAkB;YACtB,WAAW,CAAC,QAAQ,CAAC,CAAC;YACtB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAC/B,KAAK,kBAAkB,EAAE,CAAC;YACzB,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC/D,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;QACtD,CAAC;QACD,KAAK,kBAAkB,EAAE,CAAC;YACzB,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACxE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;YACvD,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,GAAG,KAAK,EAAE,CAAC;QACpF,CAAC;QACD;YACC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;IACrD,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,CAAS;IAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;IAC1B,QAAQ,GAAG,EAAE,CAAC;QACb,KAAK,cAAc;YAClB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACzC,KAAK,kBAAkB;YACtB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAC/B,KAAK,kBAAkB;YACtB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACpF,KAAK,kBAAkB,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,GAAG,KAAK,EAAE,CAAC;QACpF,CAAC;QACD;YACC,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;IACrD,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,IAAgB;IACpC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACtD,CAAC;AACF,CAAC;AA0BD,mEAAmE;AACnE,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAqBnC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAkB;IAC7C,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,eAAe;IAClC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,+BAA+B;IAChD,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAC/B,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,uBAAuB;IACxC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,sDAAsD;IACxE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,mCAAmC;CACrD,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,OAAoB;IAC1D,oFAAoF;IACpF,6EAA6E;IAC7E,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC;QACnB,yEAAyE;QACzE,MAAM,CAAC,oBAAoB,EAAE,OAAO,CAAC;QACrC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;KAC3D,CAAC,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,UAAU,CAAC,IAAgB,EAAE,OAAoB;IAChE,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,IAAI,MAA0B,CAAC;IAC/B,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;QAC5C,IAAI,GAAG,GAAG,CAAC;QACX,IAAI,GAAG,SAAS,CAAC;QAEjB,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,wCAAwC,CAAC,CAAC;QAC3E,CAAC;QAED,gFAAgF;QAChF,qDAAqD;QACrD,YAAY,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;QAE9C,6EAA6E;QAC7E,yCAAyC;QACzC,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC1B,CAAC,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACnC,SAAS;QACV,CAAC;QACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC/E,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,SAAS;QACV,CAAC;QAED,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACnD,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAEzC,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAiB,EAAE,OAAoB;IACpE,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["/**\n * The Location Filter carried by SUBSCRIBE, and draft-20's fill request.\n *\n * @module\n */\n\nimport type { Reader } from \"../stream.ts\";\nimport * as Varint from \"../varint.ts\";\nimport { type IetfVersion, Version } from \"./version.ts\";\n\n/** Which Objects a subscription delivers. */\nexport type Filter =\n\t/** Every Object in the track, encoded by omitting the parameter. */\n\t| { kind: \"unfiltered\" }\n\t/** The next Object after the live edge, which can begin mid-group. */\n\t| { kind: \"nextObject\" }\n\t/**\n\t * The given number of groups back from the next group, always open ended.\n\t * Zero is the next group and one is the current one.\n\t */\n\t| { kind: \"relative\"; groups: bigint }\n\t/**\n\t * An absolute range. `endGroup` is the last group, inclusive; `endObject` further bounds\n\t * the last object in it, and its absence includes the whole end group.\n\t */\n\t| { kind: \"absolute\"; startGroup: bigint; startObject: bigint; endGroup?: bigint; endObject?: bigint };\n\n/** The tagged Filter Type of draft-19 and earlier. */\nconst TAG_NEXT_GROUP = 0x1n;\nconst TAG_LARGEST_OBJECT = 0x2n;\nconst TAG_ABSOLUTE_START = 0x3n;\nconst TAG_ABSOLUTE_RANGE = 0x4n;\n\n/**\n * Whether this is draft-20 or newer.\n *\n * Draft-20 replaced the Filter Type tag with up to four optional varints, where the number\n * present selects the meaning.\n */\nexport function isDraft20(version: IetfVersion): boolean {\n\treturn version === Version.DRAFT_20;\n}\n\n/**\n * Draft-17 replaced QUIC's two-bit-length varint with a leading-1-bits one. The two agree\n * below 64 and diverge above it, so getting this wrong is invisible until group or object\n * ids grow past that.\n */\nfunction usesLeadingOnes(version: IetfVersion): boolean {\n\treturn version !== Version.DRAFT_14 && version !== Version.DRAFT_15 && version !== Version.DRAFT_16;\n}\n\nfunction varint(v: bigint, version: IetfVersion): Uint8Array {\n\treturn usesLeadingOnes(version) ? Varint.encodeLeadingOnes(v) : Varint.encode(v);\n}\n\nfunction unvarint(buf: Uint8Array, version: IetfVersion): [bigint, Uint8Array] {\n\treturn usesLeadingOnes(version) ? Varint.decodeLeadingOnes(buf) : Varint.decodeBigInt(buf);\n}\n\nfunction concat(parts: Uint8Array[]): Uint8Array {\n\tconst total = parts.reduce((n, p) => n + p.length, 0);\n\tconst out = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const part of parts) {\n\t\tout.set(part, offset);\n\t\toffset += part.length;\n\t}\n\treturn out;\n}\n\nfunction endDelta(startGroup: bigint, endGroup: bigint): bigint {\n\tif (endGroup < startGroup) {\n\t\tthrow new Error(`filter range runs backwards: ${startGroup} > ${endGroup}`);\n\t}\n\treturn endGroup - startGroup;\n}\n\n/** Encode a filter as its raw parameter value. Unfiltered encodes to zero bytes. */\nexport function encode(filter: Filter, version: IetfVersion): Uint8Array {\n\treturn isDraft20(version) ? encodeFields(filter, version) : encodeTag(filter, version);\n}\n\nfunction encodeFields(filter: Filter, version: IetfVersion): Uint8Array {\n\tswitch (filter.kind) {\n\t\tcase \"unfiltered\":\n\t\t\treturn new Uint8Array();\n\t\tcase \"nextObject\":\n\t\t\treturn concat([varint(0n, version), varint(0n, version)]);\n\t\tcase \"relative\":\n\t\t\treturn varint(filter.groups, version);\n\t\tcase \"absolute\": {\n\t\t\t// An open ended absolute {0, 0} is defined as equivalent to unfiltered, so it\n\t\t\t// normalizes rather than colliding with the two-zero-field nextObject spelling.\n\t\t\tif (filter.startGroup === 0n && filter.startObject === 0n && filter.endGroup === undefined) {\n\t\t\t\treturn new Uint8Array();\n\t\t\t}\n\t\t\tconst parts = [varint(filter.startGroup, version), varint(filter.startObject, version)];\n\t\t\tif (filter.endGroup !== undefined) {\n\t\t\t\tparts.push(varint(endDelta(filter.startGroup, filter.endGroup), version));\n\t\t\t\tif (filter.endObject !== undefined) {\n\t\t\t\t\tparts.push(varint(filter.endObject, version));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn concat(parts);\n\t\t}\n\t}\n}\n\nfunction encodeTag(filter: Filter, version: IetfVersion): Uint8Array {\n\tswitch (filter.kind) {\n\t\tcase \"unfiltered\":\n\t\t\t// No tag means \"everything\", which only the absolute spelling can say.\n\t\t\treturn concat([varint(TAG_ABSOLUTE_START, version), varint(0n, version), varint(0n, version)]);\n\t\tcase \"nextObject\":\n\t\t\treturn varint(TAG_LARGEST_OBJECT, version);\n\t\tcase \"relative\":\n\t\t\tif (filter.groups !== 0n) {\n\t\t\t\t// Only draft-20 can name a start further back than the next group without\n\t\t\t\t// knowing Largest Object, so there is no honest tag to fall back to.\n\t\t\t\tthrow new Error(`relative filter ${filter.groups} needs draft-20`);\n\t\t\t}\n\t\t\treturn varint(TAG_NEXT_GROUP, version);\n\t\tcase \"absolute\": {\n\t\t\t// Draft-19's AbsoluteRange ends on a group, so an object-bounded range has no\n\t\t\t// spelling. Refuse rather than widen the range the caller asked for.\n\t\t\tif (filter.endObject !== undefined) {\n\t\t\t\tthrow new Error(\"an object-bounded range needs draft-20\");\n\t\t\t}\n\t\t\tconst parts = [\n\t\t\t\tvarint(filter.endGroup === undefined ? TAG_ABSOLUTE_START : TAG_ABSOLUTE_RANGE, version),\n\t\t\t\tvarint(filter.startGroup, version),\n\t\t\t\tvarint(filter.startObject, version),\n\t\t\t];\n\t\t\tif (filter.endGroup !== undefined) {\n\t\t\t\tparts.push(varint(endDelta(filter.startGroup, filter.endGroup), version));\n\t\t\t}\n\t\t\treturn concat(parts);\n\t\t}\n\t}\n}\n\n/** Decode a filter from its raw parameter value. */\nexport function decode(data: Uint8Array, version: IetfVersion): Filter {\n\treturn isDraft20(version) ? decodeFields(data, version) : decodeTag(data, version);\n}\n\nfunction decodeFields(data: Uint8Array, version: IetfVersion): Filter {\n\tconst fields: bigint[] = [];\n\tlet rest = data;\n\twhile (rest.length > 0) {\n\t\tif (fields.length === 4) {\n\t\t\tthrow new Error(\"too many fields in LOCATION_FILTER\");\n\t\t}\n\t\tconst [value, next] = unvarint(rest, version);\n\t\tfields.push(value);\n\t\trest = next;\n\t}\n\n\tswitch (fields.length) {\n\t\tcase 0:\n\t\t\treturn { kind: \"unfiltered\" };\n\t\tcase 1:\n\t\t\treturn { kind: \"relative\", groups: fields[0] };\n\t\tdefault: {\n\t\t\tconst [startGroup, startObject] = fields;\n\t\t\t// Two zeroes is the Next Object spelling; anything else is an absolute start.\n\t\t\tif (fields.length === 2 && startGroup === 0n && startObject === 0n) {\n\t\t\t\treturn { kind: \"nextObject\" };\n\t\t\t}\n\t\t\tconst endGroup = fields.length >= 3 ? startGroup + fields[2] : undefined;\n\t\t\tconst endObject = fields.length === 4 ? fields[3] : undefined;\n\t\t\treturn { kind: \"absolute\", startGroup, startObject, endGroup, endObject };\n\t\t}\n\t}\n}\n\nfunction decodeTag(data: Uint8Array, version: IetfVersion): Filter {\n\tconst [tag, afterTag] = unvarint(data, version);\n\n\tconst readLocation = (buf: Uint8Array): [bigint, bigint, Uint8Array] => {\n\t\tconst [group, afterGroup] = unvarint(buf, version);\n\t\tconst [object, rest] = unvarint(afterGroup, version);\n\t\treturn [group, object, rest];\n\t};\n\n\tswitch (tag) {\n\t\tcase TAG_NEXT_GROUP:\n\t\t\texpectEmpty(afterTag);\n\t\t\treturn { kind: \"relative\", groups: 0n };\n\t\tcase TAG_LARGEST_OBJECT:\n\t\t\texpectEmpty(afterTag);\n\t\t\treturn { kind: \"nextObject\" };\n\t\tcase TAG_ABSOLUTE_START: {\n\t\t\tconst [startGroup, startObject, rest] = readLocation(afterTag);\n\t\t\texpectEmpty(rest);\n\t\t\treturn { kind: \"absolute\", startGroup, startObject };\n\t\t}\n\t\tcase TAG_ABSOLUTE_RANGE: {\n\t\t\tconst [startGroup, startObject, afterLocation] = readLocation(afterTag);\n\t\t\tconst [delta, rest] = unvarint(afterLocation, version);\n\t\t\texpectEmpty(rest);\n\t\t\treturn { kind: \"absolute\", startGroup, startObject, endGroup: startGroup + delta };\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`unsupported filter type: ${tag}`);\n\t}\n}\n\n/**\n * Read the tagged filter draft-14 carries inline in a SUBSCRIBE body, where the fields\n * following the tag have no length to delimit them.\n *\n * Every tag is read, including the absolute forms we do not serve. Rejecting one would tear\n * the session down over a filter the draft lets a subscriber send; what we do with it is\n * decided when the range is resolved.\n */\nexport async function decodeInline(r: Reader): Promise<Filter> {\n\tconst tag = await r.u62();\n\tswitch (tag) {\n\t\tcase TAG_NEXT_GROUP:\n\t\t\treturn { kind: \"relative\", groups: 0n };\n\t\tcase TAG_LARGEST_OBJECT:\n\t\t\treturn { kind: \"nextObject\" };\n\t\tcase TAG_ABSOLUTE_START:\n\t\t\treturn { kind: \"absolute\", startGroup: await r.u62(), startObject: await r.u62() };\n\t\tcase TAG_ABSOLUTE_RANGE: {\n\t\t\tconst startGroup = await r.u62();\n\t\t\tconst startObject = await r.u62();\n\t\t\tconst delta = await r.u62();\n\t\t\treturn { kind: \"absolute\", startGroup, startObject, endGroup: startGroup + delta };\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`unsupported filter type: ${tag}`);\n\t}\n}\n\nfunction expectEmpty(rest: Uint8Array): void {\n\tif (rest.length !== 0) {\n\t\tthrow new Error(\"trailing bytes in LOCATION_FILTER\");\n\t}\n}\n\n/**\n * A draft-20 fill: the backfill a subscriber asks for alongside its subscription.\n *\n * The publisher serves one whose range resolves to a single group, straight from the group\n * cache on a fetch stream. That covers the draft's own current-group join (a Next Object\n * subscription plus a `StartGroup=1` fill). Anything wider is refused by resetting the\n * fetch stream, the draft's fill-failure signal.\n */\nexport interface Fill {\n\t/**\n\t * The range to fill. `undefined` means the Location Filter was omitted, which inherits\n\t * the subscription's own filter; `unfiltered` (a zero length filter) means the whole\n\t * track up to Largest Object.\n\t */\n\tfilter?: Filter;\n\n\t/**\n\t * Whether the scope carried a Range Filter (0x25-0x28). Those narrow which objects pass,\n\t * which we do not implement, and serving the unfiltered range instead would deliver\n\t * objects the peer excluded. Never encoded; we send no range filters.\n\t */\n\trangeFilters: boolean;\n}\n\n/** LOCATION_FILTER, the only parameter we act on inside a fill. */\nconst FILL_LOCATION_FILTER = 0x21n;\n\n/**\n * The parameters draft-20 allows inside FILL_PARAMETERS, and how each frames its value.\n *\n * Tabulated rather than derived, because neither shortcut is right. The Key-Value-Pair rule\n * keys framing off the id's parity, but the Range Filters (0x25-0x28) carry an explicit\n * Length despite two of them having even ids. And a uint8 parameter is one raw byte rather\n * than a varint, so reading it as one misparses any value with a leading 1-bit. Either\n * mistake desyncs every parameter after it.\n */\n/**\n * Maps each to whether it carries a length prefix.\n *\n * The Key-Value-Pair rule keys the framing off the id's parity, but the Range Filters\n * (0x25-0x28) are written with an explicit `Length` field despite two of them having even\n * ids. Their own definition wins, so the framing is tabulated rather than derived: reading\n * 0x26 or 0x28 as a bare varint would desync every parameter after it.\n */\ntype Framing = \"byte\" | \"varint\" | \"bytes\";\n\nconst FILL_ALLOWED = new Map<bigint, Framing>([\n\t[0x0an, \"varint\"], // FILL_TIMEOUT\n\t[0x20n, \"byte\"], // SUBSCRIBER_PRIORITY, a uint8\n\t[FILL_LOCATION_FILTER, \"bytes\"],\n\t[0x22n, \"byte\"], // GROUP_ORDER, a uint8\n\t[0x25n, \"bytes\"], // SUBGROUP_FILTER\n\t[0x26n, \"bytes\"], // OBJECTID_FILTER, length prefixed despite an even id\n\t[0x27n, \"bytes\"], // PRIORITY_FILTER\n\t[0x28n, \"bytes\"], // OBJECT_PROPERTY_FILTER, likewise\n]);\n\n/**\n * Encode FILL_PARAMETERS, whose presence is what requests a backfill.\n *\n * The value is a nested parameter scope, encoded like a message's parameters.\n */\nexport function encodeFill(fill: Fill, version: IetfVersion): Uint8Array {\n\t// An omitted filter inherits the subscription's, so the scope is empty. An explicit\n\t// unfiltered still encodes, as a zero length filter meaning the whole track.\n\tif (fill.filter === undefined) {\n\t\treturn varint(0n, version);\n\t}\n\treturn concat([\n\t\tvarint(1n, version),\n\t\t// The first type in a scope is not delta encoded, so this is the raw id.\n\t\tvarint(FILL_LOCATION_FILTER, version),\n\t\tencodeLengthPrefixed(encode(fill.filter, version), version),\n\t]);\n}\n\n/** Decode FILL_PARAMETERS, returning the range it asks to fill. */\nexport function decodeFill(data: Uint8Array, version: IetfVersion): Fill {\n\tconst [count, afterCount] = unvarint(data, version);\n\tif (count > 64n) {\n\t\tthrow new Error(\"too many parameters in FILL_PARAMETERS\");\n\t}\n\n\tlet rest = afterCount;\n\tlet filter: Filter | undefined;\n\tlet rangeFilters = false;\n\tlet prev = 0n;\n\tfor (let i = 0n; i < count; i++) {\n\t\tconst [delta, afterType] = unvarint(rest, version);\n\t\tconst key = i === 0n ? delta : prev + delta;\n\t\tprev = key;\n\t\trest = afterType;\n\n\t\tconst framing = FILL_ALLOWED.get(key);\n\t\tif (framing === undefined) {\n\t\t\tthrow new Error(`parameter ${key} is not allowed inside FILL_PARAMETERS`);\n\t\t}\n\n\t\t// A Range Filter changes which objects the fill may contain, so its presence is\n\t\t// recorded even though its value is not interpreted.\n\t\trangeFilters ||= key >= 0x25n && key <= 0x28n;\n\n\t\t// The rest are parameters we do not act on, but their bytes still have to be\n\t\t// consumed or the remaining keys desync.\n\t\tif (framing === \"varint\") {\n\t\t\t[, rest] = unvarint(rest, version);\n\t\t\tcontinue;\n\t\t}\n\t\tif (framing === \"byte\") {\n\t\t\tif (rest.length < 1) throw new Error(\"truncated value inside FILL_PARAMETERS\");\n\t\t\trest = rest.slice(1);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst [length, afterLength] = unvarint(rest, version);\n\t\tif (BigInt(afterLength.length) < length) {\n\t\t\tthrow new Error(\"truncated value inside FILL_PARAMETERS\");\n\t\t}\n\t\tconst value = afterLength.slice(0, Number(length));\n\t\trest = afterLength.slice(Number(length));\n\n\t\tif (key === FILL_LOCATION_FILTER) {\n\t\t\tif (filter !== undefined) {\n\t\t\t\tthrow new Error(\"duplicate LOCATION_FILTER inside FILL_PARAMETERS\");\n\t\t\t}\n\t\t\tfilter = decode(value, version);\n\t\t}\n\t}\n\n\tif (rest.length !== 0) {\n\t\tthrow new Error(\"trailing bytes in FILL_PARAMETERS\");\n\t}\n\n\treturn { filter, rangeFilters };\n}\n\nfunction encodeLengthPrefixed(value: Uint8Array, version: IetfVersion): Uint8Array {\n\treturn concat([varint(BigInt(value.length), version), value]);\n}\n"]}
package/ietf/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./adapter";
2
+ export * as Cluster from "./cluster";
2
3
  export * from "./connection";
3
4
  export * from "./control";
4
5
  export * from "./fetch";
@@ -10,6 +11,7 @@ export * from "./publish_namespace";
10
11
  export * from "./publisher";
11
12
  export * from "./request";
12
13
  export * from "./setup";
14
+ export * from "./solicit";
13
15
  export * from "./subscribe";
14
16
  export * from "./subscribe_namespace";
15
17
  export * from "./subscriber";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ietf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ietf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
package/ietf/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  /* @ts-self-types="./index.d.ts" */
2
2
  export * from "./adapter.js";
3
+ import * as Cluster_1 from "./cluster.js";
4
+ export { Cluster_1 as Cluster };
3
5
  export * from "./connection.js";
4
6
  export * from "./control.js";
5
7
  export * from "./fetch.js";
@@ -11,6 +13,7 @@ export * from "./publish_namespace.js";
11
13
  export * from "./publisher.js";
12
14
  export * from "./request.js";
13
15
  export * from "./setup.js";
16
+ export * from "./solicit.js";
14
17
  export * from "./subscribe.js";
15
18
  export * from "./subscribe_namespace.js";
16
19
  export * from "./subscriber.js";
package/ietf/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ietf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./adapter.ts\";\nexport * from \"./connection.ts\";\nexport * from \"./control.ts\";\nexport * from \"./fetch.ts\";\nexport * from \"./goaway.ts\";\nexport * from \"./object.ts\";\nexport * from \"./parameters.ts\";\nexport * from \"./publish.ts\";\nexport * from \"./publish_namespace.ts\";\nexport * from \"./publisher.ts\";\nexport * from \"./request.ts\";\nexport * from \"./setup.ts\";\nexport * from \"./subscribe.ts\";\nexport * from \"./subscribe_namespace.ts\";\nexport * from \"./subscriber.ts\";\nexport * from \"./track.ts\";\nexport * from \"./version.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ietf/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;2BACJ,cAAc;sBAA3B,OAAO;AACnB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./adapter.ts\";\nexport * as Cluster from \"./cluster.ts\";\nexport * from \"./connection.ts\";\nexport * from \"./control.ts\";\nexport * from \"./fetch.ts\";\nexport * from \"./goaway.ts\";\nexport * from \"./object.ts\";\nexport * from \"./parameters.ts\";\nexport * from \"./publish.ts\";\nexport * from \"./publish_namespace.ts\";\nexport * from \"./publisher.ts\";\nexport * from \"./request.ts\";\nexport * from \"./setup.ts\";\nexport * from \"./solicit.ts\";\nexport * from \"./subscribe.ts\";\nexport * from \"./subscribe_namespace.ts\";\nexport * from \"./subscriber.ts\";\nexport * from \"./track.ts\";\nexport * from \"./version.ts\";\n"]}
@@ -1,5 +1,11 @@
1
1
  import * as Path from "../path";
2
2
  import type { Reader, Writer } from "../stream";
3
+ /** Convert the escaped moq-net path representation into IETF namespace tuple fields. */
4
+ export declare function toTuple(namespace: Path.Valid): string[];
5
+ /** Convert IETF namespace tuple fields into the escaped moq-net path representation. */
6
+ export declare function fromTuple(parts: string[]): Path.Valid;
7
+ /** Encode a moq-net namespace as an IETF namespace tuple. */
3
8
  export declare function encode(w: Writer, namespace: Path.Valid): Promise<void>;
9
+ /** Decode an IETF namespace tuple into an escaped moq-net namespace. */
4
10
  export declare function decode(r: Reader): Promise<Path.Valid>;
5
11
  //# sourceMappingURL=namespace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../src/ietf/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnD,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5E;AAED,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAc3D"}
1
+ {"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../src/ietf/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnD,wFAAwF;AACxF,wBAAgB,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,CAevD;AAED,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAErD;AAED,6DAA6D;AAC7D,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5E;AAED,wEAAwE;AACxE,wBAAsB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAc3D"}
package/ietf/namespace.js CHANGED
@@ -1,7 +1,31 @@
1
1
  /* @ts-self-types="./namespace.d.ts" */
2
2
  import * as Path from "../path.js";
3
+ /** Convert the escaped moq-net path representation into IETF namespace tuple fields. */
4
+ export function toTuple(namespace) {
5
+ if (namespace === "")
6
+ return [];
7
+ const parts = [""];
8
+ for (let i = 0; i < namespace.length; i++) {
9
+ const ch = namespace[i];
10
+ if (ch === "/") {
11
+ parts.push("");
12
+ }
13
+ else if (ch === "\\" && (namespace[i + 1] === "/" || namespace[i + 1] === "\\")) {
14
+ parts[parts.length - 1] += namespace[++i];
15
+ }
16
+ else {
17
+ parts[parts.length - 1] += ch;
18
+ }
19
+ }
20
+ return parts;
21
+ }
22
+ /** Convert IETF namespace tuple fields into the escaped moq-net path representation. */
23
+ export function fromTuple(parts) {
24
+ return parts.map((part) => part.replaceAll("\\", "\\\\").replaceAll("/", "\\/")).join("/");
25
+ }
26
+ /** Encode a moq-net namespace as an IETF namespace tuple. */
3
27
  export async function encode(w, namespace) {
4
- const parts = Path.parts(namespace);
28
+ const parts = toTuple(namespace);
5
29
  // The IETF draft limits namespaces to 32 parts.
6
30
  if (parts.length > Path.MAX_PARTS) {
7
31
  throw new Error(`namespace exceeds ${Path.MAX_PARTS} parts`);
@@ -11,6 +35,7 @@ export async function encode(w, namespace) {
11
35
  await w.string(part);
12
36
  }
13
37
  }
38
+ /** Decode an IETF namespace tuple into an escaped moq-net namespace. */
14
39
  export async function decode(r) {
15
40
  const count = await r.u53();
16
41
  // The IETF draft limits namespaces to 32 parts. Reject before reading them so a
@@ -22,6 +47,6 @@ export async function decode(r) {
22
47
  for (let i = 0; i < count; i++) {
23
48
  parts.push(await r.string());
24
49
  }
25
- return Path.from(...parts);
50
+ return fromTuple(parts);
26
51
  }
27
52
  //# sourceMappingURL=namespace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../src/ietf/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAGnC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,CAAS,EAAE,SAAqB;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEpC,gDAAgD;IAChD,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,CAAS;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;IAE5B,gFAAgF;IAChF,sDAAsD;IACtD,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;AAC5B,CAAC","sourcesContent":["import * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\n\nexport async function encode(w: Writer, namespace: Path.Valid): Promise<void> {\n\tconst parts = Path.parts(namespace);\n\n\t// The IETF draft limits namespaces to 32 parts.\n\tif (parts.length > Path.MAX_PARTS) {\n\t\tthrow new Error(`namespace exceeds ${Path.MAX_PARTS} parts`);\n\t}\n\n\tawait w.u53(parts.length);\n\tfor (const part of parts) {\n\t\tawait w.string(part);\n\t}\n}\n\nexport async function decode(r: Reader): Promise<Path.Valid> {\n\tconst count = await r.u53();\n\n\t// The IETF draft limits namespaces to 32 parts. Reject before reading them so a\n\t// hostile count can't make us buffer unbounded parts.\n\tif (count > Path.MAX_PARTS) {\n\t\tthrow new Error(`namespace exceeds ${Path.MAX_PARTS} parts`);\n\t}\n\n\tconst parts: string[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tparts.push(await r.string());\n\t}\n\treturn Path.from(...parts);\n}\n"]}
1
+ {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../src/ietf/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAGnC,wFAAwF;AACxF,MAAM,UAAU,OAAO,CAAC,SAAqB;IAC5C,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAEhC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;aAAM,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YACnF,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,SAAS,CAAC,KAAe;IACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAe,CAAC;AAC1G,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,CAAS,EAAE,SAAqB;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAEjC,gDAAgD;IAChD,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACF,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,CAAS;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;IAE5B,gFAAgF;IAChF,sDAAsD;IACtD,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC","sourcesContent":["import * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\n\n/** Convert the escaped moq-net path representation into IETF namespace tuple fields. */\nexport function toTuple(namespace: Path.Valid): string[] {\n\tif (namespace === \"\") return [];\n\n\tconst parts = [\"\"];\n\tfor (let i = 0; i < namespace.length; i++) {\n\t\tconst ch = namespace[i];\n\t\tif (ch === \"/\") {\n\t\t\tparts.push(\"\");\n\t\t} else if (ch === \"\\\\\" && (namespace[i + 1] === \"/\" || namespace[i + 1] === \"\\\\\")) {\n\t\t\tparts[parts.length - 1] += namespace[++i];\n\t\t} else {\n\t\t\tparts[parts.length - 1] += ch;\n\t\t}\n\t}\n\treturn parts;\n}\n\n/** Convert IETF namespace tuple fields into the escaped moq-net path representation. */\nexport function fromTuple(parts: string[]): Path.Valid {\n\treturn parts.map((part) => part.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"/\", \"\\\\/\")).join(\"/\") as Path.Valid;\n}\n\n/** Encode a moq-net namespace as an IETF namespace tuple. */\nexport async function encode(w: Writer, namespace: Path.Valid): Promise<void> {\n\tconst parts = toTuple(namespace);\n\n\t// The IETF draft limits namespaces to 32 parts.\n\tif (parts.length > Path.MAX_PARTS) {\n\t\tthrow new Error(`namespace exceeds ${Path.MAX_PARTS} parts`);\n\t}\n\n\tawait w.u53(parts.length);\n\tfor (const part of parts) {\n\t\tawait w.string(part);\n\t}\n}\n\n/** Decode an IETF namespace tuple into an escaped moq-net namespace. */\nexport async function decode(r: Reader): Promise<Path.Valid> {\n\tconst count = await r.u53();\n\n\t// The IETF draft limits namespaces to 32 parts. Reject before reading them so a\n\t// hostile count can't make us buffer unbounded parts.\n\tif (count > Path.MAX_PARTS) {\n\t\tthrow new Error(`namespace exceeds ${Path.MAX_PARTS} parts`);\n\t}\n\n\tconst parts: string[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tparts.push(await r.string());\n\t}\n\treturn fromTuple(parts);\n}\n"]}