webui_protocol/plugin/
webui.rs1use crate::{ProtocolError, Result};
5
6const WEBUI_ELEMENT_DATA_LEN: usize = 12;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct WebUIElementData {
11 pub binding_count: u32,
13 pub event_start: u32,
15 pub event_count: u32,
17}
18
19impl WebUIElementData {
20 #[must_use]
22 pub fn encode(self) -> [u8; WEBUI_ELEMENT_DATA_LEN] {
23 let mut data = [0u8; WEBUI_ELEMENT_DATA_LEN];
24 data[..4].copy_from_slice(&self.binding_count.to_le_bytes());
25 data[4..8].copy_from_slice(&self.event_start.to_le_bytes());
26 data[8..12].copy_from_slice(&self.event_count.to_le_bytes());
27 data
28 }
29
30 pub fn decode(bytes: &[u8]) -> Result<Self> {
36 if bytes.len() != WEBUI_ELEMENT_DATA_LEN {
37 return Err(ProtocolError::Validation(format!(
38 "WebUI element data must be {WEBUI_ELEMENT_DATA_LEN} bytes, received {}",
39 bytes.len()
40 )));
41 }
42
43 Ok(Self {
44 binding_count: u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
45 event_start: u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
46 event_count: u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
47 })
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::WebUIElementData;
54 use crate::ProtocolError;
55
56 #[test]
57 fn test_webui_element_data_roundtrip() {
58 let encoded = WebUIElementData {
59 binding_count: 2,
60 event_start: 5,
61 event_count: 1,
62 }
63 .encode();
64 let decoded = WebUIElementData::decode(&encoded).expect("decode should succeed");
65 assert_eq!(decoded.binding_count, 2);
66 assert_eq!(decoded.event_start, 5);
67 assert_eq!(decoded.event_count, 1);
68 }
69
70 #[test]
71 fn test_webui_element_data_rejects_invalid_length() {
72 let result = WebUIElementData::decode(&[1, 2, 3, 4]);
73 assert!(
74 matches!(result, Err(ProtocolError::Validation(ref msg)) if msg.contains("12 bytes")),
75 "invalid payload length should be rejected: {result:?}"
76 );
77 }
78}