ddp_rs/protocol/
packet_type.rs

1/// Packet type flags that control protocol behavior.
2///
3/// The packet type is encoded in byte 0 of the header and contains flags
4/// that determine how the packet should be interpreted and processed.
5///
6/// # Flag Bits
7///
8/// - Bits 6-7: Protocol version (1-4)
9/// - Bit 4: Timecode present (if set, header is 14 bytes instead of 10)
10/// - Bit 3: Storage (for persisting settings)
11/// - Bit 2: Reply (packet is a response)
12/// - Bit 1: Query (request information)
13/// - Bit 0: Push (final packet in sequence)
14///
15/// # Examples
16///
17/// ```
18/// use ddp_rs::protocol::PacketType;
19///
20/// let mut pkt = PacketType::default();
21/// pkt.push = true;  // Mark as final packet
22/// pkt.version = 1;  // DDP version 1
23/// ```
24#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
25#[allow(dead_code)]
26pub struct PacketType {
27    /// Protocol version (1-4)
28    pub version: u8,
29
30    /// Timecode is present (extends header to 14 bytes)
31    pub timecode: bool,
32
33    /// Storage flag (persist settings)
34    pub storage: bool,
35
36    /// Reply flag (this is a response packet)
37    pub reply: bool,
38
39    /// Query flag (request information)
40    pub query: bool,
41
42    /// Push flag (final packet in a sequence)
43    pub push: bool,
44}
45
46impl PacketType {
47    /// Sets the push flag, indicating this is the final packet in a sequence.
48    pub fn push(&mut self, push: bool) {
49        self.push = push;
50    }
51}
52
53const VERSION_MASK: u8 = 0xc0;
54//const RESERVED: u8 = 0x20;
55const TIMECODE: u8 = 0x10;
56const STORAGE: u8 = 0x08;
57const REPLY: u8 = 0x04;
58const QUERY: u8 = 0x02;
59const PUSH: u8 = 0x01;
60
61impl Default for PacketType {
62    fn default() -> Self {
63        Self {
64            version: 1,
65            timecode: false,
66            storage: false,
67            reply: false,
68            query: false,
69            push: false,
70        }
71    }
72}
73
74impl From<u8> for PacketType {
75    fn from(byte: u8) -> Self {
76        let version = match byte & VERSION_MASK {
77            0x00 => 0,
78            0x40 => 1,
79            0x80 => 2,
80            0xc0 => 3,
81            _ => 0,
82        };
83        let timecode = byte & TIMECODE == TIMECODE;
84        let storage = byte & STORAGE == STORAGE;
85        let reply = byte & REPLY == REPLY;
86        let query = byte & QUERY == QUERY;
87        let push = byte & PUSH == PUSH;
88
89        PacketType {
90            version,
91            timecode,
92            storage,
93            reply,
94            query,
95            push,
96        }
97    }
98}
99
100impl Into<u8> for PacketType {
101    fn into(self) -> u8 {
102        let mut byte: u8 = 0;
103        let v = match self.version {
104            1 => self.version,
105            2 => self.version,
106            3 => self.version,
107            4 => self.version,
108            _ => 0,
109        };
110        byte |= v << 6;
111        // Set the flag bits
112        if self.timecode {
113            byte |= TIMECODE
114        };
115        if self.storage {
116            byte |= STORAGE
117        };
118        if self.reply {
119            byte |= REPLY
120        };
121        if self.query {
122            byte |= QUERY
123        };
124        if self.push {
125            byte |= PUSH
126        };
127
128        byte
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135
136    #[test]
137    fn test_packet_type_parse() {
138        let byte: u8 = 0b00010110;
139        let packet_type = PacketType::from(byte);
140
141        assert_eq!(
142            packet_type,
143            PacketType {
144                version: 0,
145                timecode: true,
146                storage: false,
147                reply: true,
148                query: true,
149                push: false,
150            }
151        );
152    }
153
154    #[test]
155    fn test_packet_type_into_u8() {
156        let packet_type = PacketType {
157            version: 1,
158            timecode: true,
159            storage: false,
160            reply: true,
161            query: true,
162            push: false,
163        };
164
165        let byte: u8 = packet_type.into();
166        assert_eq!(byte, 0x56);
167    }
168}