I've been building mqtt-typed-client, a type-safe async MQTT client that sits
on top of rumqttc. The idea is to stop hand-writing format!() for outgoing
topics and split('/') + serde_json::from_slice for incoming ones, and declare
the topic shape once instead.
You describe a topic as a struct:
#[mqtt_topic("sensors/{location}/{sensor_id}/temperature")]
struct TemperatureTopic {
location: String,
sensor_id: u32,
payload: SensorData,
}
and the macro generates the typed publish/subscribe for it. You get a client
method with autocomplete, and the subscriber hands back the {params} already
pulled out of the topic:
client.temperature_topic().publish("kitchen", 42, &data).await?;
let mut sub = client.temperature_topic().subscribe().await?;
while let Some(Ok(msg)) = sub.receive().await {
// msg.location, msg.sensor_id, msg.payload: typed, no parsing
}
Parameters round-trip through Display/FromStr, so {sensor_id} can be a u32
instead of always a String, and a bad parse becomes a typed error in the
stream rather than a panic. Incoming messages are routed to the right
subscriber through a topic-matching tree, not a chain of starts_with checks.
It's a layer over rumqttc, not a replacement. If you need full manual
control of the event loop, use rumqttc directly. Serializers for
bincode/JSON/MessagePack/CBOR are behind feature flags.
I wrote up the before/after, and where a typed layer just gets in your way, in this blog post.
Repo: github.com/holovskyi/mqtt-typed-client
Docs: docs.rs/mqtt-typed-client
Some context, since it probably explains the type-obsession: I spent years in OCaml/F#, then a decade away from code. Rust plus LLMs are what got me back in the saddle. I use them to relearn the ecosystem and as a rubber duck for design.
Feedback welcome, especially on where the typed layer gets in your way.
1 post - 1 participant
Read full topic
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Maplike - Crate with traits for abstract containers and operations on them | 2 | 7 | 06-07-2026 |
| 2 | [Project Announcement] tinyxml2-rs: A high-performance, drop-in Rust implementation of TinyXML2 | 5 | 7 | 01-07-2026 |
| 3 | Looking for contributors: Rust transparent proxy & protocol parsing project | 5 | 7 | 08-07-2026 |
| 4 | I wrote my M.Sc. thesis on using the Rust type system in 3D graphics | 0 | 7 | 29-06-2026 |
| 5 | Focused library for parsing and formatting ASNs | 0 | 5 | 08-07-2026 |
| 6 | BloomCraft: twelve Bloom filter variants under one API, looking for feedback | 5 | 6 | 06-07-2026 |
| 7 | Show and tell : TRAINS: a leaderless, formally-verified total-order broadcast — \~2,400 lines of Rust, checked seven ways | 7 | 8 | 01-07-2026 |
| 8 | Test That! 0.5: A powerful test assertion library for Rust | 5 | 7 | 28-06-2026 |
| 9 | Chainything : A DAG-based pipeline execution engine & visual UI (with AI generation) | 2 | 7 | 29-06-2026 |
| 10 | CPUX - retained-mode GUI framework | 0 | 5 | 01-07-2026 |