Skip to main content

moqtap_codec/draft18/
error_codes.rs

1//! Error and status code registries defined by MoQT draft-18.
2//!
3//! Draft-18 defines four such registries, all listed in Section 15.10 of the
4//! draft: Session Termination Error Codes, REQUEST_ERROR Codes, PUBLISH_DONE
5//! Codes and Stream Reset Error Codes. Each is transcribed below as one enum.
6//!
7//! All four registries reserve the code points matching `0x7f * N + 0x9D` for
8//! non-negative integer N (that is, 0x9D, 0x11C, ..., 0x3fffffffffffffde) for
9//! greasing, per Section 14 of the draft. A reserved range is not an assignment,
10//! so it gets no variant; `from_u64` reports those codes as unknown just like
11//! any other unassigned value.
12//!
13//! Every `from_u64` returns `None` for a code the draft does not assign. Peers
14//! are expected to send codes this draft does not define, and a decoder must
15//! survive them.
16//!
17//! Section 14 goes further than "must not fail" and states what an unknown code
18//! means: receipt of an unknown error code in any of these four contexts MUST be
19//! treated as equivalent to that context's `INTERNAL_ERROR`, and an endpoint MUST
20//! NOT close the session merely because a REQUEST_ERROR or PUBLISH_DONE carried
21//! an unknown code. `from_u64` deliberately does not apply that equivalence: it
22//! reports the code as unrecognized so the caller still knows what arrived on the
23//! wire. Substituting `INTERNAL_ERROR` is the caller's step, not the decoder's.
24
25/// Session Termination Error Codes (draft-18 Section 15.10.1).
26///
27/// These are the codes carried in the QUIC CONNECTION_CLOSE frame or the
28/// WebTransport CLOSE_WEBTRANSPORT_SESSION capsule that ends a MoQT session.
29/// The per-code definitions live in Section 3.5 of the draft.
30///
31/// Draft-18 assigns no 0x7 in this registry: the sequence runs 0x6 then 0x8.
32///
33/// The range `0x7f * N + 0x9D` is reserved for greasing and has no variant.
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35#[repr(u64)]
36pub enum SessionErrorCode {
37    /// `NO_ERROR` — The session is being terminated without an error.
38    NoError = 0x0,
39    /// `INTERNAL_ERROR` — An implementation specific error occurred.
40    InternalError = 0x1,
41    /// `UNAUTHORIZED` — The client is not authorized to establish a session.
42    Unauthorized = 0x2,
43    /// `PROTOCOL_VIOLATION` — The remote endpoint performed an action that was
44    /// disallowed by the specification.
45    ProtocolViolation = 0x3,
46    /// `INVALID_REQUEST_ID` — The endpoint received a Request ID with an
47    /// incorrect least significant bit for the sender, or a duplicate Request
48    /// ID. See Section 10.1.
49    InvalidRequestId = 0x4,
50    /// `DUPLICATE_TRACK_ALIAS` — The endpoint attempted to use a Track Alias
51    /// that was already in use.
52    DuplicateTrackAlias = 0x5,
53    /// `KEY_VALUE_FORMATTING_ERROR` — The key-value pair has a formatting
54    /// error.
55    KeyValueFormattingError = 0x6,
56    /// `INVALID_PATH` — The PATH parameter was used by a server, on a
57    /// WebTransport session, or the server does not support the path.
58    InvalidPath = 0x8,
59    /// `MALFORMED_PATH` — The PATH parameter does not conform to the rules in
60    /// Section 10.3.1.2.
61    MalformedPath = 0x9,
62    /// `GOAWAY_TIMEOUT` — The session was closed because the peer took too long
63    /// to close the session in response to a GOAWAY (Section 10.4) message. See
64    /// session migration (Section 3.6).
65    GoawayTimeout = 0x10,
66    /// `CONTROL_MESSAGE_TIMEOUT` — The session was closed because the peer took
67    /// too long to respond to a control message.
68    ControlMessageTimeout = 0x11,
69    /// `DATA_STREAM_TIMEOUT` — The session was closed because the peer took too
70    /// long to send data expected on an open Data Stream (see Section 11). This
71    /// includes fields of a stream header or an object header within a data
72    /// stream. If an endpoint times out waiting for a new object header on an
73    /// open subgroup stream, it MAY send a STOP_SENDING on that stream or
74    /// terminate the subscription.
75    DataStreamTimeout = 0x12,
76    /// `AUTH_TOKEN_CACHE_OVERFLOW` — The Session limit Section 10.3.1.3 of the
77    /// size of all registered Authorization tokens has been exceeded.
78    AuthTokenCacheOverflow = 0x13,
79    /// `DUPLICATE_AUTH_TOKEN_ALIAS` — Authorization Token attempted to register
80    /// an Alias that was in use (see Section 10.2.2).
81    DuplicateAuthTokenAlias = 0x14,
82    /// `VERSION_NEGOTIATION_FAILED` — The client didn't offer a version
83    /// supported by the server.
84    VersionNegotiationFailed = 0x15,
85    /// `MALFORMED_AUTH_TOKEN` — Invalid Auth Token serialization during
86    /// registration (see Section 10.2.2).
87    MalformedAuthToken = 0x16,
88    /// `UNKNOWN_AUTH_TOKEN_ALIAS` — No registered token found for the provided
89    /// Alias (see Section 10.2.2).
90    UnknownAuthTokenAlias = 0x17,
91    /// `EXPIRED_AUTH_TOKEN` — Authorization token has expired (Section 10.2.2).
92    ExpiredAuthToken = 0x18,
93    /// `INVALID_AUTHORITY` — The specified AUTHORITY does not correspond to
94    /// this server or cannot be used in this context.
95    InvalidAuthority = 0x19,
96    /// `MALFORMED_AUTHORITY` — The AUTHORITY value is syntactically invalid.
97    MalformedAuthority = 0x1A,
98}
99
100/// REQUEST_ERROR Codes (draft-18 Section 15.10.2).
101///
102/// These are the codes carried in the Error Code field of a REQUEST_ERROR
103/// message rejecting a request. The registry's Specification column points at
104/// Section 10.6, which is a one-sentence introduction; the per-code definitions
105/// are one level down, in Section 10.6.2 (REQUEST_ERROR Message Format).
106///
107/// One code changes the shape of the message: a REQUEST_ERROR carries a trailing
108/// Redirect structure only when the Error Code is `REDIRECT` (0x34).
109///
110/// The range `0x7f * N + 0x9D` is reserved for greasing and has no variant.
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112#[repr(u64)]
113pub enum RequestErrorCode {
114    /// `INTERNAL_ERROR` — An implementation specific or generic error occurred.
115    InternalError = 0x0,
116    /// `UNAUTHORIZED` — The subscriber is not authorized to perform the
117    /// requested action on the given track. This might be retryable if the
118    /// authorization token is not yet valid.
119    Unauthorized = 0x1,
120    /// `TIMEOUT` — The subscription could not be completed before an
121    /// implementation specific timeout. For example, a relay could not
122    /// establish an upstream subscription within the timeout.
123    Timeout = 0x2,
124    /// `NOT_SUPPORTED` — The endpoint does not support the type of request.
125    NotSupported = 0x3,
126    /// `MALFORMED_AUTH_TOKEN` — Invalid Auth Token serialization during
127    /// registration (see Section 10.2.2).
128    MalformedAuthToken = 0x4,
129    /// `EXPIRED_AUTH_TOKEN` — Authorization token has expired (Section 10.2.2).
130    ExpiredAuthToken = 0x5,
131    /// `GOING_AWAY` — The endpoint has received a GOAWAY and MAY reject new
132    /// requests.
133    GoingAway = 0x6,
134    /// `EXCESSIVE_LOAD` — The responder is overloaded and cannot process the
135    /// request at this time. The sender SHOULD use the Retry Interval to
136    /// indicate when the request can be retried.
137    ExcessiveLoad = 0x9,
138    /// `DOES_NOT_EXIST` — The track or namespace is not available at the
139    /// publisher.
140    DoesNotExist = 0x10,
141    /// `INVALID_RANGE` — In response to SUBSCRIBE or FETCH, specified Filter or
142    /// range of Locations cannot be satisfied.
143    InvalidRange = 0x11,
144    /// `MALFORMED_TRACK` — In response to a FETCH, a relay publisher detected
145    /// the track was malformed (see Section 2.4.2).
146    MalformedTrack = 0x12,
147    /// `DUPLICATE_SUBSCRIPTION` — The PUBLISH or SUBSCRIBE request attempted to
148    /// create a subscription to a Track with the same role as an existing
149    /// subscription.
150    DuplicateSubscription = 0x19,
151    /// `UNINTERESTED` — The subscriber is not interested in the track or
152    /// namespace.
153    Uninterested = 0x20,
154    /// `PREFIX_OVERLAP` — In response to SUBSCRIBE_NAMESPACE or
155    /// SUBSCRIBE_TRACKS, the namespace prefix shares a common prefix with
156    /// another subscription of the same type in the same session.
157    /// SUBSCRIBE_NAMESPACE and SUBSCRIBE_TRACKS have independent overlap
158    /// spaces, so a SUBSCRIBE_NAMESPACE and a SUBSCRIBE_TRACKS may share the
159    /// same prefix.
160    PrefixOverlap = 0x30,
161    /// `NAMESPACE_TOO_LARGE` — In response to SUBSCRIBE_NAMESPACE or
162    /// SUBSCRIBE_TRACKS, the namespace prefix matches more publishers than the
163    /// relay is willing to enumerate.
164    NamespaceTooLarge = 0x31,
165    /// `INVALID_JOINING_REQUEST_ID` — In response to a Joining FETCH, the
166    /// referenced Request ID is not an Established Subscription.
167    InvalidJoiningRequestId = 0x32,
168    /// `UNSUPPORTED_EXTENSION` — The track contains a Mandatory Track Property
169    /// (see Section 2.5.1) that the endpoint does not understand.
170    UnsupportedExtension = 0x33,
171    /// `REDIRECT` — The request cannot be fulfilled by this endpoint, but could
172    /// succeed at the location specified in the Redirect structure. The
173    /// requester SHOULD establish a new session to the provided URI (if
174    /// present) and retry the request using the Full Track Name from the
175    /// Redirect (if present). This error code can appear in response to
176    /// SUBSCRIBE, FETCH, TRACK_STATUS, PUBLISH_NAMESPACE and
177    /// SUBSCRIBE_NAMESPACE. Relays are not required to follow redirects from
178    /// upstream and MAY forward a REDIRECT response to matching downstream
179    /// requests. A relay MAY cache a REDIRECT response for a Full Track Name
180    /// for up to Retry Interval milliseconds and use it to respond to
181    /// subsequent matching requests without forwarding them upstream.
182    Redirect = 0x34,
183}
184
185/// PUBLISH_DONE Codes (draft-18 Section 15.10.3).
186///
187/// These are the status codes carried in a PUBLISH_DONE message ending a
188/// subscription. The per-code definitions live in Section 10.11 of the draft.
189///
190/// The range `0x7f * N + 0x9D` is reserved for greasing and has no variant.
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192#[repr(u64)]
193pub enum PublishDoneStatusCode {
194    /// `INTERNAL_ERROR` — An implementation specific or generic error occurred.
195    InternalError = 0x0,
196    /// `UNAUTHORIZED` — The subscriber is no longer authorized to subscribe to
197    /// the given track.
198    Unauthorized = 0x1,
199    /// `TRACK_ENDED` — The track is no longer being published.
200    TrackEnded = 0x2,
201    /// `SUBSCRIPTION_ENDED` — The publisher reached the end of an associated
202    /// subscription filter.
203    SubscriptionEnded = 0x3,
204    /// `GOING_AWAY` — The subscriber or publisher issued a GOAWAY message.
205    GoingAway = 0x4,
206    /// `TOO_FAR_BEHIND` — The publisher's queue of objects to be sent to the
207    /// given subscriber exceeds its implementation defined limit.
208    TooFarBehind = 0x5,
209    /// `EXPIRED` — The publisher reached the timeout specified in SUBSCRIBE_OK.
210    Expired = 0x6,
211    /// `UPDATE_FAILED` — REQUEST_UPDATE failed on this subscription (see
212    /// Section 10.9).
213    UpdateFailed = 0x8,
214    /// `EXCESSIVE_LOAD` — The publisher is overloaded and is terminating the
215    /// subscription.
216    ExcessiveLoad = 0x9,
217    /// `MALFORMED_TRACK` — A relay publisher detected that the track was
218    /// malformed (see Section 2.4.2).
219    MalformedTrack = 0x12,
220}
221
222/// Stream Reset Error Codes (draft-18 Section 15.10.4).
223///
224/// Section 3.3.3 asks the application to use a relevant code from this registry
225/// when resetting *or* when sending STOP_SENDING, on any stream. That is wider
226/// than the registry name suggests: Section 10 points here for resetting or
227/// STOP_SENDING a request (bidirectional) stream, and Section 11.4 points here
228/// for resetting a data stream. The per-code definitions are in Section 3.3.3.
229///
230/// The range `0x7f * N + 0x9D` is reserved for greasing and has no variant.
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
232#[repr(u64)]
233pub enum StreamResetErrorCode {
234    /// `INTERNAL_ERROR` — An implementation specific error.
235    InternalError = 0x0,
236    /// `CANCELLED` — The stream was cancelled by either endpoint. For
237    /// Subscriptions, PUBLISH_DONE (Section 10.11) may have a more detailed
238    /// status code.
239    Cancelled = 0x1,
240    /// `DELIVERY_TIMEOUT` — A delivery timeout (Section 8) was exceeded for
241    /// this stream.
242    DeliveryTimeout = 0x2,
243    /// `SESSION_CLOSED` — The session is being closed.
244    SessionClosed = 0x3,
245    /// `GOING_AWAY` — The endpoint is rejecting this request because it has
246    /// sent or received a GOAWAY.
247    GoingAway = 0x4,
248    /// `TOO_FAR_BEHIND` — The corresponding subscription has exceeded the
249    /// publisher's resource limits and is being terminated (see Section 8).
250    TooFarBehind = 0x5,
251    /// `UNKNOWN_OBJECT_STATUS` — In response to a FETCH, the publisher is
252    /// unable to determine the status of the next Object in the requested
253    /// range.
254    UnknownObjectStatus = 0x6,
255    /// `EXPIRED_AUTH_TOKEN` — The authorization token for the request has
256    /// expired.
257    ExpiredAuthToken = 0x7,
258    /// `EXCESSIVE_LOAD` — The endpoint is overloaded and is resetting this
259    /// stream.
260    ExcessiveLoad = 0x9,
261    /// `MALFORMED_TRACK` — A relay publisher detected that the track was
262    /// malformed (see Section 2.4.2).
263    MalformedTrack = 0x12,
264}
265
266impl SessionErrorCode {
267    /// Every Session Error Code draft-18 assigns, in ascending wire order.
268    ///
269    /// This is the set [`Self::from_u64`] accepts, written out so that it can
270    /// be enumerated: nothing can iterate an enum's variants, so a caller that
271    /// wants the registry has to be handed it. Writing it down is also what
272    /// lets a test state its claims about the registry itself rather than about
273    /// the range some sweep happens to reach — that this is the set `from_u64`
274    /// answers to, and that none of it lands in the range the draft reserves
275    /// for greasing.
276    pub const ALL: &[SessionErrorCode] = &[
277        SessionErrorCode::NoError,
278        SessionErrorCode::InternalError,
279        SessionErrorCode::Unauthorized,
280        SessionErrorCode::ProtocolViolation,
281        SessionErrorCode::InvalidRequestId,
282        SessionErrorCode::DuplicateTrackAlias,
283        SessionErrorCode::KeyValueFormattingError,
284        SessionErrorCode::InvalidPath,
285        SessionErrorCode::MalformedPath,
286        SessionErrorCode::GoawayTimeout,
287        SessionErrorCode::ControlMessageTimeout,
288        SessionErrorCode::DataStreamTimeout,
289        SessionErrorCode::AuthTokenCacheOverflow,
290        SessionErrorCode::DuplicateAuthTokenAlias,
291        SessionErrorCode::VersionNegotiationFailed,
292        SessionErrorCode::MalformedAuthToken,
293        SessionErrorCode::UnknownAuthTokenAlias,
294        SessionErrorCode::ExpiredAuthToken,
295        SessionErrorCode::InvalidAuthority,
296        SessionErrorCode::MalformedAuthority,
297    ];
298
299    /// Convert a raw u64 to a `SessionErrorCode`, if valid.
300    pub fn from_u64(v: u64) -> Option<Self> {
301        match v {
302            0x0 => Some(SessionErrorCode::NoError),
303            0x1 => Some(SessionErrorCode::InternalError),
304            0x2 => Some(SessionErrorCode::Unauthorized),
305            0x3 => Some(SessionErrorCode::ProtocolViolation),
306            0x4 => Some(SessionErrorCode::InvalidRequestId),
307            0x5 => Some(SessionErrorCode::DuplicateTrackAlias),
308            0x6 => Some(SessionErrorCode::KeyValueFormattingError),
309            0x8 => Some(SessionErrorCode::InvalidPath),
310            0x9 => Some(SessionErrorCode::MalformedPath),
311            0x10 => Some(SessionErrorCode::GoawayTimeout),
312            0x11 => Some(SessionErrorCode::ControlMessageTimeout),
313            0x12 => Some(SessionErrorCode::DataStreamTimeout),
314            0x13 => Some(SessionErrorCode::AuthTokenCacheOverflow),
315            0x14 => Some(SessionErrorCode::DuplicateAuthTokenAlias),
316            0x15 => Some(SessionErrorCode::VersionNegotiationFailed),
317            0x16 => Some(SessionErrorCode::MalformedAuthToken),
318            0x17 => Some(SessionErrorCode::UnknownAuthTokenAlias),
319            0x18 => Some(SessionErrorCode::ExpiredAuthToken),
320            0x19 => Some(SessionErrorCode::InvalidAuthority),
321            0x1A => Some(SessionErrorCode::MalformedAuthority),
322            _ => None,
323        }
324    }
325
326    /// Return the raw u64 value of this error code.
327    pub fn as_u64(self) -> u64 {
328        self as u64
329    }
330}
331
332impl RequestErrorCode {
333    /// Every Request Error Code draft-18 assigns, in ascending wire order.
334    ///
335    /// This is the set [`Self::from_u64`] accepts, written out so that it can
336    /// be enumerated: nothing can iterate an enum's variants, so a caller that
337    /// wants the registry has to be handed it. Writing it down is also what
338    /// lets a test state its claims about the registry itself rather than about
339    /// the range some sweep happens to reach — that this is the set `from_u64`
340    /// answers to, and that none of it lands in the range the draft reserves
341    /// for greasing.
342    pub const ALL: &[RequestErrorCode] = &[
343        RequestErrorCode::InternalError,
344        RequestErrorCode::Unauthorized,
345        RequestErrorCode::Timeout,
346        RequestErrorCode::NotSupported,
347        RequestErrorCode::MalformedAuthToken,
348        RequestErrorCode::ExpiredAuthToken,
349        RequestErrorCode::GoingAway,
350        RequestErrorCode::ExcessiveLoad,
351        RequestErrorCode::DoesNotExist,
352        RequestErrorCode::InvalidRange,
353        RequestErrorCode::MalformedTrack,
354        RequestErrorCode::DuplicateSubscription,
355        RequestErrorCode::Uninterested,
356        RequestErrorCode::PrefixOverlap,
357        RequestErrorCode::NamespaceTooLarge,
358        RequestErrorCode::InvalidJoiningRequestId,
359        RequestErrorCode::UnsupportedExtension,
360        RequestErrorCode::Redirect,
361    ];
362
363    /// Convert a raw u64 to a `RequestErrorCode`, if valid.
364    pub fn from_u64(v: u64) -> Option<Self> {
365        match v {
366            0x0 => Some(RequestErrorCode::InternalError),
367            0x1 => Some(RequestErrorCode::Unauthorized),
368            0x2 => Some(RequestErrorCode::Timeout),
369            0x3 => Some(RequestErrorCode::NotSupported),
370            0x4 => Some(RequestErrorCode::MalformedAuthToken),
371            0x5 => Some(RequestErrorCode::ExpiredAuthToken),
372            0x6 => Some(RequestErrorCode::GoingAway),
373            0x9 => Some(RequestErrorCode::ExcessiveLoad),
374            0x10 => Some(RequestErrorCode::DoesNotExist),
375            0x11 => Some(RequestErrorCode::InvalidRange),
376            0x12 => Some(RequestErrorCode::MalformedTrack),
377            0x19 => Some(RequestErrorCode::DuplicateSubscription),
378            0x20 => Some(RequestErrorCode::Uninterested),
379            0x30 => Some(RequestErrorCode::PrefixOverlap),
380            0x31 => Some(RequestErrorCode::NamespaceTooLarge),
381            0x32 => Some(RequestErrorCode::InvalidJoiningRequestId),
382            0x33 => Some(RequestErrorCode::UnsupportedExtension),
383            0x34 => Some(RequestErrorCode::Redirect),
384            _ => None,
385        }
386    }
387
388    /// Return the raw u64 value of this error code.
389    pub fn as_u64(self) -> u64 {
390        self as u64
391    }
392}
393
394impl PublishDoneStatusCode {
395    /// Every PUBLISH_DONE Status Code draft-18 assigns, in ascending wire order.
396    ///
397    /// This is the set [`Self::from_u64`] accepts, written out so that it can
398    /// be enumerated: nothing can iterate an enum's variants, so a caller that
399    /// wants the registry has to be handed it. Writing it down is also what
400    /// lets a test state its claims about the registry itself rather than about
401    /// the range some sweep happens to reach — that this is the set `from_u64`
402    /// answers to, and that none of it lands in the range the draft reserves
403    /// for greasing.
404    pub const ALL: &[PublishDoneStatusCode] = &[
405        PublishDoneStatusCode::InternalError,
406        PublishDoneStatusCode::Unauthorized,
407        PublishDoneStatusCode::TrackEnded,
408        PublishDoneStatusCode::SubscriptionEnded,
409        PublishDoneStatusCode::GoingAway,
410        PublishDoneStatusCode::TooFarBehind,
411        PublishDoneStatusCode::Expired,
412        PublishDoneStatusCode::UpdateFailed,
413        PublishDoneStatusCode::ExcessiveLoad,
414        PublishDoneStatusCode::MalformedTrack,
415    ];
416
417    /// Convert a raw u64 to a `PublishDoneStatusCode`, if valid.
418    pub fn from_u64(v: u64) -> Option<Self> {
419        match v {
420            0x0 => Some(PublishDoneStatusCode::InternalError),
421            0x1 => Some(PublishDoneStatusCode::Unauthorized),
422            0x2 => Some(PublishDoneStatusCode::TrackEnded),
423            0x3 => Some(PublishDoneStatusCode::SubscriptionEnded),
424            0x4 => Some(PublishDoneStatusCode::GoingAway),
425            0x5 => Some(PublishDoneStatusCode::TooFarBehind),
426            0x6 => Some(PublishDoneStatusCode::Expired),
427            0x8 => Some(PublishDoneStatusCode::UpdateFailed),
428            0x9 => Some(PublishDoneStatusCode::ExcessiveLoad),
429            0x12 => Some(PublishDoneStatusCode::MalformedTrack),
430            _ => None,
431        }
432    }
433
434    /// Return the raw u64 value of this status code.
435    pub fn as_u64(self) -> u64 {
436        self as u64
437    }
438}
439
440impl StreamResetErrorCode {
441    /// Every Stream Reset Error Code draft-18 assigns, in ascending wire order.
442    ///
443    /// This is the set [`Self::from_u64`] accepts, written out so that it can
444    /// be enumerated: nothing can iterate an enum's variants, so a caller that
445    /// wants the registry has to be handed it. Writing it down is also what
446    /// lets a test state its claims about the registry itself rather than about
447    /// the range some sweep happens to reach — that this is the set `from_u64`
448    /// answers to, and that none of it lands in the range the draft reserves
449    /// for greasing.
450    pub const ALL: &[StreamResetErrorCode] = &[
451        StreamResetErrorCode::InternalError,
452        StreamResetErrorCode::Cancelled,
453        StreamResetErrorCode::DeliveryTimeout,
454        StreamResetErrorCode::SessionClosed,
455        StreamResetErrorCode::GoingAway,
456        StreamResetErrorCode::TooFarBehind,
457        StreamResetErrorCode::UnknownObjectStatus,
458        StreamResetErrorCode::ExpiredAuthToken,
459        StreamResetErrorCode::ExcessiveLoad,
460        StreamResetErrorCode::MalformedTrack,
461    ];
462
463    /// Convert a raw u64 to a `StreamResetErrorCode`, if valid.
464    pub fn from_u64(v: u64) -> Option<Self> {
465        match v {
466            0x0 => Some(StreamResetErrorCode::InternalError),
467            0x1 => Some(StreamResetErrorCode::Cancelled),
468            0x2 => Some(StreamResetErrorCode::DeliveryTimeout),
469            0x3 => Some(StreamResetErrorCode::SessionClosed),
470            0x4 => Some(StreamResetErrorCode::GoingAway),
471            0x5 => Some(StreamResetErrorCode::TooFarBehind),
472            0x6 => Some(StreamResetErrorCode::UnknownObjectStatus),
473            0x7 => Some(StreamResetErrorCode::ExpiredAuthToken),
474            0x9 => Some(StreamResetErrorCode::ExcessiveLoad),
475            0x12 => Some(StreamResetErrorCode::MalformedTrack),
476            _ => None,
477        }
478    }
479
480    /// Return the raw u64 value of this error code.
481    pub fn as_u64(self) -> u64 {
482        self as u64
483    }
484}