ddp_rs/protocol/id.rs
1use serde::{Deserialize, Serialize};
2
3/// Protocol ID used to identify the purpose of a packet.
4///
5/// IDs are used to differentiate between pixel data, control messages, configuration
6/// queries, and other packet types. The ID space is divided into several ranges:
7///
8/// - 0: Reserved
9/// - 1: Default (standard pixel data)
10/// - 2-245, 247-249: Custom IDs for application-specific use
11/// - 246: Control messages (JSON control read/write)
12/// - 250: Configuration messages (JSON config read/write)
13/// - 251: Status messages (JSON status read-only)
14/// - 254: DMX data
15/// - 255: Broadcast to all displays
16///
17/// # Examples
18///
19/// ```
20/// use ddp_rs::protocol::ID;
21///
22/// // Standard pixel data
23/// let pixel_id = ID::Default;
24///
25/// // Control message
26/// let control_id = ID::Control;
27///
28/// // Custom application ID
29/// let custom_id = ID::Custom(42);
30/// ```
31#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Copy, Default)]
32pub enum ID {
33 /// Reserved, should not be used
34 Reserved,
35
36 /// Default ID for standard pixel data
37 #[default]
38 Default,
39
40 /// Custom ID in ranges 2-245 and 247-249
41 Custom(u8),
42
43 /// Control message ID (246) for JSON control read/write
44 Control,
45
46 /// Configuration message ID (250) for JSON config read/write
47 Config,
48
49 /// Status message ID (251) for JSON status read-only
50 Status,
51
52 /// DMX data ID (254)
53 DMX,
54
55 /// Broadcast to all displays (255)
56 Broadcast,
57}
58
59impl From<u8> for ID {
60 fn from(value: u8) -> Self {
61 match value {
62 0 => ID::Reserved,
63 1 => ID::Default,
64 246 => ID::Control,
65 250 => ID::Config,
66 251 => ID::Status,
67 254 => ID::DMX,
68 255 => ID::Broadcast,
69 // All other values are custom IDs (2-245, 247-249, 252-253)
70 _ => ID::Custom(value),
71 }
72 }
73}
74
75impl Into<u8> for ID {
76 fn into(self) -> u8 {
77 match self {
78 ID::Reserved => 0,
79 ID::Default => 1,
80 ID::Control => 246,
81 ID::Config => 250,
82 ID::Status => 251,
83 ID::DMX => 254,
84 ID::Broadcast => 255,
85 ID::Custom(value) => {
86 // Valid custom ranges: 2-245, 247-249, 252-253
87 if matches!(value, 2..=245 | 247..=249 | 252..=253) {
88 value
89 } else {
90 1 // Default to ID 1 if invalid
91 }
92 }
93 }
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_id_parse() {
103 // Custom
104 let id = ID::from(212);
105 assert_eq!(id, ID::Custom(212));
106
107 // Default
108 let id = ID::from(1);
109 assert_eq!(id, ID::Default);
110
111 // Status
112 let id = ID::from(251);
113 assert_eq!(id, ID::Status);
114
115 // Reserved
116 let id = ID::from(0);
117 assert_eq!(id, ID::Reserved);
118 }
119}