Skip to main content

moqtap_codec/draft14/
message.rs

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