ddp_connection/
packet.rs

1use crate::protocol::{message::Message, Header};
2
3#[derive(Debug, PartialEq, Clone)]
4/// Packet is our internal representation of a recieved packet
5/// Used to parse messages sent back by displays
6/// This struct does allocate!
7pub struct Packet {
8    /// The packet header
9    pub header: Header,
10    /// Raw data, if you're getting pixels this is the one you want
11    pub data: Vec<u8>,
12    /// For anything that's messaging, we try to parse it or cast it to string here
13    pub parsed: Option<Message>,
14}
15
16impl Packet {
17    pub fn from_data(h: Header, d: &[u8]) -> Packet {
18        Packet {
19            header: h,
20            data: d.to_vec(),
21            parsed: None,
22        }
23    }
24
25    pub fn from_bytes(bytes: &[u8]) -> Self {
26        let header_bytes = &bytes[0..14];
27        let header = Header::try_from(header_bytes).unwrap();
28        let mut start_index: usize = 10;
29        if header.packet_type.timecode{
30            start_index = 14;
31        }
32        let data = &bytes[start_index..];
33
34
35        let mut parsed: Option<Message> = None;
36
37        if header.packet_type.reply {
38            // Try to parse the data into typed structs in the spec
39            parsed = match match header.id {
40                crate::protocol::ID::Control => match serde_json::from_slice(data) {
41                    Ok(v) => Some(Message::Control(v)),
42                    Err(_) => None,
43                },
44                crate::protocol::ID::Config => match serde_json::from_slice(data) {
45                    Ok(v) => Some(Message::Config(v)),
46                    Err(_) => None,
47                },
48                crate::protocol::ID::Status => match serde_json::from_slice(data) {
49                    Ok(v) => Some(Message::Status(v)),
50                    Err(_) => None,
51                },
52                _ => None,
53            } {
54                // Worked, return the typed struct
55                Some(v) => Some(v),
56
57                // OK, no bueno, lets try just untyped JSON
58                None => match header.id {
59                    crate::protocol::ID::Control
60                    | crate::protocol::ID::Config
61                    | crate::protocol::ID::Status => match serde_json::from_slice(data) {
62                        // JSON Value it is
63                        Ok(v) => Some(Message::Parsed((header.id, v))),
64                        // Ok we're really screwed, lets just return the raw data as a string
65                        Err(_) => match std::str::from_utf8(&data) {
66                            Ok(v) => Some(Message::Unparsed((header.id, v.to_string()))),
67                            // I guess it's... just bytes?
68                            Err(_) => None,
69                        },
70                    },
71                    _ => None,
72                },
73            }
74        }
75        Packet {
76            header,
77            data: data.to_vec(),
78            parsed,
79        }
80    }
81}
82
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_json() {
90        {
91            let data = vec![
92                0x44, 0x00, 0x0D, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8E, 0x7b, 0x0a, 0x20, 0x20,
93                0x20, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x3a, 0x0a, 0x20, 0x20,
94                0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x67,
95                0x77, 0x22, 0x3a, 0x20, 0x22, 0x61, 0x2e, 0x62, 0x2e, 0x63, 0x2e, 0x64, 0x22, 0x2c,
96                0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x69, 0x70, 0x22, 0x3a,
97                0x20, 0x22, 0x61, 0x2e, 0x62, 0x2e, 0x63, 0x2e, 0x64, 0x22, 0x2c, 0x0a, 0x20, 0x20,
98                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x20, 0x22, 0x61,
99                0x2e, 0x62, 0x2e, 0x63, 0x2e, 0x64, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
100                0x20, 0x20, 0x20, 0x22, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x3a, 0x0a, 0x20, 0x20,
101                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
102                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
103                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6c, 0x22, 0x3a,
104                0x20, 0x33, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
105                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x3a, 0x20,
106                0x31, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
107                0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x73, 0x22, 0x3a, 0x20, 0x34, 0x2c, 0x0a,
108                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
109                0x20, 0x20, 0x22, 0x74, 0x73, 0x22, 0x3a, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20,
110                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x2c, 0x0a, 0x20, 0x20, 0x20,
111                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
112                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
113                0x6c, 0x22, 0x3a, 0x20, 0x37, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
114                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x6f, 0x72, 0x74,
115                0x22, 0x3a, 0x20, 0x35, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
116                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x73, 0x22, 0x3a, 0x20,
117                0x38, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
118                0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x73, 0x22, 0x3a, 0x20, 0x36, 0x0a, 0x20,
119                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20,
120                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
121                0x0a, 0x7d,
122            ];
123            let packet = Packet::from_bytes(&data);
124
125            assert_eq!(packet.header.length, 398);
126
127            match packet.parsed {
128                Some(p) => match p {
129                    Message::Config(c) => {
130                        assert_eq!(c.config.gw.unwrap(), "a.b.c.d");
131                        assert_eq!(c.config.nm.unwrap(), "a.b.c.d");
132                        assert_eq!(c.config.ports.len(), 2);
133                    }
134                    _ => panic!("not the right packet parsed"),
135                },
136                None => panic!("Packet parsing failed"),
137            }
138        }
139    }
140
141    #[test]
142    fn test_untyped() {
143        {
144            let data = vec![
145                0x44, 0x00, 0x0D, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x7B, 0x22, 0x68, 0x65,
146                0x6C, 0x6C, 0x6F, 0x22, 0x3A, 0x20, 0x22, 0x6F, 0x6B, 0x22, 0x7D,
147            ];
148            let packet = Packet::from_bytes(&data);
149
150            match packet.parsed {
151                Some(p) => match p {
152                    Message::Parsed((_, p)) => {
153                        assert_eq!(p["hello"], "ok");
154                    }
155                    _ => panic!("not the right packet parsed"),
156                },
157                None => panic!("Packet parsing failed"),
158            }
159        }
160    }
161
162    #[test]
163    fn test_unparsed() {
164        {
165            let data = vec![
166                0x44, 0x00, 0x0D, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x53, 0x4C, 0x49, 0x43,
167                0x4B, 0x44, 0x45, 0x4E, 0x49, 0x53, 0x34, 0x30, 0x30, 0x30,
168            ];
169            let packet = Packet::from_bytes(&data);
170
171            match packet.parsed {
172                Some(p) => match p {
173                    Message::Unparsed((_, p)) => {
174                        assert_eq!(p, "SLICKDENIS4000");
175                    }
176                    _ => panic!("not the right packet parsed"),
177                },
178                None => panic!("Packet parsing failed"),
179            }
180        }
181    }
182}