mqtt_tiny/packets/
mod.rs

1//! MQTT packet types
2
3use crate::error::DecoderError;
4
5pub mod connack;
6pub mod connect;
7pub mod packet;
8pub mod publish;
9pub mod subscribe;
10pub mod unsubscribe;
11include!("_ack.rs");
12include!("_signal.rs");
13
14/// Traits for elements that can be build from a byte iterator
15pub trait TryFromIterator
16where
17    Self: Sized,
18{
19    /// Tries to build `Self` from the given byte iterator
20    fn try_from_iter<T>(iter: T) -> Result<Self, DecoderError>
21    where
22        T: IntoIterator<Item = u8>;
23}
24
25/// Traits for elements that can be built from a byte reader
26#[cfg(feature = "std")]
27pub trait TryFromReader
28where
29    Self: Sized,
30{
31    /// Tries to build `Self` from the given byte iterator
32    fn try_read<T>(reader: T) -> Result<Self, std::io::Error>
33    where
34        T: std::io::Read;
35}
36#[cfg(feature = "std")]
37impl<T> TryFromReader for T
38where
39    T: TryFromIterator,
40{
41    #[allow(clippy::unbuffered_bytes, reason = "implementors may pass a buffered reader if appropriate")]
42    fn try_read<R>(reader: R) -> Result<Self, std::io::Error>
43    where
44        R: std::io::Read,
45    {
46        use crate::error::Decoding;
47        use std::io::{Error, ErrorKind};
48
49        // Create a byte iterator from the reader
50        let mut last_error = None;
51        let iter = reader.bytes()
52            // Retain an I/O error if any
53            .map(|result| result.map_err(|e| last_error = Some(e)))
54            // Yield bytes as long as there is not an error
55            .map_while(|result| result.ok());
56
57        // Try to build `Self` from iterator
58        match (Self::try_from_iter(iter), last_error) {
59            (Ok(value), _) => Ok(value),
60            (Err(_), Some(e)) => Err(e),
61            (Err(e), _) => match e.variant {
62                // Map error to an appropriate I/O error kind
63                Decoding::Truncated => Err(Error::new(ErrorKind::UnexpectedEof, e)),
64                Decoding::SpecViolation => Err(Error::new(ErrorKind::InvalidData, e)),
65                Decoding::Memory => Err(Error::new(ErrorKind::OutOfMemory, e)),
66            },
67        }
68    }
69}
70
71/// Traits for elements that can be written to a byte writer
72#[cfg(feature = "std")]
73pub trait ToWriter {
74    /// Writes `self` to the given byte writer
75    fn write<T>(self, writer: T) -> Result<(), std::io::Error>
76    where
77        T: std::io::Write;
78}
79#[cfg(feature = "std")]
80impl<T> ToWriter for T
81where
82    T: IntoIterator<Item = u8>,
83{
84    fn write<W>(self, writer: W) -> Result<(), std::io::Error>
85    where
86        W: std::io::Write,
87    {
88        use std::io::{BufWriter, Write};
89
90        // Write each byte in a buffered way for performance
91        let mut writer = BufWriter::new(writer);
92        for byte in self {
93            // Write byte
94            writer.write_all(&[byte])?;
95        }
96
97        // Flush buffer
98        writer.flush()
99    }
100}