GenericSuback

Struct GenericSuback 

Source
pub struct GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,
{ pub props: Properties, /* private fields */ }
Expand description

MQTT 5.0 SUBACK packet representation with generic packet ID support

The SUBACK packet is sent by the MQTT server (broker) in response to a SUBSCRIBE packet from a client. It indicates the maximum QoS level that was granted for each subscription or provides reason codes indicating why the subscription failed.

According to MQTT 5.0 specification, the SUBACK packet contains:

  • Fixed header with packet type and remaining length
  • Variable header with packet identifier, properties, and reason codes
  • No payload

§Packet Structure

SUBACK Packet Structure:
+----------------+
| Fixed Header   |  - Packet type (0x90) and remaining length
+----------------+
| Packet ID      |  - 2 bytes (or PacketIdType::Buffer size)
+----------------+
| Properties     |  - Property length + properties
+----------------+
| Reason Codes   |  - One or more reason codes (1 byte each)
+----------------+

§Reason Codes

Each reason code in the SUBACK packet corresponds to a topic filter in the original SUBSCRIBE packet and indicates the maximum QoS level granted or an error:

Success codes (QoS levels):

  • 0x00 Granted QoS 0 - Maximum QoS 0
  • 0x01 Granted QoS 1 - Maximum QoS 1
  • 0x02 Granted QoS 2 - Maximum QoS 2

Error codes:

  • 0x80 Unspecified error
  • 0x83 Implementation specific error
  • 0x87 Not authorized
  • 0x8F Topic filter invalid
  • 0x91 Packet identifier in use
  • 0x97 Quota exceeded
  • 0x9E Shared subscriptions not supported
  • 0xA1 Subscription identifiers not supported
  • 0xA2 Wildcard subscriptions not supported

§Properties

MQTT 5.0 SUBACK packets can include the following properties:

  • Reason String: Human readable string for diagnostic purposes
  • User Properties: Application-specific name-value pairs

Only one Reason String property is allowed per packet.

§Generic Packet ID Support

This implementation supports generic packet ID types through the PacketIdType parameter. While MQTT specification uses 16-bit packet IDs, this allows for extended packet IDs (e.g., 32-bit) for broker cluster implementations to prevent packet ID exhaustion.

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

// Create a SUBACK with successful subscriptions
let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![
        SubackReasonCode::GrantedQos1,
        SubackReasonCode::GrantedQos2,
    ])
    .build()
    .unwrap();

assert_eq!(suback.packet_id(), 42);
assert_eq!(suback.reason_codes().len(), 2);

// Create SUBACK with mixed success and error codes
let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(100u16)
    .reason_codes(vec![
        SubackReasonCode::GrantedQos1,
        SubackReasonCode::NotAuthorized,
        SubackReasonCode::TopicFilterInvalid,
    ])
    .build()
    .unwrap();

// Add properties for diagnostics
let mut props = mqtt::packet::Properties::new();
// props.add(mqtt::packet::Property::ReasonString("Partial success".to_string()));

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(200u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos0])
    .props(props)
    .build()
    .unwrap();

// Serialize to bytes for network transmission
let buffers = suback.to_buffers();

Fields§

§props: Properties

MQTT 5.0 properties for the SUBACK packet

Contains optional properties like reason string and user properties. The properties are validated to ensure only allowed properties are included.

Implementations§

Source§

impl<PacketIdType> GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Source

pub fn props(&self) -> &Properties

MQTT 5.0 properties for the SUBACK packet

Contains optional properties like reason string and user properties. The properties are validated to ensure only allowed properties are included.

Source§

impl<PacketIdType> GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Source

pub fn builder() -> GenericSubackBuilder<PacketIdType>

Create a new GenericSubackBuilder for constructing SUBACK packets

Returns a builder instance that allows setting the various fields of a SUBACK packet in a fluent interface style. The builder ensures all required fields are set before creating the final packet.

§Returns

A new GenericSubackBuilder<PacketIdType> instance

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::GenericSuback::<u16>::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();
Source

pub fn packet_type() -> PacketType

Get the packet type for SUBACK packets

Returns the constant packet type identifier for SUBACK packets. This is always PacketType::Suback for SUBACK packets.

§Returns

The packet type PacketType::Suback

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::packet::packet_type::PacketType;

assert_eq!(mqtt::packet::v5_0::Suback::packet_type(), PacketType::Suback);
Source

pub fn packet_id(&self) -> PacketIdType

Get the packet identifier from the SUBACK packet

Returns the packet identifier that matches the SUBSCRIBE packet this SUBACK is responding to. The packet identifier is used to correlate the SUBACK with the original SUBSCRIBE request.

§Returns

