rtp_packet/error.rs
1//! Error type for RTP fixed-header parsing/serialization.
2//!
3//! Field-by-field semantics are documented in the curated spec oracle,
4//! `rtp-packet/docs/rtp-header.md` (RFC 3550 §5.1 / §5.3.1).
5
6/// Result alias for `rtp-packet` parsing/serialization.
7pub type Result<T> = core::result::Result<T, Error>;
8
9/// An RTP header parse / serialize error.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
11#[non_exhaustive]
12pub enum Error {
13 /// Input (on parse) or output buffer (on serialize) shorter than required.
14 #[error("buffer too short: need {need}, have {have} ({what})")]
15 BufferTooShort {
16 /// Bytes required.
17 need: usize,
18 /// Bytes available.
19 have: usize,
20 /// What was being parsed/serialized.
21 what: &'static str,
22 },
23 /// The 2-bit `version` field was not `2` (RFC 3550 §5.1: "The version
24 /// defined by this specification is two (2)").
25 #[error("invalid RTP version: {0} (RFC 3550 §5.1 requires version 2)")]
26 InvalidVersion(u8),
27 /// A field value did not fit its wire bit-width, or a derived count (CSRC
28 /// list length, extension word count, padding octet count) overflowed its
29 /// field.
30 #[error("field {field} value {value} invalid: {reason}")]
31 InvalidValue {
32 /// The offending field/derived-count name.
33 field: &'static str,
34 /// The offending value.
35 value: u64,
36 /// Why it is invalid.
37 reason: &'static str,
38 },
39 /// The padding region (RFC 3550 §5.1) was malformed: either the trailing
40 /// count byte was zero, exceeded the bytes actually available, or (on
41 /// serialize) a supplied padding slice's last byte did not equal its own
42 /// length.
43 #[error("invalid padding: count {count} ({reason})")]
44 InvalidPadding {
45 /// The padding-count byte (the last byte of the padding region).
46 count: u8,
47 /// Why it is invalid.
48 reason: &'static str,
49 },
50 /// A header-extension `data` slice's length was not a multiple of 4 bytes
51 /// — RFC 3550 §5.3.1's `length` field counts whole 32-bit words.
52 #[error(
53 "header extension data length {data_len} is not a multiple of 4 bytes \
54 (RFC 3550 §5.3.1: length counts 32-bit words)"
55 )]
56 ExtensionNotWordAligned {
57 /// The offending `data.len()`.
58 data_len: usize,
59 },
60 /// (`rfc8285` feature) A [`HeaderExtension`](crate::HeaderExtension)'s
61 /// `profile_id` matched neither the RFC 8285 one-byte form (`0xBEDE`) nor
62 /// the two-byte form (`profile_id & 0xFFF0 == 0x1000`). This is **not** a
63 /// malformed-packet error: RFC 8285 interpretation of the RFC 3550
64 /// §5.3.1 opaque extension `data` is profile-scoped and opt-in, so an
65 /// extension with some other `profile_id` is simply not one this crate's
66 /// `rfc8285` decoder understands.
67 #[cfg(feature = "rfc8285")]
68 #[error(
69 "profile_id {profile_id:#06x} matches neither the RFC 8285 one-byte \
70 (0xBEDE) nor two-byte (0x1000-0x100F) header-extension form"
71 )]
72 NotRfc8285Extension {
73 /// The offending `HeaderExtension::profile_id`.
74 profile_id: u16,
75 },
76 /// (`rfc8285` feature) An RFC 8285 one-byte-form local identifier was
77 /// outside the valid `1..=14` range (§4.2: 0 is reserved for padding, 15
78 /// is reserved for a future extension / used as the "stop" marker).
79 #[cfg(feature = "rfc8285")]
80 #[error(
81 "invalid RFC 8285 one-byte extension element id {0} (valid range is 1..=14; \
82 0 is reserved for padding, 15 is reserved)"
83 )]
84 InvalidOneByteExtensionId(u8),
85 /// (`rfc8285` feature) An RFC 8285 two-byte-form local identifier was 0
86 /// (§4.1.2 / §5: "0 is reserved for padding in both forms").
87 #[cfg(feature = "rfc8285")]
88 #[error(
89 "invalid RFC 8285 two-byte extension element id 0 (reserved for padding \
90 in both forms, per RFC 8285 §4.1.2/§5)"
91 )]
92 InvalidTwoByteExtensionId,
93}