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.
Typed rather than a bare byte. The wire field is one octet with 256
values, and draft-18 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
impl DatagramHeader
Sourcepub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError>
pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError>
Decode the header and stop, leaving whatever follows it in buf.
A datagram’s payload has no length field — draft-18 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.” So the header alone cannot say how many bytes belong to the object, and this method deliberately does not try: the caller holds the transport datagram and the tail is theirs.
That makes it the wrong entry point for validating the object as a
whole. Use Self::decode_object when buf holds exactly one
datagram; it consumes the tail and can therefore refuse a payload the
framing forbids.
Refuses any Type value datagram_type_is_valid rejects before reading
anything after it, for the reason SubgroupHeader::decode gives: the
Type is what names the layout of everything behind it. Which refusal it
is comes from datagram_type_error, and a Type spelled in more than
one byte is refused first by wide_type_refusal, so a padding
datagram can be told from an unassigned one.
Sourcepub fn decode_object(buf: &mut impl Buf) -> Result<(Self, Vec<u8>), CodecError>
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-18
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.
The same refusal covers a status the draft forbids a payload to: an object marked End of Group or End of Track may not carry one, per Section 11.2.1.1’s “Any object with a status code other than zero MUST have an empty payload”.
Errors with CodecError::PayloadNotPermitted when bytes remain and
the header forbids them, naming which of the two rules refused them.
Sourcepub fn encode_checked(&self, buf: &mut impl BufMut) -> Result<(), CodecError>
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.
Draft-18 Section 11.3.1 puts the framing side plainly — “The STATUS bit (0x20) indicates whether the datagram contains an Object Status or Object Payload” — and Section 11.2.1.1 the conformance side: “Any object with a status code other than zero MUST have an empty payload.” Between them there is no datagram that carries a non-zero status and a payload, so the pair being refused here is not one this encoder merely declines to spell.
ObjectStatus::Normal with the bit clear is not that case and is
accepted. It is the status the encoding elides for every datagram that
carries a payload, so stating it asks for exactly the bytes leaving it
out asks for, and nothing is lost.
A type value Section 11.3.1 lists as invalid is refused here too, on the
same grounds: a receiver that follows the draft answers one with a
PROTOCOL_VIOLATION, so writing it costs the session and not merely the
datagram. The accepted set is the one Self::decode accepts.
Errors with CodecError::InvalidField on either, before any byte is
written, so a refused header leaves buf untouched. The status half is
the datagram counterpart of the rule
SubgroupObjectReader::write_object applies on a subgroup stream,
where the status and the payload share a wire position.
Sourcepub fn encode(&self, buf: &mut impl BufMut)
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. Prefer Self::encode_checked,
which refuses that combination instead of resolving it.
pub fn is_end_of_group(&self) -> bool
pub fn has_status(&self) -> bool
Sourcepub fn has_properties(&self) -> bool
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.
Sourcepub fn status(&self) -> ObjectStatus
pub fn status(&self) -> ObjectStatus
The object’s 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
the status of an object that carries a payload is
ObjectStatus::Normal — draft-18 Section 11.2.1.1: “Any object with a
status code other than zero MUST have an empty payload.”
Sourcepub fn properties_permitted(&self) -> bool
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-18 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 general 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.”
Section 11.3.1 then states it again for this carrier in terms of the two
bits, which is why Self::decode refuses the shape rather than merely
reporting it — see SubgroupObject::properties_permitted for why the
subgroup carrier is the other way round.
Sourcepub fn properties_block_well_formed(&self) -> bool
pub fn properties_block_well_formed(&self) -> bool
Whether the properties block is framed the way a datagram may frame it.
Draft-18 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.
Sourcepub fn permits_payload(&self) -> bool
pub fn permits_payload(&self) -> bool
Whether the bytes after this datagram’s header are allowed to exist.
Draft-18 Section 11.2.1.1: “Any object with a status code other than zero MUST have an empty payload.” Section 11.3.1 states the framing side of the same rule: “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.”
Both halves of the rule are here. The framing half comes first and is the stronger one: with the STATUS bit set there is no Object Payload field at all, so no status — Normal included — makes trailing bytes part of the object. Answering from the status alone would report that a status datagram carrying Normal may be followed by a payload, and the bytes behind it would reach the application as one.
The status half then covers the header that states a status its type
byte gives no room for: End of Group under a type byte with the STATUS
bit clear permits no payload either, which is why
Self::encode_checked refuses to write that pair rather than
silently dropping the status.
This is the one place the blanket status-and-payload rule is not already
satisfied by the framing. On a subgroup stream the status and the payload
share a wire position, so no frame can state both; a datagram’s payload is
whatever follows the header to the end of the transport datagram, which
Self::decode never sees and Self::decode_object does.
Trait Implementations§
Source§impl Clone for DatagramHeader
impl Clone for DatagramHeader
Source§fn clone(&self) -> DatagramHeader
fn clone(&self) -> DatagramHeader
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more