Skip to main content

moqtap_codec/draft07/
message.rs

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