ddp_rs/protocol/
mod.rs

1// http://www.3waylabs.com/ddp/
2
3pub mod packet_type;
4pub use packet_type::*;
5
6pub mod pixel_config;
7pub use pixel_config::{PixelConfig, PixelFormat};
8
9pub mod id;
10pub use id::ID;
11
12pub mod message;
13
14pub mod timecode;
15use timecode::TimeCode;
16
17#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Default)]
18pub struct Header {
19    pub packet_type: PacketType,
20    pub sequence_number: u8,
21    pub pixel_config: PixelConfig,
22    pub id: ID,
23    pub offset: u32,
24    pub length: u16,
25    pub time_code: TimeCode, //technically supported, although untested and relies on user to handle
26}
27
28impl Into<[u8; 10]> for Header {
29    fn into(self) -> [u8; 10] {
30        // Define a byte array with the size of the header
31        let mut buffer: [u8; 10] = [0u8; 10];
32
33        // Write the packet type field to the buffer
34
35        let packet_type_byte: u8 = self.packet_type.into();
36        buffer[0] = packet_type_byte;
37
38        // Write the sequence number field to the buffer
39        buffer[1] = self.sequence_number;
40
41        // Write the pixel config field to the buffer
42        buffer[2] = self.pixel_config.into();
43
44        // Write the id field to the buffer
45        buffer[3] = self.id.into();
46
47        // Write the offset field to the buffer
48        let offset_bytes = self.offset.to_be_bytes();
49        buffer[4..8].copy_from_slice(&offset_bytes);
50
51        // Write the length field to the buffer
52        let length_bytes = self.length.to_be_bytes();
53        buffer[8..10].copy_from_slice(&length_bytes);
54
55        // Return a slice of the buffer representing the entire header
56        buffer
57    }
58}
59impl Into<[u8; 14]> for Header {
60    fn into(self) -> [u8; 14] {
61        // Define a byte array with the size of the header
62        let mut buffer = [0u8; 14];
63
64        // Write the packet type field to the buffer
65
66        let packet_type_byte: u8 = self.packet_type.into();
67        buffer[0] = packet_type_byte;
68
69        // Write the sequence number field to the buffer
70        buffer[1] = self.sequence_number;
71
72        // Write the pixel config field to the buffer
73        buffer[2] = self.pixel_config.into();
74
75        // Write the id field to the buffer
76        buffer[3] = self.id.into();
77
78        // Write the offset field to the buffer
79        let offset_bytes: [u8; 4] = self.offset.to_be_bytes();
80        buffer[4..8].copy_from_slice(&offset_bytes);
81
82        // Write the length field to the buffer
83        let length_bytes: [u8; 2] = self.length.to_be_bytes();
84        buffer[8..10].copy_from_slice(&length_bytes);
85
86        let time_code: [u8; 4] = self.time_code.to_bytes();
87        buffer[10..14].copy_from_slice(&time_code);
88
89        // Return a slice of the buffer representing the entire header
90        buffer
91    }
92}
93
94impl<'a> From<&'a [u8]> for Header {
95    fn from(bytes: &'a [u8]) -> Self {
96        // Extract the packet type field from the buffer
97        let packet_type = PacketType::from(bytes[0]);
98
99        // Extract the sequence number field from the buffer
100        let sequence_number = bytes[1];
101
102        // Extract the pixel config field from the buffer
103        let pixel_config = PixelConfig::from(bytes[2]);
104
105        // Extract the id field from the buffer
106        let id = ID::from(bytes[3]);
107
108        // Extract the offset field from the buffer
109        let offset = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
110
111        // Extract the length field from the buffer
112        let length = u16::from_be_bytes([bytes[8], bytes[9]]);
113
114        if packet_type.timecode && bytes.len() >= 14 {
115            let time_code = TimeCode::from_4_bytes([bytes[10], bytes[11], bytes[12], bytes[13]]);
116
117            Header {
118                packet_type,
119                sequence_number,
120                pixel_config,
121                id,
122                offset,
123                length,
124                time_code,
125            }
126        } else {
127            Header {
128                packet_type,
129                sequence_number,
130                pixel_config,
131                id,
132                offset,
133                length,
134                time_code: TimeCode(None),
135            }
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn test_parsing() {
146        // Normal
147        {
148            let data: [u8; 10] = [65, 6, 10, 1, 0, 0, 0, 0, 0, 3];
149            let header = Header::from(&data[..]);
150
151            assert_eq!(
152                header.packet_type,
153                PacketType {
154                    version: 1,
155                    timecode: false,
156                    storage: false,
157                    reply: false,
158                    query: false,
159                    push: true
160                }
161            );
162            assert_eq!(header.sequence_number, 6);
163            assert_eq!(header.length, 3);
164            assert_eq!(header.offset, 0);
165        }
166
167        // oddity
168        {
169            let data: [u8; 10] = [255, 12, 13, 1, 0, 0, 0x99, 0xd5, 0x01, 0x19];
170            let header = Header::from(&data[..]);
171
172            assert_eq!(
173                header.packet_type,
174                PacketType {
175                    version: 3,
176                    timecode: true,
177                    storage: true,
178                    reply: true,
179                    query: true,
180                    push: true
181                }
182            );
183
184            assert_eq!(header.sequence_number, 12);
185            assert_eq!(
186                header.pixel_config,
187                PixelConfig {
188                    data_type: pixel_config::DataType::RGB,
189                    data_size: PixelFormat::Pixel24Bits,
190                    customer_defined: false
191                }
192            );
193            assert_eq!(header.length, 281);
194            assert_eq!(header.offset, 39381);
195        }
196    }
197}