use gled_gpu::constants::UNIVERSE_BUFFER_SIZE;
const HEADER_LEN: usize = 18;
pub(super) const PACKET_LEN: usize = HEADER_LEN + UNIVERSE_BUFFER_SIZE as usize;
const MAX_PORT_ADDRESS: u16 = 0x7fff;
pub(super) fn write(buffer: &mut Vec<u8>, universe: u16, data: &[u8; 512]) -> bool {
if universe > MAX_PORT_ADDRESS {
return false;
}
let [port_low, port_high] = universe.to_le_bytes();
let [length_high, length_low] = (UNIVERSE_BUFFER_SIZE as u16).to_be_bytes();
buffer.extend_from_slice(&[
b'A',
b'r',
b't',
b'-',
b'N',
b'e',
b't',
0,
0x00,
0x50,
0,
14,
0,
0,
port_low,
port_high,
length_high,
length_low,
]);
buffer.extend_from_slice(data);
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_packet_is_what_artnet_protocol_writes() {
let mut data = [0u8; 512];
for (index, value) in data.iter_mut().enumerate() {
*value = (index * 7 % 256) as u8;
}
for universe in [0u16, 1, 255, 256, 4095, MAX_PORT_ADDRESS] {
let mut buffer = Vec::new();
assert!(write(&mut buffer, universe, &data));
let expected = artnet_protocol::ArtCommand::Output(artnet_protocol::Output {
data: artnet_protocol::PaddedData::from(data.to_vec()),
port_address: artnet_protocol::PortAddress::try_from(universe)
.expect("a port address"),
..Default::default()
})
.write_to_buffer()
.expect("an ArtDmx packet");
assert_eq!(buffer, expected, "universe {universe}");
assert_eq!(buffer.len(), PACKET_LEN);
}
}
#[test]
fn a_universe_past_the_port_addresses_writes_nothing() {
let mut buffer = vec![1, 2, 3];
assert!(!write(&mut buffer, MAX_PORT_ADDRESS + 1, &[0; 512]));
assert_eq!(buffer, [1, 2, 3]);
}
}