Skip to main content

DatagramHeader

Struct DatagramHeader 

Source
pub struct DatagramHeader {
    pub datagram_type: u8,
    pub track_alias: VarInt,
    pub group_id: VarInt,
    pub object_id: VarInt,
    pub publisher_priority: Option<u8>,
    pub properties: Vec<u8>,
    pub object_status: Option<ObjectStatus>,
}

Fields§

§datagram_type: u8§track_alias: VarInt§group_id: VarInt§object_id: VarInt§publisher_priority: Option<u8>§properties: Vec<u8>

Raw properties bytes, excluding the byte-length prefix that precedes them on the wire. Present only when datagram_type sets the PROPERTIES bit (0x01), and empty otherwise — the bit is what puts the block on the wire, so contents held here with the bit clear are not written.

Opaque: Self::encode re-emits the prefix and these bytes verbatim, and Self::decode copies them out the same way, so a datagram can be decoded and re-encoded without understanding what its properties mean. The block sits between the publisher priority and the status field, so leaving it out of the struct would put the status where the decoder looks for the properties length.

§object_status: Option<ObjectStatus>

The object’s status, carried on the wire only when datagram_type sets the STATUS bit (0x20): such a datagram holds a one-byte status code in place of a payload. None with the bit set is written as ObjectStatus::Normal; a status with the bit clear is not written at all, because the bit is what puts the field on the wire.

None is not “no status”: a datagram whose type leaves the STATUS bit clear carries a payload, and the status of an Object that carries a payload is ObjectStatus::Normal, the only row of the Object Status registry (draft-19 Section 15.9) permitting one. Self::status resolves the field either way.

Typed rather than a bare byte. The wire field is one octet with 256 values, and draft-19 Section 11.2.1.1 assigns three of them; the decoder refuses the other 253, and this type is that same refusal on the encode side — Self::encode is infallible precisely because a status it could not legally write cannot be built.

Implementations§

Source§

impl DatagramHeader

Source

pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError>

Decode a datagram header, Type field included.

A Type spelled in more than one byte is refused first, for the reason given on SubgroupHeader::decode.

Source

pub fn decode_object(buf: &mut impl Buf) -> Result<(Self, Vec<u8>), CodecError>

Decode one whole datagram: the header, then the payload that runs to the end of buf.

buf must hold exactly one transport datagram and nothing else, since that boundary is the only thing that delimits the payload — draft-19 Section 11.3.1: “There is no explicit length field for the Object Payload; the entirety of the transport datagram following the Object header contains the payload.”

Which is why the refusal lives here and not in Self::decode. A datagram whose type sets the STATUS bit has no payload at all — the same section: “When set to 1, the Object Status field is present and there is no Object Payload” — so trailing bytes after its status are not a short payload or an odd one, they are bytes the frame does not define. A decoder that stops at the header cannot see them, and a caller that treats whatever is left as the payload hands the application content the publisher never framed as content. That is the case this refuses, and it bites hardest on a status datagram carrying the Normal code 0x0, whose status alone would report a payload as permitted.

The same refusal covers a status the registry forbids a payload to, per Section 11.2.1.1 and the “Payload” column of Section 15.9.

Errors with CodecError::PayloadNotPermitted when bytes remain and the header forbids them, naming which of the two rules refused them.

Source

pub fn encode_checked(&self, buf: &mut impl BufMut) -> Result<(), CodecError>

Serialize the header, refusing a status the framing cannot carry.

A datagram states a status only when its type byte sets the STATUS bit (0x20). With the bit clear there is no status field on the wire, so an object_status of anything but ObjectStatus::Normal has nowhere to go: Self::encode drops it, and the datagram parses back as an ordinary payload object. An End of Group marker written that way does not arrive late or malformed — it does not arrive at all, and the receiver sees a normal object in its place.

ObjectStatus::Normal with the bit clear is not that case and is accepted. It is the status the encoding elides for every object that carries a payload, so stating it asks for exactly the bytes leaving it out asks for, and nothing is lost.

Errors with CodecError::InvalidField on the lossy combination, before any byte is written, so a refused header leaves buf untouched. This is the datagram half of the rule SubgroupObjectReader::write_object applies on a subgroup stream.

Also errors with CodecError::InvalidField for a Type value draft-19 Section 11.3.1 lists as invalid, and for the same reason: a datagram written with one could not be read back by Self::decode, and a codec whose two halves disagree about which datagrams exist cannot be used to rewrite captured traffic.

Source

pub fn encode(&self, buf: &mut impl BufMut)

Serialize the header exactly as its type byte describes it.

Every field the type byte announces is written, in the order Self::decode reads them, so the bytes this produces always parse back. The properties block in particular has to be written here: it sits ahead of the status field, and a datagram that skipped it would offer the status byte where the decoder reads the block’s length.

The type byte is taken as the authority on framing, which is what makes this infallible — and what makes it lossy when the struct disagrees with itself. An object_status set while the type byte leaves the STATUS bit clear is discarded here without a word, and a Type value draft-19 forbids is written out as readily as one it assigns, including Types this module’s own Self::decode refuses. Prefer Self::encode_checked, which refuses both instead of resolving them.

Source

pub fn is_end_of_group(&self) -> bool

Source

pub fn has_status(&self) -> bool

Source

pub fn has_properties(&self) -> bool

true when the type byte sets the PROPERTIES bit (0x01), which is what puts the properties block on the wire.

Reports the framing, not the contents. A decoded datagram with this set always has a non-empty Self::properties, because Self::decode refuses a zero-length block; a header built by hand can hold the two apart, and Self::encode_checked is what refuses that.

Source

pub fn status(&self) -> ObjectStatus

The datagram’s object status, with the one the encoding elides filled in.

A datagram states a status only when its type sets the STATUS bit, and such a datagram has no payload. One without the bit is all payload, and its status is ObjectStatus::Normal — the sole row of the Object Status registry (draft-19 Section 15.9) permitting a payload, so the only status it could have had.

Source

pub fn permits_payload(&self) -> bool

Whether the bytes after this datagram’s header are allowed to exist.

Two independent rules forbid them, and this reports both:

  • The framing. Draft-19 Section 11.3.1: “The STATUS bit (0x20) indicates whether the datagram contains an Object Status or Object Payload. When set to 1, the Object Status field is present and there is no Object Payload.” A datagram that states a status has no payload field at all, whichever status it states — so a STATUS datagram carrying the Normal code 0x0 has no more room for bytes than one carrying End of Group.
  • The status. Section 11.2.1.1 and the Object Status registry’s “Payload” column, Section 15.9: an Object has an empty payload unless its status is registered as permitting one. This half reaches a datagram whose type byte leaves the STATUS bit clear while the value claims a status that forbids a payload — a disagreement Self::encode_checked refuses to write, and one a decoded header never shows.

The first is the rule a decoded datagram can actually trip, and reading the registry alone misses it: Some(ObjectStatus::Normal) under a type byte with the STATUS bit set is exactly the case where the payload the draft says does not exist would otherwise be handed to the application as the object’s content, because Normal is the one status the registry marks as permitting a payload.

Distinct from Self::has_status, which reports how the datagram is framed rather than whether a payload may follow. A caller holding the bytes after the header wants this one; Self::decode_object applies it for a caller who would rather the decode simply fail.

Source

pub fn properties_permitted(&self) -> bool

Whether this datagram’s status is allowed to carry the properties it has.

The same rule the subgroup form obeys. Draft-19 Section 11.3.1 builds the datagram’s Properties field out of “the Object Properties structure defined in Section 11.2.1.2”, and that section is where the rule sits: “If an endpoint receives properties on an Object with status that is not Normal, it MUST close the session with a PROTOCOL_VIOLATION.”

See SubgroupObject::properties_permitted for why the decoder reports this instead of refusing it.

Source

pub fn properties_block_well_formed(&self) -> bool

Whether the properties block is framed the way a datagram may frame it.

Draft-19 Section 11.3.1: “If an endpoint receives a datagram with the PROPERTIES bit set and an Properties Length of 0, it MUST close the session with a PROTOCOL_VIOLATION.”

The bit and a zero length are two ways to spell “no properties”, and on a datagram they are not interchangeable: a datagram with none has a type byte that says so, and the block costs bytes the type byte already saved. This rule is the datagram’s alone. A subgroup stream says the opposite in Section 11.4.2 — “Objects with no properties set Properties Length to 0” — because there the PROPERTIES bit is fixed for the whole stream, so an object with no properties has nowhere else to say so and a zero-length block is the required spelling rather than a violation.

The mirror case is not a wire state but is a state this struct can hold: properties with the bit clear. Self::encode drops them without a word, so this reports that too, and Self::encode_checked refuses both.

Trait Implementations§

Source§

impl Clone for DatagramHeader

Source§

fn clone(&self) -> DatagramHeader

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DatagramHeader

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.