Skip to main content

moqtap_codec/draft14/
message.rs

1use crate::auth_token::{AuthorizationToken, AUTH_TOKEN_PARAMETER};
2use crate::error::{
3    CodecError, MAX_FULL_TRACK_NAME_LENGTH, MAX_GOAWAY_URI_LENGTH, MAX_MESSAGE_LENGTH,
4    MAX_REASON_PHRASE_LENGTH,
5};
6use crate::kvp::{KeyValuePair, KvpValue};
7use crate::types::*;
8pub use crate::types::{check_group_range, check_location_range, check_open_ended_group_range};
9use crate::varint::VarInt;
10use bytes::{Buf, BufMut};
11
12/// Control message type IDs (draft-14).
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14#[repr(u64)]
15pub enum MessageType {
16    /// SubscribeUpdate (type 0x02).
17    SubscribeUpdate = 0x02,
18    /// Subscribe (type 0x03).
19    Subscribe = 0x03,
20    /// SubscribeOk (type 0x04).
21    SubscribeOk = 0x04,
22    /// SubscribeError (type 0x05).
23    SubscribeError = 0x05,
24    /// PublishNamespace (type 0x06).
25    PublishNamespace = 0x06,
26    /// PublishNamespaceOk (type 0x07).
27    PublishNamespaceOk = 0x07,
28    /// PublishNamespaceError (type 0x08).
29    PublishNamespaceError = 0x08,
30    /// PublishNamespaceDone (type 0x09).
31    PublishNamespaceDone = 0x09,
32    /// Unsubscribe (type 0x0A).
33    Unsubscribe = 0x0A,
34    /// PublishDone (type 0x0B).
35    PublishDone = 0x0B,
36    /// PublishNamespaceCancel (type 0x0C).
37    PublishNamespaceCancel = 0x0C,
38    /// TrackStatus (type 0x0D).
39    TrackStatus = 0x0D,
40    /// TrackStatusOk (type 0x0E).
41    TrackStatusOk = 0x0E,
42    /// TrackStatusError (type 0x0F).
43    TrackStatusError = 0x0F,
44    /// GoAway (type 0x10).
45    GoAway = 0x10,
46    /// SubscribeNamespace (type 0x11).
47    SubscribeNamespace = 0x11,
48    /// SubscribeNamespaceOk (type 0x12).
49    SubscribeNamespaceOk = 0x12,
50    /// SubscribeNamespaceError (type 0x13).
51    SubscribeNamespaceError = 0x13,
52    /// UnsubscribeNamespace (type 0x14).
53    UnsubscribeNamespace = 0x14,
54    /// MaxRequestId (type 0x15).
55    MaxRequestId = 0x15,
56    /// Fetch (type 0x16).
57    Fetch = 0x16,
58    /// FetchCancel (type 0x17).
59    FetchCancel = 0x17,
60    /// FetchOk (type 0x18).
61    FetchOk = 0x18,
62    /// FetchError (type 0x19).
63    FetchError = 0x19,
64    /// RequestsBlocked (type 0x1A).
65    RequestsBlocked = 0x1A,
66    /// Publish (type 0x1D).
67    Publish = 0x1D,
68    /// PublishOk (type 0x1E).
69    PublishOk = 0x1E,
70    /// PublishError (type 0x1F).
71    PublishError = 0x1F,
72    /// ClientSetup (type 0x20).
73    ClientSetup = 0x20,
74    /// ServerSetup (type 0x21).
75    ServerSetup = 0x21,
76}
77
78impl MessageType {
79    /// Look up a message type by its wire ID.
80    pub fn from_id(id: u64) -> Option<Self> {
81        match id {
82            0x02 => Some(MessageType::SubscribeUpdate),
83            0x03 => Some(MessageType::Subscribe),
84            0x04 => Some(MessageType::SubscribeOk),
85            0x05 => Some(MessageType::SubscribeError),
86            0x06 => Some(MessageType::PublishNamespace),
87            0x07 => Some(MessageType::PublishNamespaceOk),
88            0x08 => Some(MessageType::PublishNamespaceError),
89            0x09 => Some(MessageType::PublishNamespaceDone),
90            0x0A => Some(MessageType::Unsubscribe),
91            0x0B => Some(MessageType::PublishDone),
92            0x0C => Some(MessageType::PublishNamespaceCancel),
93            0x0D => Some(MessageType::TrackStatus),
94            0x0E => Some(MessageType::TrackStatusOk),
95            0x0F => Some(MessageType::TrackStatusError),
96            0x10 => Some(MessageType::GoAway),
97            0x11 => Some(MessageType::SubscribeNamespace),
98            0x12 => Some(MessageType::SubscribeNamespaceOk),
99            0x13 => Some(MessageType::SubscribeNamespaceError),
100            0x14 => Some(MessageType::UnsubscribeNamespace),
101            0x15 => Some(MessageType::MaxRequestId),
102            0x16 => Some(MessageType::Fetch),
103            0x17 => Some(MessageType::FetchCancel),
104            0x18 => Some(MessageType::FetchOk),
105            0x19 => Some(MessageType::FetchError),
106            0x1A => Some(MessageType::RequestsBlocked),
107            0x1D => Some(MessageType::Publish),
108            0x1E => Some(MessageType::PublishOk),
109            0x1F => Some(MessageType::PublishError),
110            0x20 => Some(MessageType::ClientSetup),
111            0x21 => Some(MessageType::ServerSetup),
112            _ => None,
113        }
114    }
115
116    /// Return the wire ID for this message type.
117    pub fn id(&self) -> u64 {
118        *self as u64
119    }
120
121    /// This type's name in the shared vector corpus: the `message_type` its
122    /// draft's `codec/messages/*.json` files carry, in `snake_case`.
123    pub fn name(&self) -> &'static str {
124        match self {
125            MessageType::SubscribeUpdate => "subscribe_update",
126            MessageType::Subscribe => "subscribe",
127            MessageType::SubscribeOk => "subscribe_ok",
128            MessageType::SubscribeError => "subscribe_error",
129            MessageType::PublishNamespace => "publish_namespace",
130            MessageType::PublishNamespaceOk => "publish_namespace_ok",
131            MessageType::PublishNamespaceError => "publish_namespace_error",
132            MessageType::PublishNamespaceDone => "publish_namespace_done",
133            MessageType::Unsubscribe => "unsubscribe",
134            MessageType::PublishDone => "publish_done",
135            MessageType::PublishNamespaceCancel => "publish_namespace_cancel",
136            MessageType::TrackStatus => "track_status",
137            MessageType::TrackStatusOk => "track_status_ok",
138            MessageType::TrackStatusError => "track_status_error",
139            MessageType::GoAway => "goaway",
140            MessageType::SubscribeNamespace => "subscribe_namespace",
141            MessageType::SubscribeNamespaceOk => "subscribe_namespace_ok",
142            MessageType::SubscribeNamespaceError => "subscribe_namespace_error",
143            MessageType::UnsubscribeNamespace => "unsubscribe_namespace",
144            MessageType::MaxRequestId => "max_request_id",
145            MessageType::Fetch => "fetch",
146            MessageType::FetchCancel => "fetch_cancel",
147            MessageType::FetchOk => "fetch_ok",
148            MessageType::FetchError => "fetch_error",
149            MessageType::RequestsBlocked => "requests_blocked",
150            MessageType::Publish => "publish",
151            MessageType::PublishOk => "publish_ok",
152            MessageType::PublishError => "publish_error",
153            MessageType::ClientSetup => "client_setup",
154            MessageType::ServerSetup => "server_setup",
155        }
156    }
157}
158
159// ============================================================
160// Session Lifecycle Messages
161// ============================================================
162
163/// CLIENT_SETUP message (type 0x20).
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct ClientSetup {
166    /// List of MoQT versions supported by the client.
167    pub supported_versions: Vec<VarInt>,
168    /// Setup parameters.
169    pub parameters: Vec<KeyValuePair>,
170}
171
172/// SERVER_SETUP message (type 0x21).
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct ServerSetup {
175    /// The MoQT version selected by the server.
176    pub selected_version: VarInt,
177    /// Setup parameters.
178    pub parameters: Vec<KeyValuePair>,
179}
180
181/// GOAWAY message (type 0x10).
182#[derive(Debug, Clone, PartialEq, Eq)]
183pub struct GoAway {
184    /// URI for the new session to connect to.
185    pub new_session_uri: Vec<u8>,
186}
187
188/// MAX_REQUEST_ID message (type 0x15).
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub struct MaxRequestId {
191    /// The maximum request ID the peer may use.
192    pub request_id: VarInt,
193}
194
195/// REQUESTS_BLOCKED message (type 0x1A).
196#[derive(Debug, Clone, PartialEq, Eq)]
197pub struct RequestsBlocked {
198    /// The request ID that is currently blocked on.
199    pub maximum_request_id: VarInt,
200}
201
202// ============================================================
203// Subscribe Messages
204// ============================================================
205
206/// SUBSCRIBE message (type 0x03).
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct Subscribe {
209    /// The request ID for this subscription.
210    pub request_id: VarInt,
211    /// The track namespace.
212    pub track_namespace: TrackNamespace,
213    /// The track name within the namespace.
214    pub track_name: Vec<u8>,
215    /// Subscriber priority for this track.
216    pub subscriber_priority: u8,
217    /// Requested group delivery order.
218    pub group_order: GroupOrder,
219    /// Whether to forward data on this subscription.
220    pub forward: Forward,
221    /// The filter type controlling which objects are delivered.
222    pub filter_type: FilterType,
223    /// Present only for AbsoluteStart and AbsoluteRange filter types.
224    pub start_location: Option<Location>,
225    /// Present only for AbsoluteRange filter type.
226    pub end_group: Option<VarInt>,
227    /// Subscribe parameters.
228    pub parameters: Vec<KeyValuePair>,
229}
230
231/// SUBSCRIBE_OK message (type 0x04).
232#[derive(Debug, Clone, PartialEq, Eq)]
233pub struct SubscribeOk {
234    /// The request ID this response corresponds to.
235    pub request_id: VarInt,
236    /// The track alias assigned by the publisher.
237    pub track_alias: VarInt,
238    /// Subscription expiry in milliseconds (0 = no expiry).
239    pub expires: VarInt,
240    /// The group delivery order chosen by the publisher.
241    pub group_order: GroupOrder,
242    /// Whether the largest location is included.
243    pub content_exists: ContentExists,
244    /// Present only when content_exists == HasLargestLocation.
245    pub largest_location: Option<Location>,
246    /// Response parameters.
247    pub parameters: Vec<KeyValuePair>,
248}
249
250/// SUBSCRIBE_ERROR message (type 0x05).
251#[derive(Debug, Clone, PartialEq, Eq)]
252pub struct SubscribeError {
253    /// The request ID this error corresponds to.
254    pub request_id: VarInt,
255    /// Application-defined error code.
256    pub error_code: VarInt,
257    /// Human-readable reason phrase.
258    pub reason_phrase: Vec<u8>,
259}
260
261/// SUBSCRIBE_UPDATE message (type 0x02).
262#[derive(Debug, Clone, PartialEq, Eq)]
263pub struct SubscribeUpdate {
264    /// The request ID for this update message.
265    pub request_id: VarInt,
266    /// The request ID of the subscription being updated.
267    pub subscription_request_id: VarInt,
268    /// Updated start location.
269    pub start_location: Location,
270    /// Updated end group.
271    pub end_group: VarInt,
272    /// Updated subscriber priority.
273    pub subscriber_priority: u8,
274    /// Updated forward preference.
275    pub forward: Forward,
276    /// Updated parameters.
277    pub parameters: Vec<KeyValuePair>,
278}
279
280/// UNSUBSCRIBE message (type 0x0A).
281#[derive(Debug, Clone, PartialEq, Eq)]
282pub struct Unsubscribe {
283    /// The request ID of the subscription to cancel.
284    pub request_id: VarInt,
285}
286
287// ============================================================
288// Publish Messages
289// ============================================================
290
291/// PUBLISH message (type 0x1D).
292#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct Publish {
294    /// Request ID.
295    pub request_id: VarInt,
296    /// Track namespace.
297    pub track_namespace: TrackNamespace,
298    /// Track name.
299    pub track_name: Vec<u8>,
300    /// Track alias assigned by the publisher.
301    pub track_alias: VarInt,
302    /// Group delivery order.
303    pub group_order: GroupOrder,
304    /// Whether a largest location is included.
305    pub content_exists: ContentExists,
306    /// Largest location, present when content_exists == HasLargestLocation.
307    pub largest_location: Option<Location>,
308    /// Forward preference.
309    pub forward: Forward,
310    /// Publish parameters.
311    pub parameters: Vec<KeyValuePair>,
312}
313
314/// PUBLISH_OK message (type 0x1E).
315#[derive(Debug, Clone, PartialEq, Eq)]
316pub struct PublishOk {
317    /// Request ID this response corresponds to.
318    pub request_id: VarInt,
319    /// Forward preference.
320    pub forward: Forward,
321    /// Subscriber priority.
322    pub subscriber_priority: u8,
323    /// Group order.
324    pub group_order: GroupOrder,
325    /// Filter type.
326    pub filter_type: FilterType,
327    /// Present only for AbsoluteStart and AbsoluteRange filter types.
328    pub start_location: Option<Location>,
329    /// Present only for AbsoluteRange filter type.
330    pub end_group: Option<VarInt>,
331    /// Response parameters.
332    pub parameters: Vec<KeyValuePair>,
333}
334
335/// PUBLISH_ERROR message (type 0x1F).
336#[derive(Debug, Clone, PartialEq, Eq)]
337pub struct PublishError {
338    /// The request ID this error corresponds to.
339    pub request_id: VarInt,
340    /// Application-defined error code.
341    pub error_code: VarInt,
342    /// Human-readable reason phrase.
343    pub reason_phrase: Vec<u8>,
344}
345
346/// PUBLISH_DONE message (type 0x0B).
347#[derive(Debug, Clone, PartialEq, Eq)]
348pub struct PublishDone {
349    /// Request ID.
350    pub request_id: VarInt,
351    /// Status code describing why the publish finished.
352    pub status_code: VarInt,
353    /// Number of data streams used by this publish.
354    pub stream_count: VarInt,
355    /// Human-readable reason phrase.
356    pub reason_phrase: Vec<u8>,
357}
358
359// ============================================================
360// Publish Namespace Messages
361// ============================================================
362
363/// PUBLISH_NAMESPACE message (type 0x06).
364#[derive(Debug, Clone, PartialEq, Eq)]
365pub struct PublishNamespace {
366    /// The request ID for this namespace publish.
367    pub request_id: VarInt,
368    /// The track namespace to publish.
369    pub track_namespace: TrackNamespace,
370    /// Publish namespace parameters.
371    pub parameters: Vec<KeyValuePair>,
372}
373
374/// PUBLISH_NAMESPACE_OK message (type 0x07).
375#[derive(Debug, Clone, PartialEq, Eq)]
376pub struct PublishNamespaceOk {
377    /// The request ID this response corresponds to.
378    pub request_id: VarInt,
379}
380
381/// PUBLISH_NAMESPACE_ERROR message (type 0x08).
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub struct PublishNamespaceError {
384    /// The request ID this error corresponds to.
385    pub request_id: VarInt,
386    /// Application-defined error code.
387    pub error_code: VarInt,
388    /// Human-readable reason phrase.
389    pub reason_phrase: Vec<u8>,
390}
391
392/// PUBLISH_NAMESPACE_DONE message (type 0x09).
393#[derive(Debug, Clone, PartialEq, Eq)]
394pub struct PublishNamespaceDone {
395    /// Track namespace being finalized.
396    pub track_namespace: TrackNamespace,
397}
398
399/// PUBLISH_NAMESPACE_CANCEL message (type 0x0C).
400#[derive(Debug, Clone, PartialEq, Eq)]
401pub struct PublishNamespaceCancel {
402    /// Track namespace being cancelled.
403    pub track_namespace: TrackNamespace,
404    /// Application-defined error code.
405    pub error_code: VarInt,
406    /// Human-readable reason phrase.
407    pub reason_phrase: Vec<u8>,
408}
409
410// ============================================================
411// Subscribe Namespace Messages
412// ============================================================
413
414/// SUBSCRIBE_NAMESPACE message (type 0x11).
415#[derive(Debug, Clone, PartialEq, Eq)]
416pub struct SubscribeNamespace {
417    /// The request ID for this namespace subscription.
418    pub request_id: VarInt,
419    /// The track namespace to subscribe to.
420    pub track_namespace: TrackNamespace,
421    /// Subscribe namespace parameters.
422    pub parameters: Vec<KeyValuePair>,
423}
424
425/// SUBSCRIBE_NAMESPACE_OK message (type 0x12).
426#[derive(Debug, Clone, PartialEq, Eq)]
427pub struct SubscribeNamespaceOk {
428    /// The request ID this response corresponds to.
429    pub request_id: VarInt,
430}
431
432/// SUBSCRIBE_NAMESPACE_ERROR message (type 0x13).
433#[derive(Debug, Clone, PartialEq, Eq)]
434pub struct SubscribeNamespaceError {
435    /// The request ID this error corresponds to.
436    pub request_id: VarInt,
437    /// Application-defined error code.
438    pub error_code: VarInt,
439    /// Human-readable reason phrase.
440    pub reason_phrase: Vec<u8>,
441}
442
443/// UNSUBSCRIBE_NAMESPACE message (type 0x14).
444#[derive(Debug, Clone, PartialEq, Eq)]
445pub struct UnsubscribeNamespace {
446    /// The namespace prefix of the namespace subscription to cancel.
447    pub track_namespace_prefix: TrackNamespace,
448}
449
450// ============================================================
451// Fetch Messages
452// ============================================================
453
454/// FETCH type discriminator (standalone vs joining).
455#[derive(Debug, Clone, Copy, PartialEq, Eq)]
456#[repr(u64)]
457pub enum FetchType {
458    /// Standalone fetch with explicit track and range.
459    Standalone = 1,
460    /// Joining fetch relative to a subscribe request.
461    RelativeJoining = 2,
462    /// Joining fetch at an absolute group.
463    AbsoluteJoining = 3,
464}
465
466impl FetchType {
467    /// Convert a raw wire value to a [`FetchType`].
468    pub fn from_u64(v: u64) -> Option<Self> {
469        match v {
470            1 => Some(FetchType::Standalone),
471            2 => Some(FetchType::RelativeJoining),
472            3 => Some(FetchType::AbsoluteJoining),
473            _ => None,
474        }
475    }
476}
477
478/// FETCH payload — either a standalone fetch or a joining fetch.
479#[derive(Debug, Clone, PartialEq, Eq)]
480pub enum FetchPayload {
481    /// Standalone fetch.
482    Standalone {
483        /// Track namespace.
484        track_namespace: TrackNamespace,
485        /// Track name.
486        track_name: Vec<u8>,
487        /// Starting group ID.
488        start_group: VarInt,
489        /// Starting object ID.
490        start_object: VarInt,
491        /// Ending group ID.
492        end_group: VarInt,
493        /// Ending object ID.
494        end_object: VarInt,
495    },
496    /// Joining fetch.
497    Joining {
498        /// The Request ID of the subscription this fetch joins.
499        ///
500        /// Section 9.16.2 names the field Joining Request ID, as every draft
501        /// from 12 on does. Drafts 08 through 11 spelled it Joining Subscribe
502        /// ID.
503        joining_request_id: VarInt,
504        /// Joining start (relative offset or absolute group).
505        joining_start: VarInt,
506    },
507}
508
509/// FETCH message (type 0x16).
510#[derive(Debug, Clone, PartialEq, Eq)]
511pub struct Fetch {
512    /// The request ID for this fetch.
513    pub request_id: VarInt,
514    /// Subscriber priority.
515    pub subscriber_priority: u8,
516    /// Requested group order.
517    pub group_order: GroupOrder,
518    /// Fetch type discriminator.
519    pub fetch_type: FetchType,
520    /// Variant-specific payload.
521    pub fetch_payload: FetchPayload,
522    /// Fetch parameters.
523    pub parameters: Vec<KeyValuePair>,
524}
525
526/// FETCH_OK message (type 0x18).
527#[derive(Debug, Clone, PartialEq, Eq)]
528pub struct FetchOk {
529    /// The request ID this response corresponds to.
530    pub request_id: VarInt,
531    /// Group order chosen by the publisher.
532    pub group_order: GroupOrder,
533    /// End-of-track flag. A single byte, per Figure 39.
534    pub end_of_track: u8,
535    /// End location (largest group / object in the fetch).
536    pub end_location: Location,
537    /// Response parameters.
538    pub parameters: Vec<KeyValuePair>,
539}
540
541/// FETCH_ERROR message (type 0x19).
542#[derive(Debug, Clone, PartialEq, Eq)]
543pub struct FetchError {
544    /// The request ID this error corresponds to.
545    pub request_id: VarInt,
546    /// Application-defined error code.
547    pub error_code: VarInt,
548    /// Human-readable reason phrase.
549    pub reason_phrase: Vec<u8>,
550}
551
552/// FETCH_CANCEL message (type 0x17).
553#[derive(Debug, Clone, PartialEq, Eq)]
554pub struct FetchCancel {
555    /// The request ID of the fetch to cancel.
556    pub request_id: VarInt,
557}
558
559// ============================================================
560// Track Status Messages
561// ============================================================
562
563/// TRACK_STATUS message (type 0x0D) — subscribe-like request.
564#[derive(Debug, Clone, PartialEq, Eq)]
565pub struct TrackStatus {
566    /// The request ID for this track status query.
567    pub request_id: VarInt,
568    /// The track namespace to query status for.
569    pub track_namespace: TrackNamespace,
570    /// The track name within the namespace.
571    pub track_name: Vec<u8>,
572    /// Subscriber priority.
573    pub subscriber_priority: u8,
574    /// Requested group order.
575    pub group_order: GroupOrder,
576    /// Forward preference.
577    pub forward: Forward,
578    /// Filter type.
579    pub filter_type: FilterType,
580    /// Present only for AbsoluteStart and AbsoluteRange filter types.
581    pub start_location: Option<Location>,
582    /// Present only for AbsoluteRange filter type.
583    pub end_group: Option<VarInt>,
584    /// Track status parameters.
585    pub parameters: Vec<KeyValuePair>,
586}
587
588/// TRACK_STATUS_OK message (type 0x0E) — subscribe_ok-like response.
589#[derive(Debug, Clone, PartialEq, Eq)]
590pub struct TrackStatusOk {
591    /// The request ID this response corresponds to.
592    pub request_id: VarInt,
593    /// Track alias.
594    pub track_alias: VarInt,
595    /// Subscription expiry in milliseconds.
596    pub expires: VarInt,
597    /// Group order.
598    pub group_order: GroupOrder,
599    /// Whether content exists / largest location is present.
600    pub content_exists: ContentExists,
601    /// The largest location, present when content_exists == HasLargestLocation.
602    pub largest_location: Option<Location>,
603    /// Response parameters.
604    pub parameters: Vec<KeyValuePair>,
605}
606
607/// TRACK_STATUS_ERROR message (type 0x0F).
608#[derive(Debug, Clone, PartialEq, Eq)]
609pub struct TrackStatusError {
610    /// The request ID this error corresponds to.
611    pub request_id: VarInt,
612    /// Application-defined error code.
613    pub error_code: VarInt,
614    /// Human-readable reason phrase.
615    pub reason_phrase: Vec<u8>,
616}
617
618// ============================================================
619// Unified Message Enum
620// ============================================================
621
622/// A parsed MoQT control message (draft-14).
623#[derive(Debug, Clone, PartialEq, Eq)]
624pub enum ControlMessage {
625    /// ClientSetup (type 0x20).
626    ClientSetup(ClientSetup),
627    /// ServerSetup (type 0x21).
628    ServerSetup(ServerSetup),
629    /// GoAway (type 0x10).
630    GoAway(GoAway),
631    /// MaxRequestId (type 0x15).
632    MaxRequestId(MaxRequestId),
633    /// RequestsBlocked (type 0x1A).
634    RequestsBlocked(RequestsBlocked),
635    /// Subscribe (type 0x03).
636    Subscribe(Subscribe),
637    /// SubscribeOk (type 0x04).
638    SubscribeOk(SubscribeOk),
639    /// SubscribeError (type 0x05).
640    SubscribeError(SubscribeError),
641    /// SubscribeUpdate (type 0x02).
642    SubscribeUpdate(SubscribeUpdate),
643    /// Unsubscribe (type 0x0A).
644    Unsubscribe(Unsubscribe),
645    /// Publish (type 0x1D).
646    Publish(Publish),
647    /// PublishOk (type 0x1E).
648    PublishOk(PublishOk),
649    /// PublishError (type 0x1F).
650    PublishError(PublishError),
651    /// PublishDone (type 0x0B).
652    PublishDone(PublishDone),
653    /// PublishNamespace (type 0x06).
654    PublishNamespace(PublishNamespace),
655    /// PublishNamespaceOk (type 0x07).
656    PublishNamespaceOk(PublishNamespaceOk),
657    /// PublishNamespaceError (type 0x08).
658    PublishNamespaceError(PublishNamespaceError),
659    /// PublishNamespaceDone (type 0x09).
660    PublishNamespaceDone(PublishNamespaceDone),
661    /// PublishNamespaceCancel (type 0x0C).
662    PublishNamespaceCancel(PublishNamespaceCancel),
663    /// SubscribeNamespace (type 0x11).
664    SubscribeNamespace(SubscribeNamespace),
665    /// SubscribeNamespaceOk (type 0x12).
666    SubscribeNamespaceOk(SubscribeNamespaceOk),
667    /// SubscribeNamespaceError (type 0x13).
668    SubscribeNamespaceError(SubscribeNamespaceError),
669    /// UnsubscribeNamespace (type 0x14).
670    UnsubscribeNamespace(UnsubscribeNamespace),
671    /// Fetch (type 0x16).
672    Fetch(Fetch),
673    /// FetchOk (type 0x18).
674    FetchOk(FetchOk),
675    /// FetchError (type 0x19).
676    FetchError(FetchError),
677    /// FetchCancel (type 0x17).
678    FetchCancel(FetchCancel),
679    /// TrackStatus (type 0x0D).
680    TrackStatus(TrackStatus),
681    /// TrackStatusOk (type 0x0E).
682    TrackStatusOk(TrackStatusOk),
683    /// TrackStatusError (type 0x0F).
684    TrackStatusError(TrackStatusError),
685}
686
687/// Read a Group Order from a message that must name a real order.
688///
689/// Draft-14 states it for four messages, in the same words each time: "Values
690/// of 0x0 and those larger than 0x2 are a protocol error" — SUBSCRIBE_OK in
691/// Section 9.8, PUBLISH in Section 9.13, PUBLISH_OK in Section 9.14 and FETCH_OK
692/// in Section 9.17. TRACK_STATUS_OK takes the same reader without stating the
693/// sentence itself, because Section 9.21 says its "message format is identical
694/// to the SUBSCRIBE_OK message" and that a publisher "populates the fields of
695/// TRACK_STATUS_OK exactly as it would have populated a SUBSCRIBE_OK".
696///
697/// SUBSCRIBE, FETCH and TRACK_STATUS are the requests and keep the ordinary
698/// reader: there 0x0 is exactly how a subscriber says it has no preference —
699/// "A value of 0x0 indicates the original publisher's Group Order SHOULD be
700/// used" — and only values above 0x2 are called an error. The two readers
701/// cannot be merged without either refusing traffic the requests permit or
702/// accepting a reply that tells the subscriber nothing.
703fn read_group_order_response(buf: &mut impl Buf) -> Result<GroupOrder, CodecError> {
704    if !buf.has_remaining() {
705        return Err(CodecError::UnexpectedEnd);
706    }
707    match GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)? {
708        GroupOrder::Publisher => Err(CodecError::InvalidField),
709        order => Ok(order),
710    }
711}
712
713/// Refuse a Group Order of 0x0 on the messages that forbid it.
714///
715/// The decoders refuse it on the way in; without this the codec would still
716/// write a frame its own reader rejects.
717fn check_group_order(message: &ControlMessage) -> Result<(), CodecError> {
718    let order = match message {
719        ControlMessage::SubscribeOk(m) => m.group_order,
720        ControlMessage::TrackStatusOk(m) => m.group_order,
721        ControlMessage::FetchOk(m) => m.group_order,
722        ControlMessage::Publish(m) => m.group_order,
723        ControlMessage::PublishOk(m) => m.group_order,
724        _ => return Ok(()),
725    };
726    if order == GroupOrder::Publisher {
727        return Err(CodecError::InvalidField);
728    }
729    Ok(())
730}
731
732/// Hold a namespace-plus-name pair to the Full Track Name cap.
733///
734/// Draft-14 Section 2.4.1: "The maximum total length of a Full Track Name is
735/// 4,096 bytes, computed as the sum of the lengths of each Track Namespace tuple
736/// field and the Track Name length field. If an endpoint receives a Full Track
737/// Name exceeding this length, it MUST close the session with a
738/// PROTOCOL_VIOLATION."
739///
740/// The two lengths arrive as separate fields, so neither the namespace decoder
741/// nor the name decoder can settle this alone: a namespace at 4,000 bytes and a
742/// name at 500 are each legal by themselves. It has to live where a message
743/// decodes both.
744///
745/// Draft-14 states no separate cap on a Track Namespace on its own — that
746/// sentence arrives in draft-16 — so this pairwise sum is the only bound the
747/// draft gives. A control message may be 65,535 bytes, so without it a peer can
748/// hand the application a Full Track Name sixteen times the permitted size, and
749/// two relays that disagree about whether it was legal disagree about cache
750/// identity.
751/// Refuse a message whose discriminator disagrees with the fields beside it.
752///
753/// Several draft-14 messages carry a field that says which of the following
754/// fields are on the wire — FETCH's Fetch Type, SUBSCRIBE's Filter Type,
755/// SUBSCRIBE_OK's ContentExists. This codec holds the optional halves in
756/// `Option`s and an enum, so a value can say one thing in its discriminator and
757/// another in its body, and the two sides of the codec resolve that differently:
758/// the encoder writes whatever the body holds, and the decoder reads whatever
759/// the discriminator announces.
760///
761/// The result is a message that does not survive its own round trip. A FETCH
762/// whose type says Standalone and whose body is a joining pair encodes to a
763/// request id and a start where a namespace and a name belong, and comes back
764/// as a Standalone fetch of a track named after two integers — or, more often,
765/// as an error, which at least is honest. Refusing at the encoder keeps the two
766/// readings from ever diverging on the wire.
767fn check_discriminators(message: &ControlMessage) -> Result<(), CodecError> {
768    match message {
769        ControlMessage::Fetch(m) => {
770            let body_is_standalone = matches!(m.fetch_payload, FetchPayload::Standalone { .. });
771            if body_is_standalone != (m.fetch_type == FetchType::Standalone) {
772                return Err(CodecError::InvalidField);
773            }
774        }
775        ControlMessage::Subscribe(m) => {
776            let wants_start =
777                matches!(m.filter_type, FilterType::AbsoluteStart | FilterType::AbsoluteRange);
778            if wants_start != m.start_location.is_some() {
779                return Err(CodecError::InvalidField);
780            }
781            if (m.filter_type == FilterType::AbsoluteRange) != m.end_group.is_some() {
782                return Err(CodecError::InvalidField);
783            }
784        }
785        ControlMessage::SubscribeOk(m) => {
786            let has_location = m.content_exists == ContentExists::HasLargestLocation;
787            if has_location != m.largest_location.is_some() {
788                return Err(CodecError::InvalidField);
789            }
790        }
791        _ => {}
792    }
793    Ok(())
794}
795
796/// Read a Reason Phrase, holding it to the cap the draft states for the reader.
797///
798/// Section 1.4.3: "The reason phrase length has a maximum length of 1024 bytes.
799/// If an endpoint receives a length exceeding the maximum, it MUST close the
800/// session with a PROTOCOL_VIOLATION".
801///
802/// The rule is written for the receiver, and the receiver is the side that was
803/// missing it: every encoder here already refused an over-long phrase, so the
804/// codec held itself to a rule it applied to nobody else. A control message may
805/// be 65,535 bytes, so a peer could hand the application a reason phrase
806/// sixty-four times the permitted length, on any of the nine messages that
807/// carry one.
808///
809/// The length is checked before the bytes are read, so an over-long phrase
810/// costs nothing to refuse.
811fn read_reason_phrase(buf: &mut impl Buf) -> Result<Vec<u8>, CodecError> {
812    let len = VarInt::decode(buf)?.into_inner() as usize;
813    if len > MAX_REASON_PHRASE_LENGTH {
814        return Err(CodecError::ReasonPhraseTooLong);
815    }
816    read_bytes(buf, len)
817}
818
819fn check_full_track_name(namespace: &TrackNamespace, track_name: &[u8]) -> Result<(), CodecError> {
820    let total = namespace.field_bytes_len().saturating_add(track_name.len());
821    if total > MAX_FULL_TRACK_NAME_LENGTH {
822        return Err(CodecError::TrackNameTooLong);
823    }
824    Ok(())
825}
826
827/// Refuse a request whose range ends before it starts.
828///
829/// SUBSCRIBE's AbsoluteRange filter (Section 9.7), SUBSCRIBE_UPDATE
830/// (Section 9.10) and FETCH (Section 9.16.3) each state it, and the fields
831/// are not spelled the same way in the three places: an End Group is inclusive
832/// on SUBSCRIBE and FETCH and is the last group plus one on SUBSCRIBE_UPDATE,
833/// where zero means open ended, and an End Object is the last object plus one
834/// with zero meaning the whole group. The helpers this calls carry those
835/// conventions, one per shape.
836///
837/// Applied on both sides. A range that ends before it starts selects nothing,
838/// and the peer's only recourse is an error response or a session close, so
839/// writing one is not a way to ask for anything.
840fn check_ranges(message: &ControlMessage) -> Result<(), CodecError> {
841    match message {
842        ControlMessage::Subscribe(m) => match (&m.start_location, &m.end_group) {
843            (Some(start), Some(end_group)) => {
844                check_group_range(start.group.into_inner(), end_group.into_inner())
845            }
846            _ => Ok(()),
847        },
848        ControlMessage::SubscribeUpdate(m) => check_open_ended_group_range(
849            m.start_location.group.into_inner(),
850            m.end_group.into_inner(),
851        ),
852        ControlMessage::Fetch(m) => match &m.fetch_payload {
853            FetchPayload::Standalone {
854                start_group, start_object, end_group, end_object, ..
855            } => check_location_range(
856                start_group.into_inner(),
857                start_object.into_inner(),
858                end_group.into_inner(),
859                end_object.into_inner(),
860            ),
861            FetchPayload::Joining { .. } => Ok(()),
862        },
863        _ => Ok(()),
864    }
865}
866
867/// The one parameter type whose own definition lets it repeat.
868///
869/// Section 9.2.1.1: "The AUTHORIZATION TOKEN parameter MAY be repeated within a
870/// message." That is the "unless the parameter definition explicitly allows
871/// multiple instances" carve-out of Section 9.2, and on this draft it is the
872/// only one — the other two version-specific parameters and all five setup
873/// parameters say nothing of the kind.
874///
875/// The same code point, 0x03, in both namespaces: Section 9.2.1.1 assigns it to
876/// the message parameter and Section 9.3.2.5 defines the setup parameter as
877/// "See Section 9.2.1.1", so a sender may repeat it in a SETUP as well.
878const REPEATABLE_PARAMETER: u64 = 0x03;
879
880/// Every version-specific parameter type draft-14 names, from Section 9.2.1.
881///
882/// AUTHORIZATION TOKEN (0x03, Section 9.2.1.1), DELIVERY TIMEOUT (0x02, Section
883/// 9.2.1.2) and MAX_CACHE_DURATION (0x04, Section 9.2.1.3). Draft-14 publishes
884/// no IANA table for these, so the sections are the registry.
885///
886/// The list exists for one rule and one direction. Section 9.2: "Receivers MUST
887/// allow duplicates of unknown parameters." A receiver may therefore refuse a
888/// repeat only of a type it can name, and a type outside this list belongs to an
889/// extension this codec has no business closing a session over. Nothing else
890/// reads it — an unknown parameter is still decoded and carried.
891const KNOWN_VERSION_SPECIFIC_PARAMETERS: &[u64] = &[0x02, 0x03, 0x04];
892
893/// Every setup parameter type draft-14 names, from Section 9.3.2.
894///
895/// PATH (0x01), MAX_REQUEST_ID (0x02), AUTHORIZATION TOKEN (0x03),
896/// MAX_AUTH_TOKEN_CACHE_SIZE (0x04) and AUTHORITY (0x05). Section 9.3.2.6 gives
897/// MOQT_IMPLEMENTATION the code point 0x05 as well, colliding with AUTHORITY in
898/// Section 9.3.2.1; draft-15 moves it to 0x07. The collision does not change the
899/// set of code points the draft names, which is all this list is for.
900///
901/// Setup parameters are a separate namespace — Section 9.2.1 says so outright:
902/// "since Setup parameters use a separate namespace, it is impossible for these
903/// parameters to appear in Setup messages" — so a receiver deciding whether it
904/// can name a type has to know which of the two lists to consult.
905const KNOWN_SETUP_PARAMETERS: &[u64] = &[0x01, 0x02, 0x03, 0x04, 0x05];
906
907/// Refuse a parameter list a sender may not put on the wire.
908///
909/// Section 9.2: "Senders MUST NOT repeat the same parameter type in a message
910/// unless the parameter definition explicitly allows multiple instances of that
911/// type to be sent in a single message."
912///
913/// The sender's half names no exception for types the sender does not
914/// recognise, so every repeat is refused here except
915/// [`REPEATABLE_PARAMETER`]. A caller holding a parameter this codec has never
916/// heard of still may not send it twice: it knows the type it is sending, and
917/// the rule is about that knowledge, not this codec's.
918fn check_no_duplicate_parameters_sent(parameters: &[KeyValuePair]) -> Result<(), CodecError> {
919    for (i, parameter) in parameters.iter().enumerate() {
920        let key = parameter.key.into_inner();
921        if key == REPEATABLE_PARAMETER {
922            continue;
923        }
924        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
925            return Err(CodecError::DuplicateParameter(key));
926        }
927    }
928    Ok(())
929}
930
931/// Refuse a received parameter list that repeats a type this draft names.
932///
933/// The receiver's half of the same sentence is narrower, and deliberately so.
934/// Section 9.2: "Receivers SHOULD check that there are no unauthorized duplicate
935/// parameters and close the session as a PROTOCOL_VIOLATION if found. Receivers
936/// MUST allow duplicates of unknown parameters."
937///
938/// So a repeat of a type in `known` is refused, and a repeat of any other type
939/// is carried. Mirroring the sender's check here instead would close sessions
940/// over frames a conforming peer is entitled to send — an extension parameter
941/// this codec does not know may legitimately repeat, and its own definition, not
942/// this one, says whether it may.
943///
944/// Code that scans a parameter list for a key takes whichever copy it meets
945/// first, so one frame carrying two values for one named type is read
946/// differently by two conforming implementations. That is what the refusal is
947/// for, and it is also why it stops at the types whose meaning is fixed here.
948fn check_no_duplicate_parameters_received(
949    parameters: &[KeyValuePair],
950    known: &[u64],
951) -> Result<(), CodecError> {
952    for (i, parameter) in parameters.iter().enumerate() {
953        let key = parameter.key.into_inner();
954        if key == REPEATABLE_PARAMETER || !known.contains(&key) {
955            continue;
956        }
957        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
958            return Err(CodecError::DuplicateParameter(key));
959        }
960    }
961    Ok(())
962}
963
964/// Hold every AUTHORIZATION TOKEN parameter to the Token structure it names.
965///
966/// Section 9.2.1.1: "If the Token structure cannot be decoded, the receiver
967/// MUST close the Session with Key-Value Formatting error." That is the answer
968/// Section 1.4.2 gives for any Type whose value does not match the
969/// serialization that Type defines; the Token is the one structure this draft
970/// spells out, and the only parameter value in it that is more than opaque
971/// bytes.
972///
973/// Both namespaces carry the type on this draft, and both reach here.
974///
975/// A type this draft cannot name is left alone. The rule is conditional on the
976/// receiver understanding the Type, and an extension's parameter carries bytes
977/// no rule here describes.
978fn check_authorization_tokens(parameters: &[KeyValuePair]) -> Result<(), CodecError> {
979    for parameter in parameters {
980        let key = parameter.key.into_inner();
981        if key != AUTH_TOKEN_PARAMETER {
982            continue;
983        }
984        match &parameter.value {
985            KvpValue::Bytes(value) => {
986                AuthorizationToken::decode(key, value)?;
987            }
988            // Unreachable from the decoder, which picks the shape from the
989            // type and finds this one length-prefixed. A caller that built the
990            // pair in memory can still get here, and it is the same rule: the
991            // value is not the serialization the type defines.
992            KvpValue::Varint(_) => {
993                return Err(CodecError::KeyValueFormatting {
994                    key,
995                    detail: "its value is a bare varint where the type defines a Token structure",
996                });
997            }
998        }
999    }
1000    Ok(())
1001}
1002
1003/// Decode a version-specific parameter list, refusing a repeated known type.
1004fn decode_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
1005    let parameters = KeyValuePair::decode_list(buf)?;
1006    check_no_duplicate_parameters_received(&parameters, KNOWN_VERSION_SPECIFIC_PARAMETERS)?;
1007    check_authorization_tokens(&parameters)?;
1008    Ok(parameters)
1009}
1010
1011/// Decode a SETUP message's parameter list, refusing a repeated known type.
1012///
1013/// Separate from [`decode_parameters`] only in which list of names it consults;
1014/// see [`KNOWN_SETUP_PARAMETERS`] for why the two cannot share one.
1015fn decode_setup_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
1016    let parameters = KeyValuePair::decode_list(buf)?;
1017    check_no_duplicate_parameters_received(&parameters, KNOWN_SETUP_PARAMETERS)?;
1018    check_authorization_tokens(&parameters)?;
1019    Ok(parameters)
1020}
1021
1022/// Encode a parameter list, refusing every repeat the sender's rule forbids and
1023/// every token that is not one.
1024///
1025/// One function for both namespaces, unlike the decode side: the sender's rule
1026/// exempts a parameter type rather than a namespace, and the exempt type has the
1027/// same code point in each. The token rule is the same in both namespaces too,
1028/// so the two decode functions that state it agree with the one here.
1029///
1030/// A token that cannot be decoded is one the receiver must close the session
1031/// over, so writing it is not a way to send it — the sender's first sign of
1032/// trouble would be the session going.
1033fn encode_parameters(parameters: &[KeyValuePair], buf: &mut impl BufMut) -> Result<(), CodecError> {
1034    check_no_duplicate_parameters_sent(parameters)?;
1035    check_authorization_tokens(parameters)?;
1036    KeyValuePair::encode_list_checked(parameters, buf)?;
1037    Ok(())
1038}
1039
1040impl ControlMessage {
1041    /// Encode this control message to bytes (including type ID and length prefix).
1042    ///
1043    /// Draft-14 framing: type_id(vi) + payload_length(16) + payload.
1044    pub fn encode(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
1045        check_discriminators(self)?;
1046        check_group_order(self)?;
1047        check_ranges(self)?;
1048        let mut payload = Vec::with_capacity(256);
1049        self.encode_payload(&mut payload)?;
1050
1051        if payload.len() > MAX_MESSAGE_LENGTH {
1052            return Err(CodecError::MessageTooLong(payload.len()));
1053        }
1054
1055        VarInt::from_usize(self.message_type().id() as usize).encode(buf);
1056        // Draft-14: 16-bit length (big-endian)
1057        buf.put_u16(payload.len() as u16);
1058        buf.put_slice(&payload);
1059        Ok(())
1060    }
1061
1062    /// Decode a control message from bytes (reads type ID and length prefix first).
1063    ///
1064    /// Draft-14 framing: type_id(vi) + payload_length(16) + payload.
1065    pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError> {
1066        let type_id = VarInt::decode(buf)?.into_inner();
1067        let msg_type =
1068            MessageType::from_id(type_id).ok_or(CodecError::UnknownMessageType(type_id))?;
1069        // Draft-14: 16-bit length (big-endian)
1070        if buf.remaining() < 2 {
1071            return Err(CodecError::UnexpectedEnd);
1072        }
1073        let payload_len = buf.get_u16() as usize;
1074        if buf.remaining() < payload_len {
1075            return Err(CodecError::UnexpectedEnd);
1076        }
1077        let payload_bytes = buf.copy_to_bytes(payload_len);
1078        let mut payload = &payload_bytes[..];
1079        let msg = match Self::decode_payload(msg_type, &mut payload) {
1080            Ok(msg) => msg,
1081            // The fields wanted more bytes than the Length allowed. This buffer
1082            // is already bounded by that Length, so running out inside it cannot
1083            // mean the message is still arriving - which is what the same error
1084            // means everywhere else, and why a reader loops on it rather than
1085            // closing. Here there is nothing left to arrive.
1086            Err(
1087                CodecError::UnexpectedEnd
1088                | CodecError::Kvp(crate::kvp::KvpError::UnexpectedEnd)
1089                | CodecError::Kvp(crate::kvp::KvpError::VarInt(
1090                    crate::varint::VarIntError::UnexpectedEnd,
1091                ))
1092                | CodecError::VarInt(crate::varint::VarIntError::UnexpectedEnd),
1093            ) => {
1094                return Err(CodecError::ControlMessageLengthMismatch {
1095                    declared: payload_len,
1096                    detail: "its fields ran past the end",
1097                });
1098            }
1099            Err(e) => return Err(e),
1100        };
1101        check_ranges(&msg)?;
1102        // The declared length is part of the message, not a hint. Bytes left over
1103        // after the fields have been read mean the sender and this reader disagree
1104        // about the shape of the message, and guessing which of the two is right
1105        // is how a trailing field gets silently dropped.
1106        if payload.has_remaining() {
1107            return Err(CodecError::ControlMessageLengthMismatch {
1108                declared: payload_len,
1109                detail: "its fields left bytes unread",
1110            });
1111        }
1112        Ok(msg)
1113    }
1114
1115    fn encode_payload(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
1116        match self {
1117            ControlMessage::ClientSetup(m) => {
1118                VarInt::from_usize(m.supported_versions.len()).encode(buf);
1119                for v in &m.supported_versions {
1120                    v.encode(buf);
1121                }
1122                encode_parameters(&m.parameters, buf)?;
1123            }
1124            ControlMessage::ServerSetup(m) => {
1125                m.selected_version.encode(buf);
1126                encode_parameters(&m.parameters, buf)?;
1127            }
1128            ControlMessage::GoAway(m) => {
1129                if m.new_session_uri.len() > MAX_GOAWAY_URI_LENGTH {
1130                    return Err(CodecError::GoAwayUriTooLong);
1131                }
1132                VarInt::from_usize(m.new_session_uri.len()).encode(buf);
1133                buf.put_slice(&m.new_session_uri);
1134            }
1135            ControlMessage::MaxRequestId(m) => {
1136                m.request_id.encode(buf);
1137            }
1138            ControlMessage::RequestsBlocked(m) => {
1139                m.maximum_request_id.encode(buf);
1140            }
1141            ControlMessage::Subscribe(m) => {
1142                check_full_track_name(&m.track_namespace, &m.track_name)?;
1143                m.request_id.encode(buf);
1144                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1145                m.track_namespace.encode(buf);
1146                VarInt::from_usize(m.track_name.len()).encode(buf);
1147                buf.put_slice(&m.track_name);
1148                buf.put_u8(m.subscriber_priority);
1149                buf.put_u8(m.group_order as u8);
1150                buf.put_u8(m.forward as u8);
1151                VarInt::from_u64(m.filter_type as u64).unwrap().encode(buf);
1152                if let Some(loc) = &m.start_location {
1153                    loc.encode(buf);
1154                }
1155                if let Some(eg) = &m.end_group {
1156                    eg.encode(buf);
1157                }
1158                encode_parameters(&m.parameters, buf)?;
1159            }
1160            ControlMessage::SubscribeOk(m) => {
1161                m.request_id.encode(buf);
1162                m.track_alias.encode(buf);
1163                m.expires.encode(buf);
1164                buf.put_u8(m.group_order as u8);
1165                buf.put_u8(m.content_exists as u8);
1166                if let Some(loc) = &m.largest_location {
1167                    loc.encode(buf);
1168                }
1169                encode_parameters(&m.parameters, buf)?;
1170            }
1171            ControlMessage::SubscribeError(m) => {
1172                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1173                    return Err(CodecError::ReasonPhraseTooLong);
1174                }
1175                m.request_id.encode(buf);
1176                m.error_code.encode(buf);
1177                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1178                buf.put_slice(&m.reason_phrase);
1179            }
1180            ControlMessage::SubscribeUpdate(m) => {
1181                m.request_id.encode(buf);
1182                m.subscription_request_id.encode(buf);
1183                m.start_location.encode(buf);
1184                m.end_group.encode(buf);
1185                buf.put_u8(m.subscriber_priority);
1186                buf.put_u8(m.forward as u8);
1187                encode_parameters(&m.parameters, buf)?;
1188            }
1189            ControlMessage::Unsubscribe(m) => {
1190                m.request_id.encode(buf);
1191            }
1192            ControlMessage::Publish(m) => {
1193                check_full_track_name(&m.track_namespace, &m.track_name)?;
1194                m.request_id.encode(buf);
1195                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1196                m.track_namespace.encode(buf);
1197                VarInt::from_usize(m.track_name.len()).encode(buf);
1198                buf.put_slice(&m.track_name);
1199                m.track_alias.encode(buf);
1200                buf.put_u8(m.group_order as u8);
1201                buf.put_u8(m.content_exists as u8);
1202                if let Some(loc) = &m.largest_location {
1203                    loc.encode(buf);
1204                }
1205                buf.put_u8(m.forward as u8);
1206                encode_parameters(&m.parameters, buf)?;
1207            }
1208            ControlMessage::PublishOk(m) => {
1209                m.request_id.encode(buf);
1210                buf.put_u8(m.forward as u8);
1211                buf.put_u8(m.subscriber_priority);
1212                buf.put_u8(m.group_order as u8);
1213                VarInt::from_u64(m.filter_type as u64).unwrap().encode(buf);
1214                if let Some(loc) = &m.start_location {
1215                    loc.encode(buf);
1216                }
1217                if let Some(eg) = &m.end_group {
1218                    eg.encode(buf);
1219                }
1220                encode_parameters(&m.parameters, buf)?;
1221            }
1222            ControlMessage::PublishError(m) => {
1223                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1224                    return Err(CodecError::ReasonPhraseTooLong);
1225                }
1226                m.request_id.encode(buf);
1227                m.error_code.encode(buf);
1228                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1229                buf.put_slice(&m.reason_phrase);
1230            }
1231            ControlMessage::PublishDone(m) => {
1232                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1233                    return Err(CodecError::ReasonPhraseTooLong);
1234                }
1235                m.request_id.encode(buf);
1236                m.status_code.encode(buf);
1237                m.stream_count.encode(buf);
1238                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1239                buf.put_slice(&m.reason_phrase);
1240            }
1241            ControlMessage::PublishNamespace(m) => {
1242                m.request_id.encode(buf);
1243                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1244                m.track_namespace.encode(buf);
1245                encode_parameters(&m.parameters, buf)?;
1246            }
1247            ControlMessage::PublishNamespaceOk(m) => {
1248                m.request_id.encode(buf);
1249            }
1250            ControlMessage::PublishNamespaceError(m) => {
1251                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1252                    return Err(CodecError::ReasonPhraseTooLong);
1253                }
1254                m.request_id.encode(buf);
1255                m.error_code.encode(buf);
1256                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1257                buf.put_slice(&m.reason_phrase);
1258            }
1259            ControlMessage::PublishNamespaceDone(m) => {
1260                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1261                m.track_namespace.encode(buf);
1262            }
1263            ControlMessage::PublishNamespaceCancel(m) => {
1264                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1265                    return Err(CodecError::ReasonPhraseTooLong);
1266                }
1267                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1268                m.track_namespace.encode(buf);
1269                m.error_code.encode(buf);
1270                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1271                buf.put_slice(&m.reason_phrase);
1272            }
1273            ControlMessage::SubscribeNamespace(m) => {
1274                m.request_id.encode(buf);
1275                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1276                m.track_namespace.encode(buf);
1277                encode_parameters(&m.parameters, buf)?;
1278            }
1279            ControlMessage::SubscribeNamespaceOk(m) => {
1280                m.request_id.encode(buf);
1281            }
1282            ControlMessage::SubscribeNamespaceError(m) => {
1283                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1284                    return Err(CodecError::ReasonPhraseTooLong);
1285                }
1286                m.request_id.encode(buf);
1287                m.error_code.encode(buf);
1288                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1289                buf.put_slice(&m.reason_phrase);
1290            }
1291            ControlMessage::UnsubscribeNamespace(m) => {
1292                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(14))?;
1293                m.track_namespace_prefix.encode(buf);
1294            }
1295            ControlMessage::Fetch(m) => {
1296                m.request_id.encode(buf);
1297                buf.put_u8(m.subscriber_priority);
1298                buf.put_u8(m.group_order as u8);
1299                VarInt::from_usize(m.fetch_type as usize).encode(buf);
1300                match &m.fetch_payload {
1301                    FetchPayload::Standalone {
1302                        track_namespace,
1303                        track_name,
1304                        start_group,
1305                        start_object,
1306                        end_group,
1307                        end_object,
1308                    } => {
1309                        check_full_track_name(track_namespace, track_name)?;
1310                        track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1311                        track_namespace.encode(buf);
1312                        VarInt::from_usize(track_name.len()).encode(buf);
1313                        buf.put_slice(track_name);
1314                        start_group.encode(buf);
1315                        start_object.encode(buf);
1316                        end_group.encode(buf);
1317                        end_object.encode(buf);
1318                    }
1319                    FetchPayload::Joining { joining_request_id, joining_start } => {
1320                        joining_request_id.encode(buf);
1321                        joining_start.encode(buf);
1322                    }
1323                }
1324                encode_parameters(&m.parameters, buf)?;
1325            }
1326            ControlMessage::FetchOk(m) => {
1327                m.request_id.encode(buf);
1328                buf.put_u8(m.group_order as u8);
1329                buf.put_u8(m.end_of_track);
1330                m.end_location.encode(buf);
1331                encode_parameters(&m.parameters, buf)?;
1332            }
1333            ControlMessage::FetchError(m) => {
1334                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1335                    return Err(CodecError::ReasonPhraseTooLong);
1336                }
1337                m.request_id.encode(buf);
1338                m.error_code.encode(buf);
1339                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1340                buf.put_slice(&m.reason_phrase);
1341            }
1342            ControlMessage::FetchCancel(m) => {
1343                m.request_id.encode(buf);
1344            }
1345            ControlMessage::TrackStatus(m) => {
1346                check_full_track_name(&m.track_namespace, &m.track_name)?;
1347                m.request_id.encode(buf);
1348                m.track_namespace.validate(TrackNamespaceRules::for_draft(14))?;
1349                m.track_namespace.encode(buf);
1350                VarInt::from_usize(m.track_name.len()).encode(buf);
1351                buf.put_slice(&m.track_name);
1352                buf.put_u8(m.subscriber_priority);
1353                buf.put_u8(m.group_order as u8);
1354                buf.put_u8(m.forward as u8);
1355                VarInt::from_u64(m.filter_type as u64).unwrap().encode(buf);
1356                if let Some(loc) = &m.start_location {
1357                    loc.encode(buf);
1358                }
1359                if let Some(eg) = &m.end_group {
1360                    eg.encode(buf);
1361                }
1362                encode_parameters(&m.parameters, buf)?;
1363            }
1364            ControlMessage::TrackStatusOk(m) => {
1365                m.request_id.encode(buf);
1366                m.track_alias.encode(buf);
1367                m.expires.encode(buf);
1368                buf.put_u8(m.group_order as u8);
1369                buf.put_u8(m.content_exists as u8);
1370                if let Some(loc) = &m.largest_location {
1371                    loc.encode(buf);
1372                }
1373                encode_parameters(&m.parameters, buf)?;
1374            }
1375            ControlMessage::TrackStatusError(m) => {
1376                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1377                    return Err(CodecError::ReasonPhraseTooLong);
1378                }
1379                m.request_id.encode(buf);
1380                m.error_code.encode(buf);
1381                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1382                buf.put_slice(&m.reason_phrase);
1383            }
1384        }
1385        Ok(())
1386    }
1387
1388    fn decode_payload(msg_type: MessageType, buf: &mut impl Buf) -> Result<Self, CodecError> {
1389        match msg_type {
1390            MessageType::ClientSetup => {
1391                let num_versions = VarInt::decode(buf)?.into_inner() as usize;
1392                // Not a rule this draft states. It says only that the server
1393                // "MUST reply with one of the versions offered by the client"
1394                // and that a peer with no version in common "MUST close the
1395                // session" - outcomes of negotiation rather than parse errors,
1396                // and a CLIENT_SETUP offering nothing decodes cleanly under the
1397                // figure. It is refused here because there is no version a
1398                // reply could name, so the session is already over and the
1399                // early close is the more useful answer than a well-formed
1400                // message no caller can act on.
1401                if num_versions == 0 {
1402                    return Err(CodecError::InvalidField);
1403                }
1404                let mut supported_versions = crate::types::reserve_bounded(num_versions, buf);
1405                for _ in 0..num_versions {
1406                    supported_versions.push(VarInt::decode(buf)?);
1407                }
1408                let parameters = decode_setup_parameters(buf)?;
1409                Ok(ControlMessage::ClientSetup(ClientSetup { supported_versions, parameters }))
1410            }
1411            MessageType::ServerSetup => {
1412                let selected_version = VarInt::decode(buf)?;
1413                let parameters = decode_setup_parameters(buf)?;
1414                Ok(ControlMessage::ServerSetup(ServerSetup { selected_version, parameters }))
1415            }
1416            MessageType::GoAway => {
1417                let uri_len = VarInt::decode(buf)?.into_inner() as usize;
1418                // Section 9.4: "The maxmimum length of the New Session URI is
1419                // 8,192 bytes. If an endpoint receives a length exceeding the
1420                // maximum, it MUST close the session with a
1421                // PROTOCOL_VIOLATION." Stated for the receiver, and checked
1422                // before the bytes are read.
1423                if uri_len > MAX_GOAWAY_URI_LENGTH {
1424                    return Err(CodecError::GoAwayUriTooLong);
1425                }
1426                let uri = read_bytes(buf, uri_len)?;
1427                Ok(ControlMessage::GoAway(GoAway { new_session_uri: uri }))
1428            }
1429            MessageType::MaxRequestId => {
1430                let request_id = VarInt::decode(buf)?;
1431                Ok(ControlMessage::MaxRequestId(MaxRequestId { request_id }))
1432            }
1433            MessageType::RequestsBlocked => {
1434                let maximum_request_id = VarInt::decode(buf)?;
1435                Ok(ControlMessage::RequestsBlocked(RequestsBlocked { maximum_request_id }))
1436            }
1437            MessageType::Subscribe => {
1438                let request_id = VarInt::decode(buf)?;
1439                let track_namespace = TrackNamespace::decode(buf)?;
1440                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1441                let track_name = read_bytes(buf, track_name_len)?;
1442                check_full_track_name(&track_namespace, &track_name)?;
1443                if buf.remaining() < 3 {
1444                    return Err(CodecError::UnexpectedEnd);
1445                }
1446                let subscriber_priority = buf.get_u8();
1447                let group_order =
1448                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1449                let forward_val = buf.get_u8();
1450                let forward = match forward_val {
1451                    0 => Forward::DontForward,
1452                    1 => Forward::Forward,
1453                    other => return Err(CodecError::InvalidForward(other)),
1454                };
1455                // Filter Type is (i) in every figure that carries it, not a
1456                // fixed byte: the values 1 through 4 happen to share their
1457                // one-byte varint encoding with a bare byte, so the two
1458                // readings agree on everything legal and diverge only on the
1459                // longer encodings of the same values that a peer may send.
1460                let filter_val = VarInt::decode(buf)?.into_inner();
1461                let filter_type = FilterType::from_u64(filter_val)
1462                    .ok_or(CodecError::InvalidFilterType(filter_val))?;
1463                let start_location = match filter_type {
1464                    FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
1465                        Some(Location::decode(buf)?)
1466                    }
1467                    _ => None,
1468                };
1469                let end_group = match filter_type {
1470                    FilterType::AbsoluteRange => Some(VarInt::decode(buf)?),
1471                    _ => None,
1472                };
1473                let parameters = decode_parameters(buf)?;
1474                Ok(ControlMessage::Subscribe(Subscribe {
1475                    request_id,
1476                    track_namespace,
1477                    track_name,
1478                    subscriber_priority,
1479                    group_order,
1480                    forward,
1481                    filter_type,
1482                    start_location,
1483                    end_group,
1484                    parameters,
1485                }))
1486            }
1487            MessageType::SubscribeOk => {
1488                let request_id = VarInt::decode(buf)?;
1489                let track_alias = VarInt::decode(buf)?;
1490                let expires = VarInt::decode(buf)?;
1491                if buf.remaining() < 2 {
1492                    return Err(CodecError::UnexpectedEnd);
1493                }
1494                let group_order = read_group_order_response(buf)?;
1495                let content_exists_val = buf.get_u8();
1496                let content_exists = match content_exists_val {
1497                    0 => ContentExists::NoLargestLocation,
1498                    1 => ContentExists::HasLargestLocation,
1499                    other => return Err(CodecError::InvalidContentExists(other)),
1500                };
1501                let largest_location = if content_exists == ContentExists::HasLargestLocation {
1502                    Some(Location::decode(buf)?)
1503                } else {
1504                    None
1505                };
1506                let parameters = decode_parameters(buf)?;
1507                Ok(ControlMessage::SubscribeOk(SubscribeOk {
1508                    request_id,
1509                    track_alias,
1510                    expires,
1511                    group_order,
1512                    content_exists,
1513                    largest_location,
1514                    parameters,
1515                }))
1516            }
1517            MessageType::SubscribeError => {
1518                let request_id = VarInt::decode(buf)?;
1519                let error_code = VarInt::decode(buf)?;
1520                let reason_phrase = read_reason_phrase(buf)?;
1521                Ok(ControlMessage::SubscribeError(SubscribeError {
1522                    request_id,
1523                    error_code,
1524                    reason_phrase,
1525                }))
1526            }
1527            MessageType::SubscribeUpdate => {
1528                let request_id = VarInt::decode(buf)?;
1529                let subscription_request_id = VarInt::decode(buf)?;
1530                let start_location = Location::decode(buf)?;
1531                let end_group = VarInt::decode(buf)?;
1532                if buf.remaining() < 2 {
1533                    return Err(CodecError::UnexpectedEnd);
1534                }
1535                let subscriber_priority = buf.get_u8();
1536                let forward_val = buf.get_u8();
1537                let forward = match forward_val {
1538                    0 => Forward::DontForward,
1539                    1 => Forward::Forward,
1540                    other => return Err(CodecError::InvalidForward(other)),
1541                };
1542                let parameters = decode_parameters(buf)?;
1543                Ok(ControlMessage::SubscribeUpdate(SubscribeUpdate {
1544                    request_id,
1545                    subscription_request_id,
1546                    start_location,
1547                    end_group,
1548                    subscriber_priority,
1549                    forward,
1550                    parameters,
1551                }))
1552            }
1553            MessageType::Unsubscribe => {
1554                let request_id = VarInt::decode(buf)?;
1555                Ok(ControlMessage::Unsubscribe(Unsubscribe { request_id }))
1556            }
1557            MessageType::Publish => {
1558                let request_id = VarInt::decode(buf)?;
1559                let track_namespace = TrackNamespace::decode(buf)?;
1560                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1561                let track_name = read_bytes(buf, track_name_len)?;
1562                check_full_track_name(&track_namespace, &track_name)?;
1563                let track_alias = VarInt::decode(buf)?;
1564                if buf.remaining() < 2 {
1565                    return Err(CodecError::UnexpectedEnd);
1566                }
1567                let group_order = read_group_order_response(buf)?;
1568                let content_exists_val = buf.get_u8();
1569                let content_exists = match content_exists_val {
1570                    0 => ContentExists::NoLargestLocation,
1571                    1 => ContentExists::HasLargestLocation,
1572                    other => return Err(CodecError::InvalidContentExists(other)),
1573                };
1574                let largest_location = if content_exists == ContentExists::HasLargestLocation {
1575                    Some(Location::decode(buf)?)
1576                } else {
1577                    None
1578                };
1579                if buf.remaining() < 1 {
1580                    return Err(CodecError::UnexpectedEnd);
1581                }
1582                let forward_val = buf.get_u8();
1583                let forward = match forward_val {
1584                    0 => Forward::DontForward,
1585                    1 => Forward::Forward,
1586                    other => return Err(CodecError::InvalidForward(other)),
1587                };
1588                let parameters = decode_parameters(buf)?;
1589                Ok(ControlMessage::Publish(Publish {
1590                    request_id,
1591                    track_namespace,
1592                    track_name,
1593                    track_alias,
1594                    group_order,
1595                    content_exists,
1596                    largest_location,
1597                    forward,
1598                    parameters,
1599                }))
1600            }
1601            MessageType::PublishOk => {
1602                let request_id = VarInt::decode(buf)?;
1603                if buf.remaining() < 3 {
1604                    return Err(CodecError::UnexpectedEnd);
1605                }
1606                let forward_val = buf.get_u8();
1607                let forward = match forward_val {
1608                    0 => Forward::DontForward,
1609                    1 => Forward::Forward,
1610                    other => return Err(CodecError::InvalidForward(other)),
1611                };
1612                let subscriber_priority = buf.get_u8();
1613                let group_order = read_group_order_response(buf)?;
1614                let filter_val = VarInt::decode(buf)?.into_inner();
1615                let filter_type = FilterType::from_u64(filter_val)
1616                    .ok_or(CodecError::InvalidFilterType(filter_val))?;
1617                let start_location = match filter_type {
1618                    FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
1619                        Some(Location::decode(buf)?)
1620                    }
1621                    _ => None,
1622                };
1623                let end_group = match filter_type {
1624                    FilterType::AbsoluteRange => Some(VarInt::decode(buf)?),
1625                    _ => None,
1626                };
1627                let parameters = decode_parameters(buf)?;
1628                Ok(ControlMessage::PublishOk(PublishOk {
1629                    request_id,
1630                    forward,
1631                    subscriber_priority,
1632                    group_order,
1633                    filter_type,
1634                    start_location,
1635                    end_group,
1636                    parameters,
1637                }))
1638            }
1639            MessageType::PublishError => {
1640                let request_id = VarInt::decode(buf)?;
1641                let error_code = VarInt::decode(buf)?;
1642                let reason_phrase = read_reason_phrase(buf)?;
1643                Ok(ControlMessage::PublishError(PublishError {
1644                    request_id,
1645                    error_code,
1646                    reason_phrase,
1647                }))
1648            }
1649            MessageType::PublishDone => {
1650                let request_id = VarInt::decode(buf)?;
1651                let status_code = VarInt::decode(buf)?;
1652                let stream_count = VarInt::decode(buf)?;
1653                let reason_phrase = read_reason_phrase(buf)?;
1654                Ok(ControlMessage::PublishDone(PublishDone {
1655                    request_id,
1656                    status_code,
1657                    stream_count,
1658                    reason_phrase,
1659                }))
1660            }
1661            MessageType::PublishNamespace => {
1662                let request_id = VarInt::decode(buf)?;
1663                let track_namespace = TrackNamespace::decode(buf)?;
1664                let parameters = decode_parameters(buf)?;
1665                Ok(ControlMessage::PublishNamespace(PublishNamespace {
1666                    request_id,
1667                    track_namespace,
1668                    parameters,
1669                }))
1670            }
1671            MessageType::PublishNamespaceOk => {
1672                let request_id = VarInt::decode(buf)?;
1673                Ok(ControlMessage::PublishNamespaceOk(PublishNamespaceOk { request_id }))
1674            }
1675            MessageType::PublishNamespaceError => {
1676                let request_id = VarInt::decode(buf)?;
1677                let error_code = VarInt::decode(buf)?;
1678                let reason_phrase = read_reason_phrase(buf)?;
1679                Ok(ControlMessage::PublishNamespaceError(PublishNamespaceError {
1680                    request_id,
1681                    error_code,
1682                    reason_phrase,
1683                }))
1684            }
1685            MessageType::PublishNamespaceDone => {
1686                let track_namespace = TrackNamespace::decode(buf)?;
1687                Ok(ControlMessage::PublishNamespaceDone(PublishNamespaceDone { track_namespace }))
1688            }
1689            MessageType::PublishNamespaceCancel => {
1690                let track_namespace = TrackNamespace::decode(buf)?;
1691                let error_code = VarInt::decode(buf)?;
1692                let reason_phrase = read_reason_phrase(buf)?;
1693                Ok(ControlMessage::PublishNamespaceCancel(PublishNamespaceCancel {
1694                    track_namespace,
1695                    error_code,
1696                    reason_phrase,
1697                }))
1698            }
1699            MessageType::SubscribeNamespace => {
1700                let request_id = VarInt::decode(buf)?;
1701                let track_namespace = TrackNamespace::decode(buf)?;
1702                let parameters = decode_parameters(buf)?;
1703                Ok(ControlMessage::SubscribeNamespace(SubscribeNamespace {
1704                    request_id,
1705                    track_namespace,
1706                    parameters,
1707                }))
1708            }
1709            MessageType::SubscribeNamespaceOk => {
1710                let request_id = VarInt::decode(buf)?;
1711                Ok(ControlMessage::SubscribeNamespaceOk(SubscribeNamespaceOk { request_id }))
1712            }
1713            MessageType::SubscribeNamespaceError => {
1714                let request_id = VarInt::decode(buf)?;
1715                let error_code = VarInt::decode(buf)?;
1716                let reason_phrase = read_reason_phrase(buf)?;
1717                Ok(ControlMessage::SubscribeNamespaceError(SubscribeNamespaceError {
1718                    request_id,
1719                    error_code,
1720                    reason_phrase,
1721                }))
1722            }
1723            MessageType::UnsubscribeNamespace => {
1724                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1725                Ok(ControlMessage::UnsubscribeNamespace(UnsubscribeNamespace {
1726                    track_namespace_prefix,
1727                }))
1728            }
1729            MessageType::Fetch => {
1730                let request_id = VarInt::decode(buf)?;
1731                if buf.remaining() < 2 {
1732                    return Err(CodecError::UnexpectedEnd);
1733                }
1734                let subscriber_priority = buf.get_u8();
1735                let group_order =
1736                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1737                let fetch_type_val = VarInt::decode(buf)?.into_inner();
1738                let fetch_type = FetchType::from_u64(fetch_type_val)
1739                    .ok_or(CodecError::InvalidFetchType(fetch_type_val))?;
1740                let fetch_payload = match fetch_type {
1741                    FetchType::Standalone => {
1742                        let track_namespace = TrackNamespace::decode(buf)?;
1743                        let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1744                        let track_name = read_bytes(buf, track_name_len)?;
1745                        check_full_track_name(&track_namespace, &track_name)?;
1746                        let start_group = VarInt::decode(buf)?;
1747                        let start_object = VarInt::decode(buf)?;
1748                        let end_group = VarInt::decode(buf)?;
1749                        let end_object = VarInt::decode(buf)?;
1750                        FetchPayload::Standalone {
1751                            track_namespace,
1752                            track_name,
1753                            start_group,
1754                            start_object,
1755                            end_group,
1756                            end_object,
1757                        }
1758                    }
1759                    FetchType::RelativeJoining | FetchType::AbsoluteJoining => {
1760                        let joining_request_id = VarInt::decode(buf)?;
1761                        let joining_start = VarInt::decode(buf)?;
1762                        FetchPayload::Joining { joining_request_id, joining_start }
1763                    }
1764                };
1765                let parameters = decode_parameters(buf)?;
1766                Ok(ControlMessage::Fetch(Fetch {
1767                    request_id,
1768                    subscriber_priority,
1769                    group_order,
1770                    fetch_type,
1771                    fetch_payload,
1772                    parameters,
1773                }))
1774            }
1775            MessageType::FetchOk => {
1776                let request_id = VarInt::decode(buf)?;
1777                if buf.remaining() < 2 {
1778                    return Err(CodecError::UnexpectedEnd);
1779                }
1780                let group_order = read_group_order_response(buf)?;
1781                // End Of Track is (8) in Figure 39, not a varint. The two agree
1782                // on the flag's only two values, so this is the shape of the
1783                // field rather than the values it carries.
1784                let end_of_track = buf.get_u8();
1785                let end_location = Location::decode(buf)?;
1786                let parameters = decode_parameters(buf)?;
1787                Ok(ControlMessage::FetchOk(FetchOk {
1788                    request_id,
1789                    group_order,
1790                    end_of_track,
1791                    end_location,
1792                    parameters,
1793                }))
1794            }
1795            MessageType::FetchError => {
1796                let request_id = VarInt::decode(buf)?;
1797                let error_code = VarInt::decode(buf)?;
1798                let reason_phrase = read_reason_phrase(buf)?;
1799                Ok(ControlMessage::FetchError(FetchError { request_id, error_code, reason_phrase }))
1800            }
1801            MessageType::FetchCancel => {
1802                let request_id = VarInt::decode(buf)?;
1803                Ok(ControlMessage::FetchCancel(FetchCancel { request_id }))
1804            }
1805            MessageType::TrackStatus => {
1806                let request_id = VarInt::decode(buf)?;
1807                let track_namespace = TrackNamespace::decode(buf)?;
1808                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1809                let track_name = read_bytes(buf, track_name_len)?;
1810                check_full_track_name(&track_namespace, &track_name)?;
1811                if buf.remaining() < 3 {
1812                    return Err(CodecError::UnexpectedEnd);
1813                }
1814                let subscriber_priority = buf.get_u8();
1815                let group_order =
1816                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1817                let forward_val = buf.get_u8();
1818                let forward = match forward_val {
1819                    0 => Forward::DontForward,
1820                    1 => Forward::Forward,
1821                    other => return Err(CodecError::InvalidForward(other)),
1822                };
1823                // Filter Type is (i) in every figure that carries it, not a
1824                // fixed byte: the values 1 through 4 happen to share their
1825                // one-byte varint encoding with a bare byte, so the two
1826                // readings agree on everything legal and diverge only on the
1827                // longer encodings of the same values that a peer may send.
1828                let filter_val = VarInt::decode(buf)?.into_inner();
1829                let filter_type = FilterType::from_u64(filter_val)
1830                    .ok_or(CodecError::InvalidFilterType(filter_val))?;
1831                let start_location = match filter_type {
1832                    FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
1833                        Some(Location::decode(buf)?)
1834                    }
1835                    _ => None,
1836                };
1837                let end_group = match filter_type {
1838                    FilterType::AbsoluteRange => Some(VarInt::decode(buf)?),
1839                    _ => None,
1840                };
1841                let parameters = decode_parameters(buf)?;
1842                Ok(ControlMessage::TrackStatus(TrackStatus {
1843                    request_id,
1844                    track_namespace,
1845                    track_name,
1846                    subscriber_priority,
1847                    group_order,
1848                    forward,
1849                    filter_type,
1850                    start_location,
1851                    end_group,
1852                    parameters,
1853                }))
1854            }
1855            MessageType::TrackStatusOk => {
1856                let request_id = VarInt::decode(buf)?;
1857                let track_alias = VarInt::decode(buf)?;
1858                let expires = VarInt::decode(buf)?;
1859                if buf.remaining() < 2 {
1860                    return Err(CodecError::UnexpectedEnd);
1861                }
1862                let group_order = read_group_order_response(buf)?;
1863                let content_exists_val = buf.get_u8();
1864                let content_exists = match content_exists_val {
1865                    0 => ContentExists::NoLargestLocation,
1866                    1 => ContentExists::HasLargestLocation,
1867                    other => return Err(CodecError::InvalidContentExists(other)),
1868                };
1869                let largest_location = if content_exists == ContentExists::HasLargestLocation {
1870                    Some(Location::decode(buf)?)
1871                } else {
1872                    None
1873                };
1874                let parameters = decode_parameters(buf)?;
1875                Ok(ControlMessage::TrackStatusOk(TrackStatusOk {
1876                    request_id,
1877                    track_alias,
1878                    expires,
1879                    group_order,
1880                    content_exists,
1881                    largest_location,
1882                    parameters,
1883                }))
1884            }
1885            MessageType::TrackStatusError => {
1886                let request_id = VarInt::decode(buf)?;
1887                let error_code = VarInt::decode(buf)?;
1888                let reason_phrase = read_reason_phrase(buf)?;
1889                Ok(ControlMessage::TrackStatusError(TrackStatusError {
1890                    request_id,
1891                    error_code,
1892                    reason_phrase,
1893                }))
1894            }
1895        }
1896    }
1897
1898    /// Get the message type ID for this message.
1899    pub fn message_type(&self) -> MessageType {
1900        match self {
1901            ControlMessage::ClientSetup(_) => MessageType::ClientSetup,
1902            ControlMessage::ServerSetup(_) => MessageType::ServerSetup,
1903            ControlMessage::GoAway(_) => MessageType::GoAway,
1904            ControlMessage::MaxRequestId(_) => MessageType::MaxRequestId,
1905            ControlMessage::RequestsBlocked(_) => MessageType::RequestsBlocked,
1906            ControlMessage::Subscribe(_) => MessageType::Subscribe,
1907            ControlMessage::SubscribeOk(_) => MessageType::SubscribeOk,
1908            ControlMessage::SubscribeError(_) => MessageType::SubscribeError,
1909            ControlMessage::SubscribeUpdate(_) => MessageType::SubscribeUpdate,
1910            ControlMessage::Unsubscribe(_) => MessageType::Unsubscribe,
1911            ControlMessage::Publish(_) => MessageType::Publish,
1912            ControlMessage::PublishOk(_) => MessageType::PublishOk,
1913            ControlMessage::PublishError(_) => MessageType::PublishError,
1914            ControlMessage::PublishDone(_) => MessageType::PublishDone,
1915            ControlMessage::PublishNamespace(_) => MessageType::PublishNamespace,
1916            ControlMessage::PublishNamespaceOk(_) => MessageType::PublishNamespaceOk,
1917            ControlMessage::PublishNamespaceError(_) => MessageType::PublishNamespaceError,
1918            ControlMessage::PublishNamespaceDone(_) => MessageType::PublishNamespaceDone,
1919            ControlMessage::PublishNamespaceCancel(_) => MessageType::PublishNamespaceCancel,
1920            ControlMessage::SubscribeNamespace(_) => MessageType::SubscribeNamespace,
1921            ControlMessage::SubscribeNamespaceOk(_) => MessageType::SubscribeNamespaceOk,
1922            ControlMessage::SubscribeNamespaceError(_) => MessageType::SubscribeNamespaceError,
1923            ControlMessage::UnsubscribeNamespace(_) => MessageType::UnsubscribeNamespace,
1924            ControlMessage::Fetch(_) => MessageType::Fetch,
1925            ControlMessage::FetchOk(_) => MessageType::FetchOk,
1926            ControlMessage::FetchError(_) => MessageType::FetchError,
1927            ControlMessage::FetchCancel(_) => MessageType::FetchCancel,
1928            ControlMessage::TrackStatus(_) => MessageType::TrackStatus,
1929            ControlMessage::TrackStatusOk(_) => MessageType::TrackStatusOk,
1930            ControlMessage::TrackStatusError(_) => MessageType::TrackStatusError,
1931        }
1932    }
1933}