Skip to main content

moqtap_codec/draft08/
message.rs

1//! Draft-08 control message encoding and decoding.
2
3use crate::error::CodecError;
4use crate::kvp::KeyValuePair;
5use crate::types::read_bytes;
6use crate::types::*;
7use crate::types::{check_group_range, check_location_range, check_open_ended_group_range};
8use crate::varint::VarInt;
9use bytes::{Buf, BufMut};
10
11/// Control message type IDs (draft-08).
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(u64)]
14pub enum MessageType {
15    /// SubscribeUpdate (type 0x02).
16    SubscribeUpdate = 0x02,
17    /// Subscribe (type 0x03).
18    Subscribe = 0x03,
19    /// SubscribeOk (type 0x04).
20    SubscribeOk = 0x04,
21    /// SubscribeError (type 0x05).
22    SubscribeError = 0x05,
23    /// Announce (type 0x06).
24    Announce = 0x06,
25    /// AnnounceOk (type 0x07).
26    AnnounceOk = 0x07,
27    /// AnnounceError (type 0x08).
28    AnnounceError = 0x08,
29    /// Unannounce (type 0x09).
30    Unannounce = 0x09,
31    /// Unsubscribe (type 0x0A).
32    Unsubscribe = 0x0A,
33    /// SubscribeDone (type 0x0B).
34    SubscribeDone = 0x0B,
35    /// AnnounceCancel (type 0x0C).
36    AnnounceCancel = 0x0C,
37    /// TrackStatusRequest (type 0x0D).
38    TrackStatusRequest = 0x0D,
39    /// TrackStatus (type 0x0E).
40    TrackStatus = 0x0E,
41    /// GoAway (type 0x10).
42    GoAway = 0x10,
43    /// SubscribeAnnounces (type 0x11).
44    SubscribeAnnounces = 0x11,
45    /// SubscribeAnnouncesOk (type 0x12).
46    SubscribeAnnouncesOk = 0x12,
47    /// SubscribeAnnouncesError (type 0x13).
48    SubscribeAnnouncesError = 0x13,
49    /// UnsubscribeAnnounces (type 0x14).
50    UnsubscribeAnnounces = 0x14,
51    /// MaxSubscribeId (type 0x15).
52    MaxSubscribeId = 0x15,
53    /// Fetch (type 0x16).
54    Fetch = 0x16,
55    /// FetchCancel (type 0x17).
56    FetchCancel = 0x17,
57    /// FetchOk (type 0x18).
58    FetchOk = 0x18,
59    /// FetchError (type 0x19).
60    FetchError = 0x19,
61    /// SubscribesBlocked (type 0x1A).
62    SubscribesBlocked = 0x1A,
63    /// ClientSetup (type 0x40).
64    ClientSetup = 0x40,
65    /// ServerSetup (type 0x41).
66    ServerSetup = 0x41,
67}
68
69impl MessageType {
70    /// Look up a message type by its wire ID.
71    pub fn from_id(id: u64) -> Option<Self> {
72        match id {
73            0x02 => Some(MessageType::SubscribeUpdate),
74            0x03 => Some(MessageType::Subscribe),
75            0x04 => Some(MessageType::SubscribeOk),
76            0x05 => Some(MessageType::SubscribeError),
77            0x06 => Some(MessageType::Announce),
78            0x07 => Some(MessageType::AnnounceOk),
79            0x08 => Some(MessageType::AnnounceError),
80            0x09 => Some(MessageType::Unannounce),
81            0x0A => Some(MessageType::Unsubscribe),
82            0x0B => Some(MessageType::SubscribeDone),
83            0x0C => Some(MessageType::AnnounceCancel),
84            0x0D => Some(MessageType::TrackStatusRequest),
85            0x0E => Some(MessageType::TrackStatus),
86            0x10 => Some(MessageType::GoAway),
87            0x11 => Some(MessageType::SubscribeAnnounces),
88            0x12 => Some(MessageType::SubscribeAnnouncesOk),
89            0x13 => Some(MessageType::SubscribeAnnouncesError),
90            0x14 => Some(MessageType::UnsubscribeAnnounces),
91            0x15 => Some(MessageType::MaxSubscribeId),
92            0x16 => Some(MessageType::Fetch),
93            0x17 => Some(MessageType::FetchCancel),
94            0x18 => Some(MessageType::FetchOk),
95            0x19 => Some(MessageType::FetchError),
96            0x1A => Some(MessageType::SubscribesBlocked),
97            0x40 => Some(MessageType::ClientSetup),
98            0x41 => Some(MessageType::ServerSetup),
99            _ => None,
100        }
101    }
102
103    /// Return the wire ID for this message type.
104    pub fn id(&self) -> u64 {
105        *self as u64
106    }
107
108    /// This type's name in the shared vector corpus: the `message_type` its
109    /// draft's `codec/messages/*.json` files carry, in `snake_case`.
110    pub fn name(&self) -> &'static str {
111        match self {
112            MessageType::SubscribeUpdate => "subscribe_update",
113            MessageType::Subscribe => "subscribe",
114            MessageType::SubscribeOk => "subscribe_ok",
115            MessageType::SubscribeError => "subscribe_error",
116            MessageType::Announce => "announce",
117            MessageType::AnnounceOk => "announce_ok",
118            MessageType::AnnounceError => "announce_error",
119            MessageType::Unannounce => "unannounce",
120            MessageType::Unsubscribe => "unsubscribe",
121            MessageType::SubscribeDone => "subscribe_done",
122            MessageType::AnnounceCancel => "announce_cancel",
123            MessageType::TrackStatusRequest => "track_status_request",
124            MessageType::TrackStatus => "track_status",
125            MessageType::GoAway => "goaway",
126            MessageType::SubscribeAnnounces => "subscribe_announces",
127            MessageType::SubscribeAnnouncesOk => "subscribe_announces_ok",
128            MessageType::SubscribeAnnouncesError => "subscribe_announces_error",
129            MessageType::UnsubscribeAnnounces => "unsubscribe_announces",
130            MessageType::MaxSubscribeId => "max_subscribe_id",
131            MessageType::Fetch => "fetch",
132            MessageType::FetchCancel => "fetch_cancel",
133            MessageType::FetchOk => "fetch_ok",
134            MessageType::FetchError => "fetch_error",
135            MessageType::SubscribesBlocked => "subscribes_blocked",
136            MessageType::ClientSetup => "client_setup",
137            MessageType::ServerSetup => "server_setup",
138        }
139    }
140}
141
142// ============================================================
143// Session Lifecycle Messages
144// ============================================================
145
146/// CLIENT_SETUP message (type 0x40).
147#[derive(Debug, Clone, PartialEq, Eq)]
148pub struct ClientSetup {
149    /// The list of MoQT versions supported by the client.
150    pub supported_versions: Vec<VarInt>,
151    /// Setup parameters sent by the client.
152    pub parameters: Vec<KeyValuePair>,
153}
154
155/// SERVER_SETUP message (type 0x41).
156#[derive(Debug, Clone, PartialEq, Eq)]
157pub struct ServerSetup {
158    /// The MoQT version selected by the server.
159    pub selected_version: VarInt,
160    /// Setup parameters sent by the server.
161    pub parameters: Vec<KeyValuePair>,
162}
163
164/// GOAWAY message (type 0x10).
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct GoAway {
167    /// The URI for the new session the client should connect to.
168    pub new_session_uri: Vec<u8>,
169}
170
171/// MAX_SUBSCRIBE_ID message (type 0x15).
172#[derive(Debug, Clone, PartialEq, Eq)]
173pub struct MaxSubscribeId {
174    /// The maximum subscribe ID the peer is willing to accept.
175    pub subscribe_id: VarInt,
176}
177
178/// SUBSCRIBES_BLOCKED message (type 0x1A).
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct SubscribesBlocked {
181    /// The maximum subscribe ID advertised by the peer.
182    pub maximum_subscribe_id: VarInt,
183}
184
185// ============================================================
186// Subscribe Messages
187// ============================================================
188
189/// SUBSCRIBE message (type 0x03).
190///
191/// Draft-08: filter_type is a VarInt. AbsoluteRange has no end_object.
192#[derive(Debug, Clone, PartialEq, Eq)]
193pub struct Subscribe {
194    /// The subscribe ID for this request.
195    pub subscribe_id: VarInt,
196    /// The track alias assigned by the subscriber.
197    pub track_alias: VarInt,
198    /// The track namespace to subscribe to.
199    pub track_namespace: TrackNamespace,
200    /// The track name within the namespace.
201    pub track_name: Vec<u8>,
202    /// The priority of this subscriber relative to others.
203    pub subscriber_priority: u8,
204    /// The requested group delivery order.
205    pub group_order: GroupOrder,
206    /// The filter type controlling which objects are delivered.
207    pub filter_type: FilterType,
208    /// Present only for AbsoluteStart and AbsoluteRange filter types.
209    pub start_location: Option<Location>,
210    /// Present only for AbsoluteRange filter type (end_group only, no end_object).
211    pub end_group: Option<VarInt>,
212    /// Subscribe parameters.
213    pub parameters: Vec<KeyValuePair>,
214}
215
216/// SUBSCRIBE_OK message (type 0x04).
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct SubscribeOk {
219    /// The subscribe ID this response corresponds to.
220    pub subscribe_id: VarInt,
221    /// The expiration time for this subscription in milliseconds.
222    pub expires: VarInt,
223    /// The group delivery order chosen by the publisher.
224    pub group_order: GroupOrder,
225    /// Whether the largest location is included.
226    pub content_exists: ContentExists,
227    /// Present only when content_exists == HasLargestLocation.
228    pub largest_group_id: Option<VarInt>,
229    /// Present only when content_exists == HasLargestLocation.
230    pub largest_object_id: Option<VarInt>,
231    /// Subscribe OK parameters.
232    pub parameters: Vec<KeyValuePair>,
233}
234
235/// SUBSCRIBE_ERROR message (type 0x05).
236#[derive(Debug, Clone, PartialEq, Eq)]
237pub struct SubscribeError {
238    /// The subscribe ID this error corresponds to.
239    pub subscribe_id: VarInt,
240    /// The error code indicating the reason for failure.
241    pub error_code: VarInt,
242    /// A human-readable reason for the error.
243    pub reason_phrase: Vec<u8>,
244    /// The track alias from the original subscribe request.
245    pub track_alias: VarInt,
246}
247
248/// SUBSCRIBE_UPDATE message (type 0x02).
249///
250/// Draft-08: no end_object field (only end_group).
251#[derive(Debug, Clone, PartialEq, Eq)]
252pub struct SubscribeUpdate {
253    /// The subscribe ID to update.
254    pub subscribe_id: VarInt,
255    /// The new start group.
256    pub start_group: VarInt,
257    /// The new start object.
258    pub start_object: VarInt,
259    /// The new end group.
260    pub end_group: VarInt,
261    /// The updated subscriber priority.
262    pub subscriber_priority: u8,
263    /// Updated subscribe parameters.
264    pub parameters: Vec<KeyValuePair>,
265}
266
267/// SUBSCRIBE_DONE message (type 0x0B).
268///
269/// Draft-08: has stream_count instead of content_exists/final_group/final_object.
270#[derive(Debug, Clone, PartialEq, Eq)]
271pub struct SubscribeDone {
272    /// The subscribe ID this message refers to.
273    pub subscribe_id: VarInt,
274    /// The status code for the subscription completion.
275    pub status_code: VarInt,
276    /// Number of streams delivered.
277    pub stream_count: VarInt,
278    /// A human-readable reason phrase.
279    pub reason_phrase: Vec<u8>,
280}
281
282/// UNSUBSCRIBE message (type 0x0A).
283#[derive(Debug, Clone, PartialEq, Eq)]
284pub struct Unsubscribe {
285    /// The subscribe ID to unsubscribe from.
286    pub subscribe_id: VarInt,
287}
288
289// ============================================================
290// Announce Messages
291// ============================================================
292
293/// ANNOUNCE message (type 0x06).
294#[derive(Debug, Clone, PartialEq, Eq)]
295pub struct Announce {
296    /// The track namespace being announced.
297    pub track_namespace: TrackNamespace,
298    /// Announce parameters.
299    pub parameters: Vec<KeyValuePair>,
300}
301
302/// ANNOUNCE_OK message (type 0x07).
303#[derive(Debug, Clone, PartialEq, Eq)]
304pub struct AnnounceOk {
305    /// The track namespace that was accepted.
306    pub track_namespace: TrackNamespace,
307}
308
309/// ANNOUNCE_ERROR message (type 0x08).
310#[derive(Debug, Clone, PartialEq, Eq)]
311pub struct AnnounceError {
312    /// The track namespace that was rejected.
313    pub track_namespace: TrackNamespace,
314    /// The error code indicating the reason for failure.
315    pub error_code: VarInt,
316    /// A human-readable reason for the error.
317    pub reason_phrase: Vec<u8>,
318}
319
320/// ANNOUNCE_CANCEL message (type 0x0C).
321#[derive(Debug, Clone, PartialEq, Eq)]
322pub struct AnnounceCancel {
323    /// The track namespace being cancelled.
324    pub track_namespace: TrackNamespace,
325    /// The error code indicating the reason for cancellation.
326    pub error_code: VarInt,
327    /// A human-readable reason for the cancellation.
328    pub reason_phrase: Vec<u8>,
329}
330
331/// UNANNOUNCE message (type 0x09).
332#[derive(Debug, Clone, PartialEq, Eq)]
333pub struct Unannounce {
334    /// The track namespace being unannounced.
335    pub track_namespace: TrackNamespace,
336}
337
338// ============================================================
339// Subscribe Announces Messages
340// ============================================================
341
342/// SUBSCRIBE_ANNOUNCES message (type 0x11).
343#[derive(Debug, Clone, PartialEq, Eq)]
344pub struct SubscribeAnnounces {
345    /// The track namespace prefix to subscribe to announcements for.
346    pub track_namespace_prefix: TrackNamespace,
347    /// Subscribe announces parameters.
348    pub parameters: Vec<KeyValuePair>,
349}
350
351/// SUBSCRIBE_ANNOUNCES_OK message (type 0x12).
352#[derive(Debug, Clone, PartialEq, Eq)]
353pub struct SubscribeAnnouncesOk {
354    /// The track namespace prefix that was accepted.
355    pub track_namespace_prefix: TrackNamespace,
356}
357
358/// SUBSCRIBE_ANNOUNCES_ERROR message (type 0x13).
359#[derive(Debug, Clone, PartialEq, Eq)]
360pub struct SubscribeAnnouncesError {
361    /// The track namespace prefix that was rejected.
362    pub track_namespace_prefix: TrackNamespace,
363    /// The error code indicating the reason for failure.
364    pub error_code: VarInt,
365    /// A human-readable reason for the error.
366    pub reason_phrase: Vec<u8>,
367}
368
369/// UNSUBSCRIBE_ANNOUNCES message (type 0x14).
370#[derive(Debug, Clone, PartialEq, Eq)]
371pub struct UnsubscribeAnnounces {
372    /// The track namespace prefix to unsubscribe from.
373    pub track_namespace_prefix: TrackNamespace,
374}
375
376// ============================================================
377// Track Status Messages
378// ============================================================
379
380/// TRACK_STATUS_REQUEST message (type 0x0D).
381#[derive(Debug, Clone, PartialEq, Eq)]
382pub struct TrackStatusRequest {
383    /// The track namespace to query status for.
384    pub track_namespace: TrackNamespace,
385    /// The track name to query status for.
386    pub track_name: Vec<u8>,
387}
388
389/// TRACK_STATUS message (type 0x0E).
390#[derive(Debug, Clone, PartialEq, Eq)]
391pub struct TrackStatus {
392    /// The track namespace this status is for.
393    pub track_namespace: TrackNamespace,
394    /// The track name this status is for.
395    pub track_name: Vec<u8>,
396    /// The status code for the track.
397    pub status_code: VarInt,
398    /// The last group ID available on this track.
399    pub last_group_id: VarInt,
400    /// The last object ID available on this track.
401    pub last_object_id: VarInt,
402}
403
404// ============================================================
405// Fetch Messages
406// ============================================================
407
408/// Fetch type for FETCH message (draft-08).
409#[derive(Debug, Clone, Copy, PartialEq, Eq)]
410#[repr(u64)]
411pub enum FetchType {
412    /// Standalone fetch with explicit track and range.
413    Standalone = 1,
414    /// Joining fetch referencing an existing subscription.
415    Joining = 2,
416}
417
418impl FetchType {
419    /// Convert a raw value to a `FetchType`, if valid.
420    pub fn from_u64(v: u64) -> Option<Self> {
421        match v {
422            1 => Some(FetchType::Standalone),
423            2 => Some(FetchType::Joining),
424            _ => None,
425        }
426    }
427}
428
429/// FETCH message (type 0x16).
430///
431/// Draft-08: has fetch_type (standalone vs joining).
432#[derive(Debug, Clone, PartialEq, Eq)]
433pub struct Fetch {
434    /// The subscribe ID for this fetch request.
435    pub subscribe_id: VarInt,
436    /// The priority of this subscriber relative to others.
437    pub subscriber_priority: u8,
438    /// The requested group delivery order.
439    pub group_order: GroupOrder,
440    /// The fetch type (standalone or joining).
441    pub fetch_type: FetchType,
442    /// Track namespace (standalone only).
443    pub track_namespace: Option<TrackNamespace>,
444    /// Track name (standalone only).
445    pub track_name: Option<Vec<u8>>,
446    /// Start group (standalone only).
447    pub start_group: Option<VarInt>,
448    /// Start object (standalone only).
449    pub start_object: Option<VarInt>,
450    /// End group (standalone only).
451    pub end_group: Option<VarInt>,
452    /// End object (standalone only).
453    pub end_object: Option<VarInt>,
454    /// Joining subscribe ID (joining only).
455    pub joining_subscribe_id: Option<VarInt>,
456    /// Preceding group offset (joining only).
457    pub preceding_group_offset: Option<VarInt>,
458    /// Fetch parameters.
459    pub parameters: Vec<KeyValuePair>,
460}
461
462/// FETCH_OK message (type 0x18).
463///
464/// Draft-08: largest_group_id and largest_object_id are always present.
465#[derive(Debug, Clone, PartialEq, Eq)]
466pub struct FetchOk {
467    /// The subscribe ID this response corresponds to.
468    pub subscribe_id: VarInt,
469    /// The group delivery order chosen by the publisher.
470    pub group_order: GroupOrder,
471    /// Whether this fetch reaches the end of the track (1 = yes).
472    pub end_of_track: u8,
473    /// The largest group ID available.
474    pub largest_group_id: VarInt,
475    /// The largest object ID available.
476    pub largest_object_id: VarInt,
477    /// Fetch OK parameters.
478    pub parameters: Vec<KeyValuePair>,
479}
480
481/// FETCH_ERROR message (type 0x19).
482#[derive(Debug, Clone, PartialEq, Eq)]
483pub struct FetchError {
484    /// The subscribe ID this error corresponds to.
485    pub subscribe_id: VarInt,
486    /// The error code indicating the reason for failure.
487    pub error_code: VarInt,
488    /// A human-readable reason for the error.
489    pub reason_phrase: Vec<u8>,
490}
491
492/// FETCH_CANCEL message (type 0x17).
493#[derive(Debug, Clone, PartialEq, Eq)]
494pub struct FetchCancel {
495    /// The subscribe ID for the fetch to cancel.
496    pub subscribe_id: VarInt,
497}
498
499// ============================================================
500// Unified Message Enum
501// ============================================================
502
503/// Read a Group Order from a message that must name a real order.
504///
505/// SUBSCRIBE_OK and FETCH_OK each say
506/// "Values of 0x0 and those larger than 0x2 are a protocol error": a responder
507/// reports the order it settled on, so deferring to the publisher is not an
508/// answer it can give. SUBSCRIBE and FETCH are the requests, and there
509/// 0x0 is exactly how a subscriber says it has no preference — "the original
510/// publisher's Group Order SHOULD be used". The two readers cannot be merged
511/// without either refusing traffic the requests permit or accepting a reply
512/// that tells the subscriber nothing.
513fn read_group_order_response(buf: &mut impl Buf) -> Result<GroupOrder, CodecError> {
514    if !buf.has_remaining() {
515        return Err(CodecError::UnexpectedEnd);
516    }
517    match GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)? {
518        GroupOrder::Publisher => Err(CodecError::InvalidField),
519        order => Ok(order),
520    }
521}
522
523/// Hold a TRACK_STATUS Status Code and the fields after it to Section 7.24.
524///
525/// "The 'Status Code' field provides additional information about the status of
526/// the track. It MUST hold one of the following values. Any other value is a
527/// malformed message." Two of those values - 0x01 and 0x02 - add "Subsequent
528/// fields MUST be zero, and any other value is a malformed message".
529///
530/// Applied on both sides. A malformed message is one this codec must not read
531/// and equally must not write: an encoder that emits an unassigned Status Code
532/// hands a conforming peer a message it is required to reject.
533fn check_track_status(
534    status_code: VarInt,
535    last_group_id: VarInt,
536    last_object_id: VarInt,
537) -> Result<(), CodecError> {
538    let code = crate::draft08::error_codes::TrackStatusCode::from_u64(status_code.into_inner())
539        .ok_or(CodecError::InvalidField)?;
540    if code.requires_zero_location()
541        && (last_group_id.into_inner() != 0 || last_object_id.into_inner() != 0)
542    {
543        return Err(CodecError::InvalidField);
544    }
545    Ok(())
546}
547
548/// Refuse a message whose optional fields disagree with the field that decides
549/// whether they are on the wire.
550///
551/// Presence is not a property of the Rust value: the decoder derives it from a
552/// Filter Type, a Content Exists flag or a Fetch Type, and reads exactly the
553/// fields that discriminator names. An encoder that instead writes whatever
554/// happens to be `Some` produces a frame its own reader refuses - short by the
555/// missing fields, so the declared length runs out mid-payload, or long by the
556/// surplus ones, so bytes are left over. Section 7 makes either a session
557/// close, which is why this refuses rather than papering over it.
558fn check_discriminators(message: &ControlMessage) -> Result<(), CodecError> {
559    match message {
560        ControlMessage::Subscribe(m) => {
561            let wants_start =
562                matches!(m.filter_type, FilterType::AbsoluteStart | FilterType::AbsoluteRange);
563            if wants_start != m.start_location.is_some() {
564                return Err(CodecError::InvalidField);
565            }
566            if (m.filter_type == FilterType::AbsoluteRange) != m.end_group.is_some() {
567                return Err(CodecError::InvalidField);
568            }
569            Ok(())
570        }
571        ControlMessage::SubscribeOk(m) => {
572            let has = m.content_exists == ContentExists::HasLargestLocation;
573            if has != m.largest_group_id.is_some() || has != m.largest_object_id.is_some() {
574                return Err(CodecError::InvalidField);
575            }
576            Ok(())
577        }
578        ControlMessage::Fetch(m) => {
579            let standalone = m.fetch_type == FetchType::Standalone;
580            let standalone_fields = [
581                m.track_namespace.is_some(),
582                m.track_name.is_some(),
583                m.start_group.is_some(),
584                m.start_object.is_some(),
585                m.end_group.is_some(),
586                m.end_object.is_some(),
587            ];
588            if standalone_fields.iter().any(|present| *present != standalone) {
589                return Err(CodecError::InvalidField);
590            }
591            let joining_fields =
592                [m.joining_subscribe_id.is_some(), m.preceding_group_offset.is_some()];
593            if joining_fields.contains(&standalone) {
594                return Err(CodecError::InvalidField);
595            }
596            Ok(())
597        }
598        _ => Ok(()),
599    }
600}
601
602/// Refuse a Group Order of 0x0 on the messages that forbid it.
603///
604/// The decoders refuse it on the way in; without this the codec would still
605/// write a frame its own reader rejects.
606fn check_group_order(message: &ControlMessage) -> Result<(), CodecError> {
607    let order = match message {
608        ControlMessage::SubscribeOk(m) => m.group_order,
609        ControlMessage::FetchOk(m) => m.group_order,
610        _ => return Ok(()),
611    };
612    if order == GroupOrder::Publisher {
613        return Err(CodecError::InvalidField);
614    }
615    Ok(())
616}
617
618/// A decoded MoQT control message (draft-08).
619#[derive(Debug, Clone, PartialEq, Eq)]
620pub enum ControlMessage {
621    /// ClientSetup (type 0x40).
622    ClientSetup(ClientSetup),
623    /// ServerSetup (type 0x41).
624    ServerSetup(ServerSetup),
625    /// GoAway (type 0x10).
626    GoAway(GoAway),
627    /// MaxSubscribeId (type 0x15).
628    MaxSubscribeId(MaxSubscribeId),
629    /// SubscribesBlocked (type 0x1A).
630    SubscribesBlocked(SubscribesBlocked),
631    /// Subscribe (type 0x03).
632    Subscribe(Subscribe),
633    /// SubscribeOk (type 0x04).
634    SubscribeOk(SubscribeOk),
635    /// SubscribeError (type 0x05).
636    SubscribeError(SubscribeError),
637    /// SubscribeUpdate (type 0x02).
638    SubscribeUpdate(SubscribeUpdate),
639    /// SubscribeDone (type 0x0B).
640    SubscribeDone(SubscribeDone),
641    /// Unsubscribe (type 0x0A).
642    Unsubscribe(Unsubscribe),
643    /// Announce (type 0x06).
644    Announce(Announce),
645    /// AnnounceOk (type 0x07).
646    AnnounceOk(AnnounceOk),
647    /// AnnounceError (type 0x08).
648    AnnounceError(AnnounceError),
649    /// AnnounceCancel (type 0x0C).
650    AnnounceCancel(AnnounceCancel),
651    /// Unannounce (type 0x09).
652    Unannounce(Unannounce),
653    /// SubscribeAnnounces (type 0x11).
654    SubscribeAnnounces(SubscribeAnnounces),
655    /// SubscribeAnnouncesOk (type 0x12).
656    SubscribeAnnouncesOk(SubscribeAnnouncesOk),
657    /// SubscribeAnnouncesError (type 0x13).
658    SubscribeAnnouncesError(SubscribeAnnouncesError),
659    /// UnsubscribeAnnounces (type 0x14).
660    UnsubscribeAnnounces(UnsubscribeAnnounces),
661    /// TrackStatusRequest (type 0x0D).
662    TrackStatusRequest(TrackStatusRequest),
663    /// TrackStatus (type 0x0E).
664    TrackStatus(TrackStatus),
665    /// Fetch (type 0x16).
666    Fetch(Fetch),
667    /// FetchOk (type 0x18).
668    FetchOk(FetchOk),
669    /// FetchError (type 0x19).
670    FetchError(FetchError),
671    /// FetchCancel (type 0x17).
672    FetchCancel(FetchCancel),
673}
674
675/// Refuse a request whose range ends before it starts.
676///
677/// SUBSCRIBE's AbsoluteRange filter (Section 7.4), SUBSCRIBE_UPDATE
678/// (Section 7.5) and FETCH (Section 7.7) each state it, and the fields
679/// are not spelled the same way in the three places: an End Group is inclusive
680/// on SUBSCRIBE and FETCH and is the last group plus one on SUBSCRIBE_UPDATE,
681/// where zero means open ended, and an End Object is the last object plus one
682/// with zero meaning the whole group. The helpers this calls carry those
683/// conventions, one per shape.
684///
685/// Applied on both sides. A range that ends before it starts selects nothing,
686/// and the peer's only recourse is an error response or a session close, so
687/// writing one is not a way to ask for anything.
688fn check_ranges(message: &ControlMessage) -> Result<(), CodecError> {
689    match message {
690        ControlMessage::Subscribe(m) => match (&m.start_location, &m.end_group) {
691            (Some(start), Some(end_group)) => {
692                check_group_range(start.group.into_inner(), end_group.into_inner())
693            }
694            _ => Ok(()),
695        },
696        ControlMessage::SubscribeUpdate(m) => {
697            check_open_ended_group_range(m.start_group.into_inner(), m.end_group.into_inner())
698        }
699        ControlMessage::Fetch(m) => {
700            match (&m.start_group, &m.start_object, &m.end_group, &m.end_object) {
701                (Some(start_group), Some(start_object), Some(end_group), Some(end_object)) => {
702                    check_location_range(
703                        start_group.into_inner(),
704                        start_object.into_inner(),
705                        end_group.into_inner(),
706                        end_object.into_inner(),
707                    )
708                }
709                _ => Ok(()),
710            }
711        }
712        _ => Ok(()),
713    }
714}
715
716/// Refuse a parameter list that names the same Parameter Type twice.
717///
718/// Section 7.1: "Senders MUST NOT repeat the same parameter type in a
719/// message. Receivers SHOULD check that there are no duplicate
720/// parameters and close the session as a 'Protocol Violation' if found."
721///
722/// Applied on both sides. Code that scans a parameter list for a key takes
723/// whichever copy it meets first, so one frame carrying two values for one type
724/// is read differently by two conforming implementations - which is what makes
725/// the sender's half a MUST NOT rather than advice.
726fn check_no_duplicate_parameters(parameters: &[KeyValuePair]) -> Result<(), CodecError> {
727    for (i, parameter) in parameters.iter().enumerate() {
728        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
729            return Err(CodecError::DuplicateParameter(parameter.key.into_inner()));
730        }
731    }
732    Ok(())
733}
734
735/// The setup parameters this draft describes as carrying a single integer.
736///
737/// Section 7.2.2.2 gives MAX_SUBSCRIBE_ID as "an initial value for the Maximum
738/// Subscribe ID". PATH (Section 7.2.2.1) is a URI string and carries no implied
739/// length, so it is absent; ROLE, the other varint-valued setup parameter,
740/// belongs to draft-07 and this draft does not define it.
741const SETUP_VARINT_PARAMETERS: &[u64] = &[0x02];
742
743/// The version-specific parameters this draft describes as carrying a single
744/// integer.
745///
746/// Section 7.1.1.2 gives DELIVERY TIMEOUT as "the duration in milliseconds"
747/// and Section 7.1.1.3 gives MAX CACHE DURATION as "An integer expressing a
748/// number of milliseconds". AUTHORIZATION INFO is "an ASCII string" and is
749/// absent for the same reason PATH is.
750///
751/// The two lists are not interchangeable. Setup parameters and version-specific
752/// parameters use separate namespaces, and 0x02 is MAX_SUBSCRIBE_ID in one and
753/// AUTHORIZATION INFO in the other - applying the setup list to a SUBSCRIBE
754/// would refuse every authorization string that is not accidentally a varint.
755const VERSION_VARINT_PARAMETERS: &[u64] = &[0x03, 0x04];
756
757/// Refuse a parameter whose value is not the shape its type implies.
758///
759/// Section 7.1: "If a receiver understands a parameter type, and the parameter
760/// length implied by that type does not match the Parameter Length field, the
761/// receiver MUST terminate the session with error code 'Parameter Length
762/// Mismatch'."
763///
764/// This draft frames every parameter as {Type, Length, Value} with no per-key
765/// table, so a parameter that came off the wire always arrives as bytes and its
766/// declared length is whatever the sender wrote. For a type whose definition
767/// says the value is one integer, the implied length is that varint's own
768/// length, and the two agree only when the value is exactly one varint with
769/// nothing after it.
770///
771/// A value already held as a varint is not checked: [`KeyValuePair::encode_d07`]
772/// derives its length field from the varint it is about to write, so those two
773/// cannot disagree. Only bytes can.
774fn check_parameter_lengths(
775    parameters: &[KeyValuePair],
776    varint_typed: &[u64],
777) -> Result<(), CodecError> {
778    for parameter in parameters {
779        let key = parameter.key.into_inner();
780        if !varint_typed.contains(&key) {
781            continue;
782        }
783        if let crate::kvp::KvpValue::Bytes(bytes) = &parameter.value {
784            let mut cursor = &bytes[..];
785            let one_varint = VarInt::decode(&mut cursor).is_ok() && !cursor.has_remaining();
786            if !one_varint {
787                return Err(CodecError::ParameterLengthMismatch(key));
788            }
789        }
790    }
791    Ok(())
792}
793
794/// Decode a version-specific parameter list, refusing a repeated type and a
795/// value whose length disagrees with its type.
796fn decode_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
797    let parameters = KeyValuePair::decode_list_d07(buf)?;
798    check_no_duplicate_parameters(&parameters)?;
799    check_parameter_lengths(&parameters, VERSION_VARINT_PARAMETERS)?;
800    Ok(parameters)
801}
802
803/// Encode a version-specific parameter list, refusing a repeated type and a
804/// value whose length disagrees with its type.
805fn encode_parameters(parameters: &[KeyValuePair], buf: &mut impl BufMut) -> Result<(), CodecError> {
806    check_no_duplicate_parameters(parameters)?;
807    check_parameter_lengths(parameters, VERSION_VARINT_PARAMETERS)?;
808    KeyValuePair::encode_list_d07(parameters, buf);
809    Ok(())
810}
811
812/// Decode a setup parameter list.
813///
814/// Setup parameters use a namespace of their own, so the same key number means
815/// something different here than it does in every other message and the implied
816/// lengths are read from a different list.
817fn decode_setup_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
818    let parameters = KeyValuePair::decode_list_d07(buf)?;
819    check_no_duplicate_parameters(&parameters)?;
820    check_parameter_lengths(&parameters, SETUP_VARINT_PARAMETERS)?;
821    Ok(parameters)
822}
823
824/// Encode a setup parameter list, under the setup namespace's implied lengths.
825fn encode_setup_parameters(
826    parameters: &[KeyValuePair],
827    buf: &mut impl BufMut,
828) -> Result<(), CodecError> {
829    check_no_duplicate_parameters(parameters)?;
830    check_parameter_lengths(parameters, SETUP_VARINT_PARAMETERS)?;
831    KeyValuePair::encode_list_d07(parameters, buf);
832    Ok(())
833}
834
835impl ControlMessage {
836    /// Return the message type for this control message.
837    pub fn message_type(&self) -> MessageType {
838        match self {
839            ControlMessage::ClientSetup(_) => MessageType::ClientSetup,
840            ControlMessage::ServerSetup(_) => MessageType::ServerSetup,
841            ControlMessage::GoAway(_) => MessageType::GoAway,
842            ControlMessage::MaxSubscribeId(_) => MessageType::MaxSubscribeId,
843            ControlMessage::SubscribesBlocked(_) => MessageType::SubscribesBlocked,
844            ControlMessage::Subscribe(_) => MessageType::Subscribe,
845            ControlMessage::SubscribeOk(_) => MessageType::SubscribeOk,
846            ControlMessage::SubscribeError(_) => MessageType::SubscribeError,
847            ControlMessage::SubscribeUpdate(_) => MessageType::SubscribeUpdate,
848            ControlMessage::SubscribeDone(_) => MessageType::SubscribeDone,
849            ControlMessage::Unsubscribe(_) => MessageType::Unsubscribe,
850            ControlMessage::Announce(_) => MessageType::Announce,
851            ControlMessage::AnnounceOk(_) => MessageType::AnnounceOk,
852            ControlMessage::AnnounceError(_) => MessageType::AnnounceError,
853            ControlMessage::AnnounceCancel(_) => MessageType::AnnounceCancel,
854            ControlMessage::Unannounce(_) => MessageType::Unannounce,
855            ControlMessage::SubscribeAnnounces(_) => MessageType::SubscribeAnnounces,
856            ControlMessage::SubscribeAnnouncesOk(_) => MessageType::SubscribeAnnouncesOk,
857            ControlMessage::SubscribeAnnouncesError(_) => MessageType::SubscribeAnnouncesError,
858            ControlMessage::UnsubscribeAnnounces(_) => MessageType::UnsubscribeAnnounces,
859            ControlMessage::TrackStatusRequest(_) => MessageType::TrackStatusRequest,
860            ControlMessage::TrackStatus(_) => MessageType::TrackStatus,
861            ControlMessage::Fetch(_) => MessageType::Fetch,
862            ControlMessage::FetchOk(_) => MessageType::FetchOk,
863            ControlMessage::FetchError(_) => MessageType::FetchError,
864            ControlMessage::FetchCancel(_) => MessageType::FetchCancel,
865        }
866    }
867
868    /// Encode this control message (type ID + length prefix + payload).
869    pub fn encode(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
870        check_discriminators(self)?;
871        check_group_order(self)?;
872        check_ranges(self)?;
873        let mut payload = Vec::with_capacity(256);
874        self.encode_payload(&mut payload)?;
875
876        // No cap here. This draft frames a control message with a varint
877        // Length and states no maximum, and this module's own decoder applies
878        // none either - a ceiling on encode would refuse to write a message
879        // this codec will read. The 65,535-byte limit belongs to draft-11 and
880        // later, where the Length field is 16 bits wide and the limit is a
881        // consequence of the framing.
882
883        VarInt::from_usize(self.message_type().id() as usize).encode(buf);
884        VarInt::from_usize(payload.len()).encode(buf);
885        buf.put_slice(&payload);
886        Ok(())
887    }
888
889    /// Decode a control message from bytes.
890    pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError> {
891        let type_id = VarInt::decode(buf)?.into_inner();
892        let msg_type =
893            MessageType::from_id(type_id).ok_or(CodecError::UnknownMessageType(type_id))?;
894        let payload_len = VarInt::decode(buf)?.into_inner() as usize;
895        if buf.remaining() < payload_len {
896            return Err(CodecError::UnexpectedEnd);
897        }
898        let payload_bytes = buf.copy_to_bytes(payload_len);
899        let mut payload = &payload_bytes[..];
900        let msg = match Self::decode_payload(msg_type, &mut payload) {
901            Ok(msg) => msg,
902            // The fields wanted more bytes than the Length allowed. This buffer
903            // is already bounded by that Length, so running out inside it cannot
904            // mean the message is still arriving - which is what the same error
905            // means everywhere else, and why a reader loops on it rather than
906            // closing. Here there is nothing left to arrive.
907            Err(
908                CodecError::UnexpectedEnd
909                | CodecError::Kvp(crate::kvp::KvpError::UnexpectedEnd)
910                | CodecError::Kvp(crate::kvp::KvpError::VarInt(
911                    crate::varint::VarIntError::UnexpectedEnd,
912                ))
913                | CodecError::VarInt(crate::varint::VarIntError::UnexpectedEnd),
914            ) => {
915                return Err(CodecError::ControlMessageLengthMismatch {
916                    declared: payload_len,
917                    detail: "its fields ran past the end",
918                });
919            }
920            Err(e) => return Err(e),
921        };
922        check_ranges(&msg)?;
923        // The declared length is part of the message, not a hint. Bytes left over
924        // after the fields have been read mean the sender and this reader disagree
925        // about the shape of the message, and guessing which of the two is right
926        // is how a trailing field gets silently dropped.
927        if payload.has_remaining() {
928            return Err(CodecError::ControlMessageLengthMismatch {
929                declared: payload_len,
930                detail: "its fields left bytes unread",
931            });
932        }
933        Ok(msg)
934    }
935
936    fn encode_payload(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
937        match self {
938            ControlMessage::ClientSetup(m) => {
939                VarInt::from_usize(m.supported_versions.len()).encode(buf);
940                for v in &m.supported_versions {
941                    v.encode(buf);
942                }
943                encode_setup_parameters(&m.parameters, buf)?;
944            }
945            ControlMessage::ServerSetup(m) => {
946                m.selected_version.encode(buf);
947                encode_setup_parameters(&m.parameters, buf)?;
948            }
949            ControlMessage::GoAway(m) => {
950                VarInt::from_usize(m.new_session_uri.len()).encode(buf);
951                buf.put_slice(&m.new_session_uri);
952            }
953            ControlMessage::MaxSubscribeId(m) => {
954                m.subscribe_id.encode(buf);
955            }
956            ControlMessage::SubscribesBlocked(m) => {
957                m.maximum_subscribe_id.encode(buf);
958            }
959            ControlMessage::Subscribe(m) => {
960                m.subscribe_id.encode(buf);
961                m.track_alias.encode(buf);
962                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
963                m.track_namespace.encode(buf);
964                VarInt::from_usize(m.track_name.len()).encode(buf);
965                buf.put_slice(&m.track_name);
966                buf.put_u8(m.subscriber_priority);
967                buf.put_u8(m.group_order as u8);
968                VarInt::from_usize(m.filter_type as usize).encode(buf);
969                if let Some(loc) = &m.start_location {
970                    loc.encode(buf);
971                }
972                if let Some(eg) = &m.end_group {
973                    eg.encode(buf);
974                }
975                encode_parameters(&m.parameters, buf)?;
976            }
977            ControlMessage::SubscribeOk(m) => {
978                m.subscribe_id.encode(buf);
979                m.expires.encode(buf);
980                buf.put_u8(m.group_order as u8);
981                buf.put_u8(m.content_exists as u8);
982                if let Some(gid) = &m.largest_group_id {
983                    gid.encode(buf);
984                }
985                if let Some(oid) = &m.largest_object_id {
986                    oid.encode(buf);
987                }
988                encode_parameters(&m.parameters, buf)?;
989            }
990            ControlMessage::SubscribeError(m) => {
991                m.subscribe_id.encode(buf);
992                m.error_code.encode(buf);
993                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
994                buf.put_slice(&m.reason_phrase);
995                m.track_alias.encode(buf);
996            }
997            ControlMessage::SubscribeUpdate(m) => {
998                m.subscribe_id.encode(buf);
999                m.start_group.encode(buf);
1000                m.start_object.encode(buf);
1001                m.end_group.encode(buf);
1002                buf.put_u8(m.subscriber_priority);
1003                encode_parameters(&m.parameters, buf)?;
1004            }
1005            ControlMessage::SubscribeDone(m) => {
1006                m.subscribe_id.encode(buf);
1007                m.status_code.encode(buf);
1008                m.stream_count.encode(buf);
1009                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1010                buf.put_slice(&m.reason_phrase);
1011            }
1012            ControlMessage::Unsubscribe(m) => {
1013                m.subscribe_id.encode(buf);
1014            }
1015            ControlMessage::Announce(m) => {
1016                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1017                m.track_namespace.encode(buf);
1018                encode_parameters(&m.parameters, buf)?;
1019            }
1020            ControlMessage::AnnounceOk(m) => {
1021                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1022                m.track_namespace.encode(buf);
1023            }
1024            ControlMessage::AnnounceError(m) => {
1025                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1026                m.track_namespace.encode(buf);
1027                m.error_code.encode(buf);
1028                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1029                buf.put_slice(&m.reason_phrase);
1030            }
1031            ControlMessage::AnnounceCancel(m) => {
1032                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1033                m.track_namespace.encode(buf);
1034                m.error_code.encode(buf);
1035                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1036                buf.put_slice(&m.reason_phrase);
1037            }
1038            ControlMessage::Unannounce(m) => {
1039                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1040                m.track_namespace.encode(buf);
1041            }
1042            ControlMessage::SubscribeAnnounces(m) => {
1043                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(8))?;
1044                m.track_namespace_prefix.encode(buf);
1045                encode_parameters(&m.parameters, buf)?;
1046            }
1047            ControlMessage::SubscribeAnnouncesOk(m) => {
1048                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(8))?;
1049                m.track_namespace_prefix.encode(buf);
1050            }
1051            ControlMessage::SubscribeAnnouncesError(m) => {
1052                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(8))?;
1053                m.track_namespace_prefix.encode(buf);
1054                m.error_code.encode(buf);
1055                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1056                buf.put_slice(&m.reason_phrase);
1057            }
1058            ControlMessage::UnsubscribeAnnounces(m) => {
1059                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(8))?;
1060                m.track_namespace_prefix.encode(buf);
1061            }
1062            ControlMessage::TrackStatusRequest(m) => {
1063                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1064                m.track_namespace.encode(buf);
1065                VarInt::from_usize(m.track_name.len()).encode(buf);
1066                buf.put_slice(&m.track_name);
1067            }
1068            ControlMessage::TrackStatus(m) => {
1069                m.track_namespace.validate(TrackNamespaceRules::for_draft(8))?;
1070                m.track_namespace.encode(buf);
1071                VarInt::from_usize(m.track_name.len()).encode(buf);
1072                buf.put_slice(&m.track_name);
1073                check_track_status(m.status_code, m.last_group_id, m.last_object_id)?;
1074                m.status_code.encode(buf);
1075                m.last_group_id.encode(buf);
1076                m.last_object_id.encode(buf);
1077            }
1078            ControlMessage::Fetch(m) => {
1079                m.subscribe_id.encode(buf);
1080                buf.put_u8(m.subscriber_priority);
1081                buf.put_u8(m.group_order as u8);
1082                VarInt::from_usize(m.fetch_type as usize).encode(buf);
1083                match m.fetch_type {
1084                    FetchType::Standalone => {
1085                        if let Some(ns) = &m.track_namespace {
1086                            ns.encode(buf);
1087                        }
1088                        if let Some(name) = &m.track_name {
1089                            VarInt::from_usize(name.len()).encode(buf);
1090                            buf.put_slice(name);
1091                        }
1092                        if let Some(sg) = &m.start_group {
1093                            sg.encode(buf);
1094                        }
1095                        if let Some(so) = &m.start_object {
1096                            so.encode(buf);
1097                        }
1098                        if let Some(eg) = &m.end_group {
1099                            eg.encode(buf);
1100                        }
1101                        if let Some(eo) = &m.end_object {
1102                            eo.encode(buf);
1103                        }
1104                    }
1105                    FetchType::Joining => {
1106                        if let Some(jsi) = &m.joining_subscribe_id {
1107                            jsi.encode(buf);
1108                        }
1109                        if let Some(pgo) = &m.preceding_group_offset {
1110                            pgo.encode(buf);
1111                        }
1112                    }
1113                }
1114                encode_parameters(&m.parameters, buf)?;
1115            }
1116            ControlMessage::FetchOk(m) => {
1117                m.subscribe_id.encode(buf);
1118                buf.put_u8(m.group_order as u8);
1119                buf.put_u8(m.end_of_track);
1120                m.largest_group_id.encode(buf);
1121                m.largest_object_id.encode(buf);
1122                encode_parameters(&m.parameters, buf)?;
1123            }
1124            ControlMessage::FetchError(m) => {
1125                m.subscribe_id.encode(buf);
1126                m.error_code.encode(buf);
1127                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1128                buf.put_slice(&m.reason_phrase);
1129            }
1130            ControlMessage::FetchCancel(m) => {
1131                m.subscribe_id.encode(buf);
1132            }
1133        }
1134        Ok(())
1135    }
1136
1137    fn decode_payload(msg_type: MessageType, buf: &mut impl Buf) -> Result<Self, CodecError> {
1138        match msg_type {
1139            MessageType::ClientSetup => {
1140                let num_versions = VarInt::decode(buf)?.into_inner() as usize;
1141                // Not a rule this draft states. It says only that the server
1142                // "MUST reply with one of the versions offered by the client"
1143                // and that a peer with no version in common "MUST close the
1144                // session" - outcomes of negotiation rather than parse errors,
1145                // and a CLIENT_SETUP offering nothing decodes cleanly under the
1146                // figure. It is refused here because there is no version a
1147                // reply could name, so the session is already over and the
1148                // early close is the more useful answer than a well-formed
1149                // message no caller can act on.
1150                if num_versions == 0 {
1151                    return Err(CodecError::InvalidField);
1152                }
1153                let mut supported_versions = crate::types::reserve_bounded(num_versions, buf);
1154                for _ in 0..num_versions {
1155                    supported_versions.push(VarInt::decode(buf)?);
1156                }
1157                let parameters = decode_setup_parameters(buf)?;
1158                Ok(ControlMessage::ClientSetup(ClientSetup { supported_versions, parameters }))
1159            }
1160            MessageType::ServerSetup => {
1161                let selected_version = VarInt::decode(buf)?;
1162                let parameters = decode_setup_parameters(buf)?;
1163                Ok(ControlMessage::ServerSetup(ServerSetup { selected_version, parameters }))
1164            }
1165            MessageType::GoAway => {
1166                let uri_len = VarInt::decode(buf)?.into_inner() as usize;
1167                let uri = read_bytes(buf, uri_len)?;
1168                Ok(ControlMessage::GoAway(GoAway { new_session_uri: uri }))
1169            }
1170            MessageType::MaxSubscribeId => {
1171                let subscribe_id = VarInt::decode(buf)?;
1172                Ok(ControlMessage::MaxSubscribeId(MaxSubscribeId { subscribe_id }))
1173            }
1174            MessageType::SubscribesBlocked => {
1175                let maximum_subscribe_id = VarInt::decode(buf)?;
1176                Ok(ControlMessage::SubscribesBlocked(SubscribesBlocked { maximum_subscribe_id }))
1177            }
1178            MessageType::Subscribe => {
1179                let subscribe_id = VarInt::decode(buf)?;
1180                let track_alias = VarInt::decode(buf)?;
1181                let track_namespace = TrackNamespace::decode(buf)?;
1182                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1183                let track_name = read_bytes(buf, track_name_len)?;
1184                if buf.remaining() < 2 {
1185                    return Err(CodecError::UnexpectedEnd);
1186                }
1187                let subscriber_priority = buf.get_u8();
1188                let group_order =
1189                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1190                let filter_val = VarInt::decode(buf)?.into_inner();
1191                let filter_type = FilterType::from_u64(filter_val)
1192                    .ok_or(CodecError::InvalidFilterType(filter_val))?;
1193                let start_location = match filter_type {
1194                    FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
1195                        Some(Location::decode(buf)?)
1196                    }
1197                    _ => None,
1198                };
1199                let end_group = match filter_type {
1200                    FilterType::AbsoluteRange => Some(VarInt::decode(buf)?),
1201                    _ => None,
1202                };
1203                let parameters = decode_parameters(buf)?;
1204                Ok(ControlMessage::Subscribe(Subscribe {
1205                    subscribe_id,
1206                    track_alias,
1207                    track_namespace,
1208                    track_name,
1209                    subscriber_priority,
1210                    group_order,
1211                    filter_type,
1212                    start_location,
1213                    end_group,
1214                    parameters,
1215                }))
1216            }
1217            MessageType::SubscribeOk => {
1218                let subscribe_id = VarInt::decode(buf)?;
1219                let expires = VarInt::decode(buf)?;
1220                if buf.remaining() < 2 {
1221                    return Err(CodecError::UnexpectedEnd);
1222                }
1223                let group_order = read_group_order_response(buf)?;
1224                let content_exists_val = buf.get_u8();
1225                let content_exists = match content_exists_val {
1226                    0 => ContentExists::NoLargestLocation,
1227                    1 => ContentExists::HasLargestLocation,
1228                    other => return Err(CodecError::InvalidContentExists(other)),
1229                };
1230                let (largest_group_id, largest_object_id) =
1231                    if content_exists == ContentExists::HasLargestLocation {
1232                        let gid = VarInt::decode(buf)?;
1233                        let oid = VarInt::decode(buf)?;
1234                        (Some(gid), Some(oid))
1235                    } else {
1236                        (None, None)
1237                    };
1238                let parameters = decode_parameters(buf)?;
1239                Ok(ControlMessage::SubscribeOk(SubscribeOk {
1240                    subscribe_id,
1241                    expires,
1242                    group_order,
1243                    content_exists,
1244                    largest_group_id,
1245                    largest_object_id,
1246                    parameters,
1247                }))
1248            }
1249            MessageType::SubscribeError => {
1250                let subscribe_id = VarInt::decode(buf)?;
1251                let error_code = VarInt::decode(buf)?;
1252                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1253                let reason_phrase = read_bytes(buf, reason_len)?;
1254                let track_alias = VarInt::decode(buf)?;
1255                Ok(ControlMessage::SubscribeError(SubscribeError {
1256                    subscribe_id,
1257                    error_code,
1258                    reason_phrase,
1259                    track_alias,
1260                }))
1261            }
1262            MessageType::SubscribeUpdate => {
1263                let subscribe_id = VarInt::decode(buf)?;
1264                let start_group = VarInt::decode(buf)?;
1265                let start_object = VarInt::decode(buf)?;
1266                let end_group = VarInt::decode(buf)?;
1267                if buf.remaining() < 1 {
1268                    return Err(CodecError::UnexpectedEnd);
1269                }
1270                let subscriber_priority = buf.get_u8();
1271                let parameters = decode_parameters(buf)?;
1272                Ok(ControlMessage::SubscribeUpdate(SubscribeUpdate {
1273                    subscribe_id,
1274                    start_group,
1275                    start_object,
1276                    end_group,
1277                    subscriber_priority,
1278                    parameters,
1279                }))
1280            }
1281            MessageType::SubscribeDone => {
1282                let subscribe_id = VarInt::decode(buf)?;
1283                let status_code = VarInt::decode(buf)?;
1284                let stream_count = VarInt::decode(buf)?;
1285                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1286                let reason_phrase = read_bytes(buf, reason_len)?;
1287                Ok(ControlMessage::SubscribeDone(SubscribeDone {
1288                    subscribe_id,
1289                    status_code,
1290                    stream_count,
1291                    reason_phrase,
1292                }))
1293            }
1294            MessageType::Unsubscribe => {
1295                let subscribe_id = VarInt::decode(buf)?;
1296                Ok(ControlMessage::Unsubscribe(Unsubscribe { subscribe_id }))
1297            }
1298            MessageType::Announce => {
1299                let track_namespace = TrackNamespace::decode(buf)?;
1300                let parameters = decode_parameters(buf)?;
1301                Ok(ControlMessage::Announce(Announce { track_namespace, parameters }))
1302            }
1303            MessageType::AnnounceOk => {
1304                let track_namespace = TrackNamespace::decode(buf)?;
1305                Ok(ControlMessage::AnnounceOk(AnnounceOk { track_namespace }))
1306            }
1307            MessageType::AnnounceError => {
1308                let track_namespace = TrackNamespace::decode(buf)?;
1309                let error_code = VarInt::decode(buf)?;
1310                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1311                let reason_phrase = read_bytes(buf, reason_len)?;
1312                Ok(ControlMessage::AnnounceError(AnnounceError {
1313                    track_namespace,
1314                    error_code,
1315                    reason_phrase,
1316                }))
1317            }
1318            MessageType::AnnounceCancel => {
1319                let track_namespace = TrackNamespace::decode(buf)?;
1320                let error_code = VarInt::decode(buf)?;
1321                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1322                let reason_phrase = read_bytes(buf, reason_len)?;
1323                Ok(ControlMessage::AnnounceCancel(AnnounceCancel {
1324                    track_namespace,
1325                    error_code,
1326                    reason_phrase,
1327                }))
1328            }
1329            MessageType::Unannounce => {
1330                let track_namespace = TrackNamespace::decode(buf)?;
1331                Ok(ControlMessage::Unannounce(Unannounce { track_namespace }))
1332            }
1333            MessageType::SubscribeAnnounces => {
1334                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1335                let parameters = decode_parameters(buf)?;
1336                Ok(ControlMessage::SubscribeAnnounces(SubscribeAnnounces {
1337                    track_namespace_prefix,
1338                    parameters,
1339                }))
1340            }
1341            MessageType::SubscribeAnnouncesOk => {
1342                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1343                Ok(ControlMessage::SubscribeAnnouncesOk(SubscribeAnnouncesOk {
1344                    track_namespace_prefix,
1345                }))
1346            }
1347            MessageType::SubscribeAnnouncesError => {
1348                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1349                let error_code = VarInt::decode(buf)?;
1350                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1351                let reason_phrase = read_bytes(buf, reason_len)?;
1352                Ok(ControlMessage::SubscribeAnnouncesError(SubscribeAnnouncesError {
1353                    track_namespace_prefix,
1354                    error_code,
1355                    reason_phrase,
1356                }))
1357            }
1358            MessageType::UnsubscribeAnnounces => {
1359                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1360                Ok(ControlMessage::UnsubscribeAnnounces(UnsubscribeAnnounces {
1361                    track_namespace_prefix,
1362                }))
1363            }
1364            MessageType::TrackStatusRequest => {
1365                let track_namespace = TrackNamespace::decode(buf)?;
1366                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1367                let track_name = read_bytes(buf, track_name_len)?;
1368                Ok(ControlMessage::TrackStatusRequest(TrackStatusRequest {
1369                    track_namespace,
1370                    track_name,
1371                }))
1372            }
1373            MessageType::TrackStatus => {
1374                let track_namespace = TrackNamespace::decode(buf)?;
1375                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1376                let track_name = read_bytes(buf, track_name_len)?;
1377                let status_code = VarInt::decode(buf)?;
1378                let last_group_id = VarInt::decode(buf)?;
1379                let last_object_id = VarInt::decode(buf)?;
1380                check_track_status(status_code, last_group_id, last_object_id)?;
1381                Ok(ControlMessage::TrackStatus(TrackStatus {
1382                    track_namespace,
1383                    track_name,
1384                    status_code,
1385                    last_group_id,
1386                    last_object_id,
1387                }))
1388            }
1389            MessageType::Fetch => {
1390                let subscribe_id = VarInt::decode(buf)?;
1391                if buf.remaining() < 2 {
1392                    return Err(CodecError::UnexpectedEnd);
1393                }
1394                let subscriber_priority = buf.get_u8();
1395                let group_order =
1396                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1397                let fetch_type_val = VarInt::decode(buf)?.into_inner();
1398                let fetch_type = FetchType::from_u64(fetch_type_val)
1399                    .ok_or(CodecError::InvalidFetchType(fetch_type_val))?;
1400                let (
1401                    track_namespace,
1402                    track_name,
1403                    start_group,
1404                    start_object,
1405                    end_group,
1406                    end_object,
1407                    joining_subscribe_id,
1408                    preceding_group_offset,
1409                ) = match fetch_type {
1410                    FetchType::Standalone => {
1411                        let ns = TrackNamespace::decode(buf)?;
1412                        let name_len = VarInt::decode(buf)?.into_inner() as usize;
1413                        let name = read_bytes(buf, name_len)?;
1414                        let sg = VarInt::decode(buf)?;
1415                        let so = VarInt::decode(buf)?;
1416                        let eg = VarInt::decode(buf)?;
1417                        let eo = VarInt::decode(buf)?;
1418                        (Some(ns), Some(name), Some(sg), Some(so), Some(eg), Some(eo), None, None)
1419                    }
1420                    FetchType::Joining => {
1421                        let jsi = VarInt::decode(buf)?;
1422                        let pgo = VarInt::decode(buf)?;
1423                        (None, None, None, None, None, None, Some(jsi), Some(pgo))
1424                    }
1425                };
1426                let parameters = decode_parameters(buf)?;
1427                Ok(ControlMessage::Fetch(Fetch {
1428                    subscribe_id,
1429                    subscriber_priority,
1430                    group_order,
1431                    fetch_type,
1432                    track_namespace,
1433                    track_name,
1434                    start_group,
1435                    start_object,
1436                    end_group,
1437                    end_object,
1438                    joining_subscribe_id,
1439                    preceding_group_offset,
1440                    parameters,
1441                }))
1442            }
1443            MessageType::FetchOk => {
1444                let subscribe_id = VarInt::decode(buf)?;
1445                if buf.remaining() < 2 {
1446                    return Err(CodecError::UnexpectedEnd);
1447                }
1448                let group_order = read_group_order_response(buf)?;
1449                let end_of_track = buf.get_u8();
1450                let largest_group_id = VarInt::decode(buf)?;
1451                let largest_object_id = VarInt::decode(buf)?;
1452                let parameters = decode_parameters(buf)?;
1453                Ok(ControlMessage::FetchOk(FetchOk {
1454                    subscribe_id,
1455                    group_order,
1456                    end_of_track,
1457                    largest_group_id,
1458                    largest_object_id,
1459                    parameters,
1460                }))
1461            }
1462            MessageType::FetchError => {
1463                let subscribe_id = VarInt::decode(buf)?;
1464                let error_code = VarInt::decode(buf)?;
1465                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1466                let reason_phrase = read_bytes(buf, reason_len)?;
1467                Ok(ControlMessage::FetchError(FetchError {
1468                    subscribe_id,
1469                    error_code,
1470                    reason_phrase,
1471                }))
1472            }
1473            MessageType::FetchCancel => {
1474                let subscribe_id = VarInt::decode(buf)?;
1475                Ok(ControlMessage::FetchCancel(FetchCancel { subscribe_id }))
1476            }
1477        }
1478    }
1479}