Crate mqtt_protocol_core

Source
Expand description

§MQTT Protocol Core

A Sans-I/O style MQTT protocol library for Rust that supports both MQTT v5.0 and v3.1.1.

This library provides a pure protocol implementation without any I/O operations, making it suitable for use with any async runtime or synchronous I/O framework. All operations are synchronous and the library focuses solely on MQTT protocol message parsing, validation, and generation.

§Features

  • Sans-I/O Design: Pure protocol implementation with no I/O dependencies
  • Dual Version Support: Full support for both MQTT v3.1.1 and v5.0
  • Generic Packet ID: Supports custom packet ID types (u16, u32) for broker clustering
  • Zero-Copy Payload: Efficient payload handling with ArcPayload
  • Comprehensive: All MQTT packet types and features supported
  • Type Safety: Compile-time role and version checking

§Quick Start

§Basic Client Connection

use mqtt_protocol_core::mqtt::{
    Connection, Version,
    connection::role::Client,
    packet::v5_0::Connect,
};

// Create a client connection for MQTT v5.0
let mut client = Connection::<Client>::new(Version::V5_0);

// Create a CONNECT packet
let connect = Connect::builder()
    .client_id("my-client")
    .unwrap()
    .clean_start(true)
    .build()
    .unwrap();

// Send the packet through the connection
let events = client.send(connect.into());

§Server with Version Auto-Detection

use mqtt_protocol_core::mqtt::{
    Connection, Version,
    connection::role::Server,
};

// Create a server that accepts any MQTT version
let mut server = Connection::<Server>::new(Version::Undetermined);

// The server will automatically adapt to the client's protocol version
// when it receives a CONNECT packet

§Architecture

The library is organized into several key modules:

§Sans-I/O Pattern

This library follows the Sans-I/O pattern, meaning it handles protocol logic without performing any I/O operations. Instead, it returns events that tell your application what actions to take:

use mqtt_protocol_core::mqtt::{
    Connection, Version,
    connection::{role::Client, event::GenericEvent},
    common::Cursor,
};

let mut client = Connection::<Client>::new(Version::V5_0);
let data = &[0u8; 0][..];
let mut data_cursor = Cursor::new(data);
let events = client.recv(&mut data_cursor);

for event in events {
    match event {
        GenericEvent::RequestSendPacket { packet, .. } => {
            // Send packet over network
        }
        GenericEvent::NotifyPacketReceived(packet) => {
            // Handle received packet
        }
        // ... other events
        _ => {}
    }
}

§Generic Packet ID Support

The library supports custom packet ID types for advanced use cases like broker clustering, where u32 packet IDs can prevent ID exhaustion:

use mqtt_protocol_core::mqtt::{GenericConnection, connection::role::Server};

// Use u32 packet IDs instead of standard u16
let mut server = GenericConnection::<Server, u32>::new(
    mqtt_protocol_core::mqtt::Version::V5_0
);

§No-std Support

This library fully supports no_std environments for embedded systems. To use in a no_std environment, disable the default std feature:

[dependencies]
mqtt-protocol-core = { version = "0.3.0", default-features = false }

No-std usage example:

#![no_std]
extern crate alloc;

use alloc::{vec::Vec, string::String};
use mqtt_protocol_core::mqtt::{
    Connection, Version,
    connection::role::Client,
    packet::v5_0::Connect,
    common::Cursor,
};

fn main() {
    // Create client connection
    let mut client = Connection::<Client>::new(Version::V5_0);

    // Create CONNECT packet
    let connect = Connect::builder()
        .client_id("embedded-client")
        .unwrap()
        .clean_start(true)
        .build()
        .unwrap();

    // Send packet and handle events
    let events = client.send(connect.into());

    // Process events in your embedded application
    for event in events {
        match event {
            // Handle RequestSendPacket, NotifyPacketReceived, etc.
            _ => {}
        }
    }
}

Key points for no-std usage:

  • Use extern crate alloc; to enable heap allocations
  • Import types from alloc crate instead of std
  • IoSlice functionality is not available in no_std mode

Modules§

logger
mqtt
prelude