Skip to main content

moqtap_codec/draft11/
error_codes.rs

1//! Draft-11 error and status code registries.
2//!
3//! Draft-11 predates the IANA registries introduced in draft-14: every code
4//! point here is defined by an inline `Code`/`Reason` table in the body of the
5//! document, and each table is scoped to one control message rather than to a
6//! shared registry. The tables carry no symbolic ALLCAPS names, so each variant
7//! name below is derived from the reason text and the doc comment repeats the
8//! draft's own wording verbatim, so the mapping stays checkable against the
9//! document.
10//!
11//! Every `from_u64` returns `None` for a code this draft does not define. Peers
12//! do send codes from other drafts and from private extensions, and a decoder
13//! that panics on one is a decoder that dies on the wire.
14//!
15//! Not every draft-11 code registry is written as a table. `TrackStatusCode`
16//! below comes from a prose list in the body of section 8.18, and the object
17//! status values of section 9.1.1.1 are likewise prose; those live in
18//! `super::types::ObjectStatus` rather than here.
19
20/// Session termination codes, from the table in draft-11 section 3.4
21/// (Termination). Carried in the session-level termination error code.
22///
23/// The draft assigns 0x0 through 0x9 and then 0x10 through 0x15; 0xA through
24/// 0xF are not assigned.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26#[repr(u64)]
27pub enum SessionErrorCode {
28    /// `No Error` — the session is being terminated without an error.
29    NoError = 0x0,
30    /// `Internal Error` — an implementation specific error occurred.
31    InternalError = 0x1,
32    /// `Unauthorized` — the endpoint breached an agreement, which MAY have been
33    /// pre-negotiated by the application.
34    Unauthorized = 0x2,
35    /// `Protocol Violation` — the remote endpoint performed an action that was
36    /// disallowed by the specification.
37    ProtocolViolation = 0x3,
38    /// `Invalid Request ID` — the session was closed because the endpoint used a
39    /// Request ID that was smaller than or equal to a previously received
40    /// request ID, or the least-significant bit of the request ID was incorrect
41    /// for the endpoint.
42    InvalidRequestId = 0x4,
43    /// `Duplicate Track Alias` — the endpoint attempted to use a Track Alias
44    /// that was already in use.
45    DuplicateTrackAlias = 0x5,
46    /// `Key-Value Formatting Error` — the key-value pair has a formatting error.
47    KeyValueFormattingError = 0x6,
48    /// `Too Many Requests` — the session was closed because the endpoint used a
49    /// Request ID equal or larger than the current Maximum Request ID.
50    TooManyRequests = 0x7,
51    /// `Invalid Path` — the PATH parameter was used by a server, on a
52    /// WebTransport session, or the server does not support the path.
53    InvalidPath = 0x8,
54    /// `Malformed Path` — the PATH parameter does not conform to the rules in
55    /// draft-11 section 8.3.2.1.
56    MalformedPath = 0x9,
57    /// `GOAWAY Timeout` — the session was closed because the peer took too long
58    /// to close the session in response to a GOAWAY message. See session
59    /// migration, draft-11 section 3.5.
60    GoawayTimeout = 0x10,
61    /// `Control Message Timeout` — the session was closed because the peer took
62    /// too long to respond to a control message.
63    ControlMessageTimeout = 0x11,
64    /// `Data Stream Timeout` — the session was closed because the peer took too
65    /// long to send data expected on an open data stream. This includes fields
66    /// of a stream header or an object header within a data stream. An endpoint
67    /// that times out waiting for a new object header on an open subgroup
68    /// stream MAY instead send STOP_SENDING on that stream or terminate the
69    /// subscription.
70    DataStreamTimeout = 0x12,
71    /// `Auth Token Cache Overflow` — the session limit on the total size of all
72    /// registered authorization tokens has been exceeded. See draft-11
73    /// section 8.3.2.3.
74    AuthTokenCacheOverflow = 0x13,
75    /// `Duplicate Auth Token Alias` — an Authorization Token attempted to
76    /// register an alias that was in use. See draft-11 section 8.2.1.1.
77    DuplicateAuthTokenAlias = 0x14,
78    /// `Version Negotiation Failed` — the client didn't offer a version
79    /// supported by the server.
80    VersionNegotiationFailed = 0x15,
81}
82
83/// SUBSCRIBE_ERROR codes, from the table in draft-11 section 8.9.
84///
85/// The draft assigns 0x0 through 0x6 and then 0x10 through 0x12; 0x7 through
86/// 0xF are not assigned.
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88#[repr(u64)]
89pub enum SubscribeErrorCode {
90    /// `Internal Error` — an implementation specific or generic error occurred.
91    InternalError = 0x0,
92    /// `Unauthorized` — the subscriber is not authorized to subscribe to the
93    /// given track.
94    Unauthorized = 0x1,
95    /// `Timeout` — the subscription could not be completed before an
96    /// implementation specific timeout. For example, a relay could not
97    /// establish an upstream subscription within the timeout.
98    Timeout = 0x2,
99    /// `Not Supported` — the endpoint does not support the SUBSCRIBE method.
100    NotSupported = 0x3,
101    /// `Track Does Not Exist` — the requested track is not available at the
102    /// publisher.
103    TrackDoesNotExist = 0x4,
104    /// `Invalid Range` — the end of the SUBSCRIBE range is earlier than the
105    /// beginning, or the end of the range has already been published.
106    InvalidRange = 0x5,
107    /// `Retry Track Alias` — the publisher requires the subscriber to use the
108    /// given Track Alias when subscribing. The alias to retry with is carried
109    /// in the Track Alias field of the SUBSCRIBE_ERROR message.
110    RetryTrackAlias = 0x6,
111    /// `Malformed Auth Token` — invalid Auth Token serialization during
112    /// registration. See draft-11 section 8.2.1.1.
113    MalformedAuthToken = 0x10,
114    /// `Unknown Auth Token Alias` — the Authorization Token refers to an alias
115    /// that is not registered. See draft-11 section 8.2.1.1.
116    UnknownAuthTokenAlias = 0x11,
117    /// `Expired Auth Token` — the authorization token has expired. See draft-11
118    /// section 8.2.1.1.
119    ExpiredAuthToken = 0x12,
120}
121
122/// SUBSCRIBE_DONE status codes, from the table in draft-11 section 8.12.
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124#[repr(u64)]
125pub enum SubscribeDoneStatusCode {
126    /// `Internal Error` — an implementation specific or generic error occurred.
127    InternalError = 0x0,
128    /// `Unauthorized` — the subscriber is no longer authorized to subscribe to
129    /// the given track.
130    Unauthorized = 0x1,
131    /// `Track Ended` — the track is no longer being published.
132    TrackEnded = 0x2,
133    /// `Subscription Ended` — the publisher reached the end of an associated
134    /// Subscribe filter.
135    SubscriptionEnded = 0x3,
136    /// `Going Away` — the subscriber or publisher issued a GOAWAY message.
137    GoingAway = 0x4,
138    /// `Expired` — the publisher reached the timeout specified in SUBSCRIBE_OK.
139    Expired = 0x5,
140    /// `Too Far Behind` — the publisher's queue of objects to be sent to the
141    /// given subscriber exceeds its implementation defined limit.
142    TooFarBehind = 0x6,
143}
144
145/// FETCH_ERROR codes, from the table in draft-11 section 8.15.
146///
147/// The draft assigns 0x0 through 0x7 and then 0x10 through 0x12; 0x8 through
148/// 0xF are not assigned.
149#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150#[repr(u64)]
151pub enum FetchErrorCode {
152    /// `Internal Error` — an implementation specific or generic error occurred.
153    InternalError = 0x0,
154    /// `Unauthorized` — the subscriber is not authorized to fetch from the given
155    /// track.
156    Unauthorized = 0x1,
157    /// `Timeout` — the fetch could not be completed before an implementation
158    /// specific timeout. For example, a relay could not FETCH missing objects
159    /// within the timeout.
160    Timeout = 0x2,
161    /// `Not Supported` — the endpoint does not support the FETCH method.
162    NotSupported = 0x3,
163    /// `Track Does Not Exist` — the requested track is not available at the
164    /// publisher.
165    TrackDoesNotExist = 0x4,
166    /// `Invalid Range` — the end of the requested range is earlier than the
167    /// beginning, the start of the requested range is beyond the Largest
168    /// Object, or the track has not published any Objects yet.
169    InvalidRange = 0x5,
170    /// `No Objects` — no Objects exist between the requested Start and End
171    /// Locations.
172    NoObjects = 0x6,
173    /// `Invalid Joining Subscribe ID` — the joining Fetch referenced a Request
174    /// ID that did not belong to an active Subscription.
175    InvalidJoiningSubscribeId = 0x7,
176    /// `Malformed Auth Token` — invalid Auth Token serialization during
177    /// registration. See draft-11 section 8.2.1.1.
178    MalformedAuthToken = 0x10,
179    /// `Unknown Auth Token Alias` — the Authorization Token refers to an alias
180    /// that is not registered. See draft-11 section 8.2.1.1.
181    UnknownAuthTokenAlias = 0x11,
182    /// `Expired Auth Token` — the authorization token has expired. See draft-11
183    /// section 8.2.1.1.
184    ExpiredAuthToken = 0x12,
185}
186
187/// ANNOUNCE_ERROR codes, from the table in draft-11 section 8.21.
188///
189/// The draft assigns 0x0 through 0x4 and then 0x10 through 0x12; 0x5 through
190/// 0xF are not assigned.
191///
192/// These codes are also carried in the Error Code field of ANNOUNCE_CANCEL:
193/// draft-11 section 8.23 states that ANNOUNCE_CANCEL uses the same error codes
194/// as ANNOUNCE_ERROR, and defines no registry of its own.
195#[derive(Debug, Clone, Copy, PartialEq, Eq)]
196#[repr(u64)]
197pub enum AnnounceErrorCode {
198    /// `Internal Error` — an implementation specific or generic error occurred.
199    InternalError = 0x0,
200    /// `Unauthorized` — the subscriber is not authorized to announce the given
201    /// namespace.
202    Unauthorized = 0x1,
203    /// `Timeout` — the announce could not be completed before an implementation
204    /// specific timeout.
205    Timeout = 0x2,
206    /// `Not Supported` — the endpoint does not support the ANNOUNCE method.
207    NotSupported = 0x3,
208    /// `Uninterested` — the namespace is not of interest to the endpoint.
209    Uninterested = 0x4,
210    /// `Malformed Auth Token` — invalid Auth Token serialization during
211    /// registration. See draft-11 section 8.2.1.1.
212    MalformedAuthToken = 0x10,
213    /// `Unknown Auth Token Alias` — the Authorization Token refers to an alias
214    /// that is not registered. See draft-11 section 8.2.1.1.
215    UnknownAuthTokenAlias = 0x11,
216    /// `Expired Auth Token` — the authorization token has expired. See draft-11
217    /// section 8.2.1.1.
218    ExpiredAuthToken = 0x12,
219}
220
221/// SUBSCRIBE_ANNOUNCES_ERROR codes, from the table in draft-11 section 8.26.
222///
223/// The draft assigns 0x0 through 0x5 and then 0x10 through 0x12; 0x6 through
224/// 0xF are not assigned.
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226#[repr(u64)]
227pub enum SubscribeAnnouncesErrorCode {
228    /// `Internal Error` — an implementation specific or generic error occurred.
229    InternalError = 0x0,
230    /// `Unauthorized` — the subscriber is not authorized to subscribe to the
231    /// given namespace prefix.
232    Unauthorized = 0x1,
233    /// `Timeout` — the operation could not be completed before an
234    /// implementation specific timeout.
235    Timeout = 0x2,
236    /// `Not Supported` — the endpoint does not support the SUBSCRIBE_ANNOUNCES
237    /// method.
238    NotSupported = 0x3,
239    /// `Namespace Prefix Unknown` — the namespace prefix is not available for
240    /// subscription.
241    NamespacePrefixUnknown = 0x4,
242    /// `Namespace Prefix Overlap` — the namespace prefix overlaps with another
243    /// SUBSCRIBE_ANNOUNCES in the same session.
244    NamespacePrefixOverlap = 0x5,
245    /// `Malformed Auth Token` — invalid Auth Token serialization during
246    /// registration. See draft-11 section 8.2.1.1.
247    MalformedAuthToken = 0x10,
248    /// `Unknown Auth Token Alias` — the Authorization Token refers to an alias
249    /// that is not registered. See draft-11 section 8.2.1.1.
250    UnknownAuthTokenAlias = 0x11,
251    /// `Expired Auth Token` — the authorization token has expired. See draft-11
252    /// section 8.2.1.1.
253    ExpiredAuthToken = 0x12,
254}
255
256/// TRACK_STATUS status codes, carried in the Status Code field of the
257/// TRACK_STATUS message.
258///
259/// Draft-11 section 8.18 defines these as a prose list rather than as a
260/// `Code`/`Reason` table, which is why they are named from the prose here. The
261/// draft is stricter about this field than about the error registries above: it
262/// says the Status Code MUST hold one of these values and that any other value
263/// is a malformed message, so `from_u64` returning `None` is a decode failure
264/// rather than a merely unrecognised code.
265///
266/// The draft also carries an unresolved editorial note about authorization
267/// failures in this section, so a later draft may add codes here.
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269#[repr(u64)]
270pub enum TrackStatusCode {
271    /// The track is in progress, and subsequent fields contain the highest
272    /// group and object ID for that track.
273    InProgress = 0x00,
274    /// The track does not exist. Subsequent fields MUST be zero, and any other
275    /// value is a malformed message.
276    TrackDoesNotExist = 0x01,
277    /// The track has not yet begun. Subsequent fields MUST be zero, and any
278    /// other value is a malformed message.
279    NotYetBegun = 0x02,
280    /// The track has finished, so there is no live edge. Subsequent fields
281    /// contain the highest group and object ID known.
282    Finished = 0x03,
283    /// The publisher is a relay that cannot obtain the current track status
284    /// from upstream. Subsequent fields contain the largest group and object
285    /// ID known.
286    RelayStatusUnavailable = 0x04,
287}
288
289/// Data stream reset codes, from the table in draft-11 section 9.4.3 (Closing
290/// Subgroup Streams). Carried in RESET_STREAM and RESET_STREAM_AT.
291#[derive(Debug, Clone, Copy, PartialEq, Eq)]
292#[repr(u64)]
293pub enum StreamResetErrorCode {
294    /// `Internal Error` — an implementation specific error.
295    InternalError = 0x0,
296    /// `Cancelled` — the subscriber requested cancellation via UNSUBSCRIBE,
297    /// FETCH_CANCEL or STOP_SENDING, or the publisher ended the subscription,
298    /// in which case SUBSCRIBE_DONE will have a more detailed status code.
299    Cancelled = 0x1,
300    /// `Delivery Timeout` — the DELIVERY TIMEOUT was exceeded for this stream.
301    /// See draft-11 section 8.2.1.2.
302    DeliveryTimeout = 0x2,
303    /// `Session Closed` — the publisher session is being closed.
304    SessionClosed = 0x3,
305}
306
307impl SessionErrorCode {
308    /// Every session termination code draft-11 assigns, in ascending wire order.
309    ///
310    /// This is the set [`Self::from_u64`] accepts, written out so that it can
311    /// be enumerated: nothing can iterate an enum's variants, so a caller that
312    /// wants the registry has to be handed it. Writing it down is also what
313    /// lets a test state its claims about the registry itself rather than about
314    /// the range some sweep happens to reach.
315    pub const ALL: &[SessionErrorCode] = &[
316        SessionErrorCode::NoError,
317        SessionErrorCode::InternalError,
318        SessionErrorCode::Unauthorized,
319        SessionErrorCode::ProtocolViolation,
320        SessionErrorCode::InvalidRequestId,
321        SessionErrorCode::DuplicateTrackAlias,
322        SessionErrorCode::KeyValueFormattingError,
323        SessionErrorCode::TooManyRequests,
324        SessionErrorCode::InvalidPath,
325        SessionErrorCode::MalformedPath,
326        SessionErrorCode::GoawayTimeout,
327        SessionErrorCode::ControlMessageTimeout,
328        SessionErrorCode::DataStreamTimeout,
329        SessionErrorCode::AuthTokenCacheOverflow,
330        SessionErrorCode::DuplicateAuthTokenAlias,
331        SessionErrorCode::VersionNegotiationFailed,
332    ];
333
334    /// Convert a raw u64 to a `SessionErrorCode`, if valid.
335    pub fn from_u64(v: u64) -> Option<Self> {
336        match v {
337            0x0 => Some(SessionErrorCode::NoError),
338            0x1 => Some(SessionErrorCode::InternalError),
339            0x2 => Some(SessionErrorCode::Unauthorized),
340            0x3 => Some(SessionErrorCode::ProtocolViolation),
341            0x4 => Some(SessionErrorCode::InvalidRequestId),
342            0x5 => Some(SessionErrorCode::DuplicateTrackAlias),
343            0x6 => Some(SessionErrorCode::KeyValueFormattingError),
344            0x7 => Some(SessionErrorCode::TooManyRequests),
345            0x8 => Some(SessionErrorCode::InvalidPath),
346            0x9 => Some(SessionErrorCode::MalformedPath),
347            0x10 => Some(SessionErrorCode::GoawayTimeout),
348            0x11 => Some(SessionErrorCode::ControlMessageTimeout),
349            0x12 => Some(SessionErrorCode::DataStreamTimeout),
350            0x13 => Some(SessionErrorCode::AuthTokenCacheOverflow),
351            0x14 => Some(SessionErrorCode::DuplicateAuthTokenAlias),
352            0x15 => Some(SessionErrorCode::VersionNegotiationFailed),
353            _ => None,
354        }
355    }
356
357    /// Return the raw u64 value of this error code.
358    pub fn as_u64(self) -> u64 {
359        self as u64
360    }
361}
362
363impl SubscribeErrorCode {
364    /// Every SUBSCRIBE_ERROR code draft-11 assigns, in ascending wire order.
365    ///
366    /// This is the set [`Self::from_u64`] accepts, written out so that it can
367    /// be enumerated: nothing can iterate an enum's variants, so a caller that
368    /// wants the registry has to be handed it. Writing it down is also what
369    /// lets a test state its claims about the registry itself rather than about
370    /// the range some sweep happens to reach.
371    pub const ALL: &[SubscribeErrorCode] = &[
372        SubscribeErrorCode::InternalError,
373        SubscribeErrorCode::Unauthorized,
374        SubscribeErrorCode::Timeout,
375        SubscribeErrorCode::NotSupported,
376        SubscribeErrorCode::TrackDoesNotExist,
377        SubscribeErrorCode::InvalidRange,
378        SubscribeErrorCode::RetryTrackAlias,
379        SubscribeErrorCode::MalformedAuthToken,
380        SubscribeErrorCode::UnknownAuthTokenAlias,
381        SubscribeErrorCode::ExpiredAuthToken,
382    ];
383
384    /// Convert a raw u64 to a `SubscribeErrorCode`, if valid.
385    pub fn from_u64(v: u64) -> Option<Self> {
386        match v {
387            0x0 => Some(SubscribeErrorCode::InternalError),
388            0x1 => Some(SubscribeErrorCode::Unauthorized),
389            0x2 => Some(SubscribeErrorCode::Timeout),
390            0x3 => Some(SubscribeErrorCode::NotSupported),
391            0x4 => Some(SubscribeErrorCode::TrackDoesNotExist),
392            0x5 => Some(SubscribeErrorCode::InvalidRange),
393            0x6 => Some(SubscribeErrorCode::RetryTrackAlias),
394            0x10 => Some(SubscribeErrorCode::MalformedAuthToken),
395            0x11 => Some(SubscribeErrorCode::UnknownAuthTokenAlias),
396            0x12 => Some(SubscribeErrorCode::ExpiredAuthToken),
397            _ => None,
398        }
399    }
400
401    /// Return the raw u64 value of this error code.
402    pub fn as_u64(self) -> u64 {
403        self as u64
404    }
405}
406
407impl SubscribeDoneStatusCode {
408    /// Every SUBSCRIBE_DONE status code draft-11 assigns, in ascending wire order.
409    ///
410    /// This is the set [`Self::from_u64`] accepts, written out so that it can
411    /// be enumerated: nothing can iterate an enum's variants, so a caller that
412    /// wants the registry has to be handed it. Writing it down is also what
413    /// lets a test state its claims about the registry itself rather than about
414    /// the range some sweep happens to reach.
415    pub const ALL: &[SubscribeDoneStatusCode] = &[
416        SubscribeDoneStatusCode::InternalError,
417        SubscribeDoneStatusCode::Unauthorized,
418        SubscribeDoneStatusCode::TrackEnded,
419        SubscribeDoneStatusCode::SubscriptionEnded,
420        SubscribeDoneStatusCode::GoingAway,
421        SubscribeDoneStatusCode::Expired,
422        SubscribeDoneStatusCode::TooFarBehind,
423    ];
424
425    /// Convert a raw u64 to a `SubscribeDoneStatusCode`, if valid.
426    pub fn from_u64(v: u64) -> Option<Self> {
427        match v {
428            0x0 => Some(SubscribeDoneStatusCode::InternalError),
429            0x1 => Some(SubscribeDoneStatusCode::Unauthorized),
430            0x2 => Some(SubscribeDoneStatusCode::TrackEnded),
431            0x3 => Some(SubscribeDoneStatusCode::SubscriptionEnded),
432            0x4 => Some(SubscribeDoneStatusCode::GoingAway),
433            0x5 => Some(SubscribeDoneStatusCode::Expired),
434            0x6 => Some(SubscribeDoneStatusCode::TooFarBehind),
435            _ => None,
436        }
437    }
438
439    /// Return the raw u64 value of this status code.
440    pub fn as_u64(self) -> u64 {
441        self as u64
442    }
443}
444
445impl FetchErrorCode {
446    /// Every FETCH_ERROR code draft-11 assigns, in ascending wire order.
447    ///
448    /// This is the set [`Self::from_u64`] accepts, written out so that it can
449    /// be enumerated: nothing can iterate an enum's variants, so a caller that
450    /// wants the registry has to be handed it. Writing it down is also what
451    /// lets a test state its claims about the registry itself rather than about
452    /// the range some sweep happens to reach.
453    pub const ALL: &[FetchErrorCode] = &[
454        FetchErrorCode::InternalError,
455        FetchErrorCode::Unauthorized,
456        FetchErrorCode::Timeout,
457        FetchErrorCode::NotSupported,
458        FetchErrorCode::TrackDoesNotExist,
459        FetchErrorCode::InvalidRange,
460        FetchErrorCode::NoObjects,
461        FetchErrorCode::InvalidJoiningSubscribeId,
462        FetchErrorCode::MalformedAuthToken,
463        FetchErrorCode::UnknownAuthTokenAlias,
464        FetchErrorCode::ExpiredAuthToken,
465    ];
466
467    /// Convert a raw u64 to a `FetchErrorCode`, if valid.
468    pub fn from_u64(v: u64) -> Option<Self> {
469        match v {
470            0x0 => Some(FetchErrorCode::InternalError),
471            0x1 => Some(FetchErrorCode::Unauthorized),
472            0x2 => Some(FetchErrorCode::Timeout),
473            0x3 => Some(FetchErrorCode::NotSupported),
474            0x4 => Some(FetchErrorCode::TrackDoesNotExist),
475            0x5 => Some(FetchErrorCode::InvalidRange),
476            0x6 => Some(FetchErrorCode::NoObjects),
477            0x7 => Some(FetchErrorCode::InvalidJoiningSubscribeId),
478            0x10 => Some(FetchErrorCode::MalformedAuthToken),
479            0x11 => Some(FetchErrorCode::UnknownAuthTokenAlias),
480            0x12 => Some(FetchErrorCode::ExpiredAuthToken),
481            _ => None,
482        }
483    }
484
485    /// Return the raw u64 value of this error code.
486    pub fn as_u64(self) -> u64 {
487        self as u64
488    }
489}
490
491impl AnnounceErrorCode {
492    /// Every ANNOUNCE_ERROR code draft-11 assigns, in ascending wire order.
493    ///
494    /// This is the set [`Self::from_u64`] accepts, written out so that it can
495    /// be enumerated: nothing can iterate an enum's variants, so a caller that
496    /// wants the registry has to be handed it. Writing it down is also what
497    /// lets a test state its claims about the registry itself rather than about
498    /// the range some sweep happens to reach.
499    pub const ALL: &[AnnounceErrorCode] = &[
500        AnnounceErrorCode::InternalError,
501        AnnounceErrorCode::Unauthorized,
502        AnnounceErrorCode::Timeout,
503        AnnounceErrorCode::NotSupported,
504        AnnounceErrorCode::Uninterested,
505        AnnounceErrorCode::MalformedAuthToken,
506        AnnounceErrorCode::UnknownAuthTokenAlias,
507        AnnounceErrorCode::ExpiredAuthToken,
508    ];
509
510    /// Convert a raw u64 to an `AnnounceErrorCode`, if valid.
511    pub fn from_u64(v: u64) -> Option<Self> {
512        match v {
513            0x0 => Some(AnnounceErrorCode::InternalError),
514            0x1 => Some(AnnounceErrorCode::Unauthorized),
515            0x2 => Some(AnnounceErrorCode::Timeout),
516            0x3 => Some(AnnounceErrorCode::NotSupported),
517            0x4 => Some(AnnounceErrorCode::Uninterested),
518            0x10 => Some(AnnounceErrorCode::MalformedAuthToken),
519            0x11 => Some(AnnounceErrorCode::UnknownAuthTokenAlias),
520            0x12 => Some(AnnounceErrorCode::ExpiredAuthToken),
521            _ => None,
522        }
523    }
524
525    /// Return the raw u64 value of this error code.
526    pub fn as_u64(self) -> u64 {
527        self as u64
528    }
529}
530
531impl SubscribeAnnouncesErrorCode {
532    /// Every SUBSCRIBE_ANNOUNCES_ERROR code draft-11 assigns, in ascending wire order.
533    ///
534    /// This is the set [`Self::from_u64`] accepts, written out so that it can
535    /// be enumerated: nothing can iterate an enum's variants, so a caller that
536    /// wants the registry has to be handed it. Writing it down is also what
537    /// lets a test state its claims about the registry itself rather than about
538    /// the range some sweep happens to reach.
539    pub const ALL: &[SubscribeAnnouncesErrorCode] = &[
540        SubscribeAnnouncesErrorCode::InternalError,
541        SubscribeAnnouncesErrorCode::Unauthorized,
542        SubscribeAnnouncesErrorCode::Timeout,
543        SubscribeAnnouncesErrorCode::NotSupported,
544        SubscribeAnnouncesErrorCode::NamespacePrefixUnknown,
545        SubscribeAnnouncesErrorCode::NamespacePrefixOverlap,
546        SubscribeAnnouncesErrorCode::MalformedAuthToken,
547        SubscribeAnnouncesErrorCode::UnknownAuthTokenAlias,
548        SubscribeAnnouncesErrorCode::ExpiredAuthToken,
549    ];
550
551    /// Convert a raw u64 to a `SubscribeAnnouncesErrorCode`, if valid.
552    pub fn from_u64(v: u64) -> Option<Self> {
553        match v {
554            0x0 => Some(SubscribeAnnouncesErrorCode::InternalError),
555            0x1 => Some(SubscribeAnnouncesErrorCode::Unauthorized),
556            0x2 => Some(SubscribeAnnouncesErrorCode::Timeout),
557            0x3 => Some(SubscribeAnnouncesErrorCode::NotSupported),
558            0x4 => Some(SubscribeAnnouncesErrorCode::NamespacePrefixUnknown),
559            0x5 => Some(SubscribeAnnouncesErrorCode::NamespacePrefixOverlap),
560            0x10 => Some(SubscribeAnnouncesErrorCode::MalformedAuthToken),
561            0x11 => Some(SubscribeAnnouncesErrorCode::UnknownAuthTokenAlias),
562            0x12 => Some(SubscribeAnnouncesErrorCode::ExpiredAuthToken),
563            _ => None,
564        }
565    }
566
567    /// Return the raw u64 value of this error code.
568    pub fn as_u64(self) -> u64 {
569        self as u64
570    }
571}
572
573impl TrackStatusCode {
574    /// Convert a raw u64 to a `TrackStatusCode`, if valid.
575    pub fn from_u64(v: u64) -> Option<Self> {
576        match v {
577            0x00 => Some(TrackStatusCode::InProgress),
578            0x01 => Some(TrackStatusCode::TrackDoesNotExist),
579            0x02 => Some(TrackStatusCode::NotYetBegun),
580            0x03 => Some(TrackStatusCode::Finished),
581            0x04 => Some(TrackStatusCode::RelayStatusUnavailable),
582            _ => None,
583        }
584    }
585
586    /// Whether this code requires the fields after it to be zero.
587    ///
588    /// Section 8.18 says of 0x01 "Subsequent fields MUST be zero, and any other
589    /// value is a malformed message", and the same of 0x02. The other three
590    /// codes describe those fields as carrying a real location, so they place
591    /// no requirement on them.
592    pub fn requires_zero_location(self) -> bool {
593        matches!(self, TrackStatusCode::TrackDoesNotExist | TrackStatusCode::NotYetBegun)
594    }
595
596    /// Return the raw u64 value of this status code.
597    pub fn as_u64(self) -> u64 {
598        self as u64
599    }
600}
601
602impl StreamResetErrorCode {
603    /// Every subgroup stream reset code draft-11 assigns, in ascending wire order.
604    ///
605    /// This is the set [`Self::from_u64`] accepts, written out so that it can
606    /// be enumerated: nothing can iterate an enum's variants, so a caller that
607    /// wants the registry has to be handed it. Writing it down is also what
608    /// lets a test state its claims about the registry itself rather than about
609    /// the range some sweep happens to reach.
610    pub const ALL: &[StreamResetErrorCode] = &[
611        StreamResetErrorCode::InternalError,
612        StreamResetErrorCode::Cancelled,
613        StreamResetErrorCode::DeliveryTimeout,
614        StreamResetErrorCode::SessionClosed,
615    ];
616
617    /// Convert a raw u64 to a `StreamResetErrorCode`, if valid.
618    pub fn from_u64(v: u64) -> Option<Self> {
619        match v {
620            0x0 => Some(StreamResetErrorCode::InternalError),
621            0x1 => Some(StreamResetErrorCode::Cancelled),
622            0x2 => Some(StreamResetErrorCode::DeliveryTimeout),
623            0x3 => Some(StreamResetErrorCode::SessionClosed),
624            _ => None,
625        }
626    }
627
628    /// Return the raw u64 value of this error code.
629    pub fn as_u64(self) -> u64 {
630        self as u64
631    }
632}