The packet identifier as PacketIdType

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(1234u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

assert_eq!(suback.packet_id(), 1234);
Source

pub fn reason_codes(&self) -> Vec<SubackReasonCode>

Get the reason codes from the SUBACK packet

Returns a vector of reason codes indicating the result of each subscription request in the original SUBSCRIBE packet. Each reason code corresponds to a topic filter in the SUBSCRIBE packet, in the same order.

Invalid reason code bytes are converted to SubackReasonCode::UnspecifiedError to maintain packet integrity.

§Returns

A Vec<SubackReasonCode> containing the subscription results

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![
        SubackReasonCode::GrantedQos1,
        SubackReasonCode::NotAuthorized,
        SubackReasonCode::GrantedQos0,
    ])
    .build()
    .unwrap();

let codes = suback.reason_codes();
assert_eq!(codes.len(), 3);
assert_eq!(codes[0], SubackReasonCode::GrantedQos1);
assert_eq!(codes[1], SubackReasonCode::NotAuthorized);
assert_eq!(codes[2], SubackReasonCode::GrantedQos0);
Source

pub fn parse(data: &[u8]) -> Result<(Self, usize), MqttError>

Parse a SUBACK packet from raw bytes

Parses the variable header and payload of a SUBACK packet from the provided byte buffer. The fixed header should already be parsed before calling this method.

§Parameters
  • data - The raw bytes containing the SUBACK packet variable header and payload
§Returns

Returns a tuple containing:

  • The parsed GenericSuback instance
  • The number of bytes consumed during parsing
§Errors

Returns MqttError if:

  • The packet is malformed (insufficient bytes, invalid packet ID, invalid reason codes)
  • The packet violates protocol rules (no reason codes provided)
  • Properties contain invalid or disallowed property types
  • Multiple Reason String properties are present
§Examples
use mqtt_protocol_core::mqtt;

// Parse SUBACK packet from network data
let data = &[0x00, 0x10, 0x00, 0x00]; // packet_id=16, no properties, granted QoS 0
let (suback, consumed) = mqtt::packet::v5_0::Suback::parse(data).unwrap();

assert_eq!(suback.packet_id(), 16);
assert_eq!(consumed, 4);
Source

pub fn size(&self) -> usize

Calculate the total size of the SUBACK packet in bytes

Returns the total number of bytes required to represent this SUBACK packet when serialized for network transmission. This includes the fixed header, variable header, and all reason codes.

§Returns

The total packet size in bytes

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

let size = suback.size();
assert!(size > 0);
Source

pub fn to_buffers(&self) -> Vec<IoSlice<'_>>

Convert the SUBACK packet to I/O buffers for efficient network transmission

Returns a vector of IoSlice references that can be used with vectored I/O operations for efficient network transmission without copying data. The buffers represent the complete SUBACK packet in wire format.

The returned buffers contain the packet in the following order:

  1. Fixed header (packet type and remaining length)
  2. Packet identifier
  3. Property length
  4. Properties (if any)
  5. Reason codes
§Returns

A Vec<IoSlice<'_>> containing references to the packet data

§Examples
use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

let buffers = suback.to_buffers();
// Use buffers for vectored I/O operations
// let bytes_written = socket.write_vectored(&buffers)?;
Source

pub fn to_continuous_buffer(&self) -> Vec<u8>

Create a continuous buffer containing the complete packet data

Returns a vector containing all packet bytes in a single continuous buffer. This method is compatible with no-std environments and provides an alternative to to_buffers() when vectored I/O is not needed.

The returned buffer contains the complete SUBACK packet serialized according to the MQTT v5.0 protocol specification, including fixed header, remaining length, packet identifier, properties, and reason codes.

§Returns

A vector containing the complete packet data

§Examples
use mqtt_protocol_core::mqtt;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(1u16)
    .build()
    .unwrap();

let buffer = suback.to_continuous_buffer();
// buffer contains all packet bytes

Trait Implementations§

Source§

impl<PacketIdType> Clone for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Clone, PacketIdType::Buffer: Clone,

Source§

fn clone(&self) -> GenericSuback<PacketIdType>

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<PacketIdType> Debug for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

Debug trait implementation for GenericSuback

Provides a debug representation of the SUBACK packet using the same JSON format as the Display trait. This ensures consistent output for logging and debugging.

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

println!("{:?}", suback); // Prints JSON representation
Source§

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

Formats the value using the given formatter. Read more
Source§

impl<PacketIdType> Display for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

Display trait implementation for GenericSuback

Provides a human-readable JSON representation of the SUBACK packet. The display format includes the packet type, packet ID, properties (if any), and reason codes.

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

println!("{}", suback); // Prints JSON representation
Source§

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

Formats the value using the given formatter. Read more
Source§

impl<PacketIdType> From<GenericSuback<PacketIdType>> for GenericPacket<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

Source§

fn from(v: GenericSuback<PacketIdType>) -> GenericPacket<PacketIdType>

Converts to this type from the input type.
Source§

impl<PacketIdType> GenericPacketDisplay for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

GenericPacketDisplay implementation for GenericSuback

Provides standardized display formatting for SUBACK packets through the GenericPacketDisplay trait. This allows consistent formatting across different packet types in the library.

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::packet::GenericPacketDisplay;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

// Use trait methods for consistent formatting
println!("{}", format_args!("{}", suback));
Source§

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

