Repository: bytebeamio/rumqtt (language: rust)

Issue:
rumqttc examples | Payload (de)serialization
I've been struggling to serialize (`Vec<u8>`) and deserialize (`Bytes`) a struct into a valid MQTT `payload` since I just recently started using Rust and this library (great, but I'm not an expert).

Can we include an easy example demonstrating how to serialize and deserialize a struct into a valid MQTT payload?

What follows can be a good place to start ([`bincode`](https://crates.io/crates/bincode) + [`serde`](https://crates.io/crates/serde))?

```rust
use rumqttc::Incoming;
use rumqttc::{Client, Event, MqttOptions, QoS};
use serde::{Deserialize, Serialize};
use std::thread;
use std::time::{Duration, SystemTime};

#[derive(Serialize, Deserialize, Debug)]
struct Message {
    i: usize,
    time: SystemTime,
}

impl From<&[u8]> for Message {
    fn from(value: &[u8]) -> Self {
        bincode::deserialize(value).unwrap()
    }
}

impl From<Message> for Vec<u8> {
    fn from(value: Message) -> Self {
        bincode::serialize(&value).unwrap()
    }
}

fn main() {
    let mqqt_opts = MqttOptions::new("ciao", "localhost", 1883);

    let (mut client, mut connection) = Client::new(mqqt_opts, 10);
    client.subscribe("hello/rumqtt", QoS::AtMostOnce).unwrap();
    thread::spawn(move || {
        for i in 0..10 {
            let message = Message {
                i,
                time: SystemTime::now(),
            };

            client
                .publish("hello/rumqtt", QoS::AtLeastOnce, false, message)
                .unwrap();
            thread::sleep(Duration::from_millis(100));
        }
    });

    // Iterate to poll the eventloop for connection progress
    for notification in connection.iter() {
        if let Event::Incoming(Incoming::Publish(message)) = notification.unwrap() {
            let message: Message = message.payload.as_ref().into();
            println!("Payload = {:?}", message);
        }
    }
}
```


Discussion / hints:
@carlocorradini Sure, that example looks good. Would you like to make a contribution or should I add it for you :)

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 2f89ae615..2a796b393 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -271,6 +271,15 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "bitflags"
 version = "1.3.2"
@@ -1956,6 +1965,7 @@ version = "0.21.0"
 dependencies = [
  "async-http-proxy",
  "async-tungstenite",
+ "bincode",
  "bytes",
  "color-backtrace",
  "flume",
diff --git a/rumqttc/Cargo.toml b/rumqttc/Cargo.toml
index 4da29ccf7..28c55d2f7 100644
--- a/rumqttc/Cargo.toml
+++ b/rumqttc/Cargo.toml
@@ -47,6 +47,7 @@ url = { version = "2", default-features = false, optional = true }
 async-http-proxy = { version = "1.2.5", features = ["runtime-tokio", "basic-auth"], optional = true }
 
 [dev-dependencies]
+bincode = "1.3.3"
 color-backtrace = "0.4"
 matches = "0.1"
 pretty_assertions = "1"
diff --git a/rumqttc/examples/serde.rs b/rumqttc/examples/serde.rs
new file mode 100644
index 000000000..a72cafb74
--- /dev/null
+++ b/rumqttc/examples/serde.rs
@@ -0,0 +1,62 @@
+use bincode::ErrorKind;
+use rumqttc::{Client, Event, Incoming, MqttOptions, QoS};
+use serde::{Deserialize, Serialize};
+use std::convert::TryFrom;
+use std::thread;
+use std::time::{Duration, SystemTime};
+
+#[derive(Serialize, Deserialize, Debug)]
+struct Message {
+    i: usize,
+    time: SystemTime,
+}
+
+impl From<&Message> for Vec<u8> {
+    fn from(value: &Message) -> Self {
+        bincode::serialize(value).unwrap()
+    }
+}
+
+impl From<Message> for Vec<u8> {
+    fn from(value: Message) -> Self {
+        bincode::serialize(&value).unwrap()
+    }
+}
+
+impl TryFrom<&[u8]> for Message {
+    type Error = Box<ErrorKind>;
+
+    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+        bincode::deserialize(value)
+    }
+}
+
+fn main() {
+    let mqqt_opts = MqttOptions::new("test-1", "localhost", 1883);
+
+    let (mut client, mut connection) = Client::new(mqqt_opts, 10);
+    client.subscribe("hello/rumqtt", QoS::AtMostOnce).unwrap();
+    thread::spawn(move || {
+        for i in 0..10 {
+            let message = Message {
+                i,
+                time: SystemTime::now(),
+            };
+
+            client
+                .publish("hello/rumqtt", QoS::AtLeastOnce, false, message)
+                .unwrap();
+            thread::sleep(Duration::from_millis(100));
+        }
+    });
+
+    // Iterate to poll the eventloop for connection progress
+    for notification in connection.iter() {
+        if let Ok(Event::Incoming(Incoming::Publish(packet))) = notification {
+            match Message::try_from(packet.payload.as_ref()) {
+                Ok(message) => println!("Payload = {message:?}"),
+                Err(error) => println!("Error = {error}"),
+            }
+        }
+    }
+}


Test patch: