mqtt/control/variable_header/
connect_flags.rs

1use std::io::{self, Read, Write};
2
3use byteorder::{ReadBytesExt, WriteBytesExt};
4
5use crate::control::variable_header::VariableHeaderError;
6use crate::{Decodable, Encodable};
7
8/// Flags for `CONNECT` packet
9#[derive(Debug, Eq, PartialEq, Copy, Clone)]
10pub struct ConnectFlags {
11    pub user_name: bool,
12    pub password: bool,
13    pub will_retain: bool,
14    pub will_qos: u8,
15    pub will_flag: bool,
16    pub clean_session: bool,
17    // We never use this, but must decode because brokers must verify it's zero per [MQTT-3.1.2-3]
18    pub reserved: bool,
19}
20
21impl ConnectFlags {
22    pub fn empty() -> ConnectFlags {
23        ConnectFlags {
24            user_name: false,
25            password: false,
26            will_retain: false,
27            will_qos: 0,
28            will_flag: false,
29            clean_session: false,
30            reserved: false,
31        }
32    }
33}
34
35impl Encodable for ConnectFlags {
36    #[rustfmt::skip]
37    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
38        let code = ((self.user_name as u8) << 7)
39            | ((self.password as u8) << 6)
40            | ((self.will_retain as u8) << 5)
41            | ((self.will_qos) << 3)
42            | ((self.will_flag as u8) << 2)
43            | ((self.clean_session as u8) << 1);
44
45        writer.write_u8(code)
46    }
47
48    fn encoded_length(&self) -> u32 {
49        1
50    }
51}
52
53impl Decodable for ConnectFlags {
54    type Error = VariableHeaderError;
55    type Cond = ();
56
57    fn decode_with<R: Read>(reader: &mut R, _rest: ()) -> Result<ConnectFlags, VariableHeaderError> {
58        let code = reader.read_u8()?;
59        if code & 1 != 0 {
60            return Err(VariableHeaderError::InvalidReservedFlag);
61        }
62
63        Ok(ConnectFlags {
64            user_name: (code & 0b1000_0000) != 0,
65            password: (code & 0b0100_0000) != 0,
66            will_retain: (code & 0b0010_0000) != 0,
67            will_qos: (code & 0b0001_1000) >> 3,
68            will_flag: (code & 0b0000_0100) != 0,
69            clean_session: (code & 0b0000_0010) != 0,
70            reserved: (code & 0b0000_0001) != 0,
71        })
72    }
73}