Source§

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

Source§

impl<PacketIdType> GenericPacketTrait for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

GenericPacketTrait implementation for GenericSuback

Provides the standard packet interface methods for SUBACK packets. This trait allows SUBACK packets to be used polymorphically with other MQTT packet types.

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::packet::GenericPacketTrait;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

// Use trait methods
let size = suback.size();
let buffers = suback.to_buffers();
Source§

fn size(&self) -> usize

Source§

fn to_buffers(&self) -> Vec<IoSlice<'_>>

Source§

fn to_continuous_buffer(&self) -> Vec<u8>

Create a continuous buffer containing the complete packet data Read more
Source§

impl<PacketIdType> PacketKind for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Source§

const IS_SUBACK: bool = true

true if this is a SUBACK packet
Source§

const IS_V5_0: bool = true

true if this is an MQTT v5.0 packet
Source§

const IS_CONNECT: bool = false

true if this is a CONNECT packet
Source§

const IS_CONNACK: bool = false

true if this is a CONNACK packet
Source§

const IS_PUBLISH: bool = false

true if this is a PUBLISH packet
Source§

const IS_PUBACK: bool = false

true if this is a PUBACK packet
Source§

const IS_PUBREC: bool = false

true if this is a PUBREC packet
Source§

const IS_PUBREL: bool = false

true if this is a PUBREL packet
Source§

const IS_PUBCOMP: bool = false

true if this is a PUBCOMP packet
Source§

const IS_SUBSCRIBE: bool = false

true if this is a SUBSCRIBE packet
Source§

const IS_UNSUBSCRIBE: bool = false

true if this is an UNSUBSCRIBE packet
Source§

const IS_UNSUBACK: bool = false

true if this is an UNSUBACK packet
Source§

const IS_PINGREQ: bool = false

true if this is a PINGREQ packet
Source§

const IS_PINGRESP: bool = false

true if this is a PINGRESP packet
Source§

const IS_DISCONNECT: bool = false

true if this is a DISCONNECT packet
Source§

const IS_AUTH: bool = false

true if this is an AUTH packet (v5.0 only)
Source§

const IS_V3_1_1: bool = false

true if this is an MQTT v3.1.1 packet
Source§

impl<PacketIdType> PartialEq for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + PartialEq, PacketIdType::Buffer: PartialEq,

Source§

fn eq(&self, other: &GenericSuback<PacketIdType>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<PacketIdType> Serialize for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

Serialize trait implementation for GenericSuback

Provides JSON serialization support for SUBACK packets. The serialized format includes the packet type, packet ID, properties (if any), and reason codes.

The serialized structure contains:

  • type: Always “suback”
  • packet_id: The packet identifier
  • props: Properties object (only if non-empty)
  • reason_codes: Array of reason codes (only if non-empty)

§Examples

use mqtt_protocol_core::mqtt;
use mqtt_protocol_core::mqtt::result_code::SubackReasonCode;

let suback = mqtt::packet::v5_0::Suback::builder()
    .packet_id(42u16)
    .reason_codes(vec![SubackReasonCode::GrantedQos1])
    .build()
    .unwrap();

let json = serde_json::to_string(&suback).unwrap();
// json contains: {"type":"suback","packet_id":42,"reason_codes":["GrantedQos1"]}
Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<PacketIdType> TryInto<GenericSuback<PacketIdType>> for GenericPacket<PacketIdType>
where PacketIdType: IsPacketId + Serialize,

Source§

type Error = &'static str

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

fn try_into( self, ) -> Result<GenericSuback<PacketIdType>, <Self as TryInto<GenericSuback<PacketIdType>>>::Error>

Performs the conversion.
Source§

impl<PacketIdType> Eq for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId + Eq, PacketIdType::Buffer: Eq,

Source§

impl<PacketIdType> SendableRole<Any> for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Source§

impl<PacketIdType> SendableRole<Server> for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Source§

impl<PacketIdType> StructuralPartialEq for GenericSuback<PacketIdType>
where PacketIdType: IsPacketId,

Auto Trait Implementations§

§

impl<PacketIdType> Freeze for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: Freeze,

§

impl<PacketIdType> RefUnwindSafe for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: RefUnwindSafe,

§

impl<PacketIdType> Send for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: Send,

§

impl<PacketIdType> Sync for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: Sync,

§

impl<PacketIdType> Unpin for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: Unpin,

§

impl<PacketIdType> UnwindSafe for GenericSuback<PacketIdType>
where <PacketIdType as IsPacketId>::Buffer: UnwindSafe,

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<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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<Role, PacketIdType, T> Sendable<Role, PacketIdType> for T
where Role: RoleType, PacketIdType: IsPacketId, T: SendableRole<Role> + SendableVersion + Display + Debug + PacketKind + SendableHelper<Role, PacketIdType>,

Source§

fn dispatch_send( self, connection: &mut GenericConnection<Role, PacketIdType>, ) -> Vec<GenericEvent<PacketIdType>>

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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

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

Source§

type Error = Infallible

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.