Repository: quartiq/minimq
Pull request #169 (2025-01-22 14:41:23)

pub: respond default topic


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10f89ca..c1495dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ This document describes the changes to Minimq between releases.
 ## Changed
 * The `Publication::finish()` API was removed in favor of a new `Publication::respond()` API for
 constructing replies to previously received messages.
+* `DeferredPublication` has been removed: pass a `FnOnce(&mut [u8])` as payload.
 * [breaking] `embedded-nal` bumped. Now `core::net::SocketAddr` and related ip types are used.
   MSRV becomes 1.77.0.
 
diff --git a/src/lib.rs b/src/lib.rs
index 2c8a5b2..dee9a79 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -81,7 +81,7 @@ mod will;
 pub use broker::Broker;
 pub use config::ConfigBuilder;
 pub use properties::Property;
-pub use publication::{DeferredPublication, Publication};
+pub use publication::Publication;
 pub use reason_codes::ReasonCode;
 pub use will::Will;
 
diff --git a/src/publication.rs b/src/publication.rs
index e123f6e..f372d57 100644
--- a/src/publication.rs
+++ b/src/publication.rs
@@ -9,7 +9,7 @@ pub trait ToPayload {
     fn serialize(self, buffer: &mut [u8]) -> Result<usize, Self::Error>;
 }
 
-impl<'a> ToPayload for &'a [u8] {
+impl ToPayload for &[u8] {
     type Error = ();
 
     fn serialize(self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
@@ -21,7 +21,7 @@ impl<'a> ToPayload for &'a [u8] {
     }
 }
 
-impl<'a> ToPayload for &'a str {
+impl ToPayload for &str {
     type Error = ();
 
     fn serialize(self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
@@ -37,33 +37,10 @@ impl<const N: usize> ToPayload for &[u8; N] {
     }
 }
 
-/// A publication where the payload is serialized directly into the transmission buffer in the
-/// future.
-///
-/// # Note
-/// This is "deferred" because the closure will only be called once the publication is actually
-/// sent.
-pub struct DeferredPublication<F> {
-    func: F,
-}
-
-impl<E, F: FnOnce(&mut [u8]) -> Result<usize, E>> DeferredPublication<F> {
-    pub fn new<'a>(topic: &'a str, func: F) -> Publication<'a, Self> {
-        Publication::new(topic, Self { func })
-    }
-
-    pub fn respond<'a>(
-        received_properties: &'a Properties<'a>,
-        func: F,
-    ) -> Result<Publication<'a, Self>, ProtocolError> {
-        Publication::respond(received_properties, Self { func })
-    }
-}
-
-impl<E, F: FnOnce(&mut [u8]) -> Result<usize, E>> ToPayload for DeferredPublication<F> {
+impl<E, F: FnOnce(&mut [u8]) -> Result<usize, E>> ToPayload for F {
     type Error = E;
     fn serialize(self, buffer: &mut [u8]) -> Result<usize, E> {
-        (self.func)(buffer)
+        self(buffer)
     }
 }
 
@@ -87,7 +64,7 @@ pub struct Publication<'a, P> {
     pub(crate) retain: Retain,
 }
 
-impl<'a, P: ToPayload> Publication<'a, P> {
+impl<'a, P> Publication<'a, P> {
     /// Generate the publication as a reply to some other received message.
     ///
     /// # Note
@@ -98,8 +75,9 @@ impl<'a, P: ToPayload> Publication<'a, P> {
     ///   publication properties.
     ///
     /// * If a response topic is identified, the message topic will be
-    ///   configured for it, which will override any previously-specified topic.
+    ///   configured for it, which will override the default topic.
     pub fn respond(
+        default_topic: Option<&'a str>,
         received_properties: &'a Properties<'a>,
         payload: P,
     ) -> Result<Self, ProtocolError> {
@@ -113,6 +91,7 @@ impl<'a, P: ToPayload> Publication<'a, P> {
                     None
                 }
             })
+            .or(default_topic)
             .ok_or(ProtocolError::NoTopic)?;
 
         let publication = Self::new(response_topic, payload);


Test patch:
diff --git a/tests/deferred_payload.rs b/tests/deferred_payload.rs
index b568fff..3536ebb 100644
--- a/tests/deferred_payload.rs
+++ b/tests/deferred_payload.rs
@@ -1,4 +1,4 @@
-use minimq::{DeferredPublication, Minimq, QoS};
+use minimq::{Minimq, Publication, QoS};
 
 use core::net::{IpAddr, Ipv4Addr};
 use std_embedded_time::StandardClock;
@@ -23,7 +23,7 @@ fn main() -> std::io::Result<()> {
 
     assert!(matches!(
         mqtt.client().publish(
-            DeferredPublication::new("data", |_buf| { Err("Oops!") }).qos(QoS::ExactlyOnce)
+            Publication::new("data", |_buf: &mut [u8]| Err("Oops!")).qos(QoS::ExactlyOnce)
         ),
         Err(minimq::PubError::Serialization("Oops!"))
     ));
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
index f2b1f2a..766446e 100644
--- a/tests/integration_test.rs
+++ b/tests/integration_test.rs
@@ -31,7 +31,7 @@ fn main() -> std::io::Result<()> {
             .poll(|client, topic, payload, properties| {
                 log::info!("{} < {}", topic, core::str::from_utf8(payload).unwrap());
 
-                if let Ok(response) = Publication::respond(properties, b"Pong") {
+                if let Ok(response) = Publication::respond(None, properties, b"Pong") {
                     client.publish(response).unwrap();
                 }