use crate::protocol::{
self, ReadBytes, ReadBytesExt, ReadFromBytes, SizeBytes, WriteBytes, WriteBytesExt,
WriteToBytes, LE,
};
use std::borrow::Cow;
use std::ffi::CString;
use std::{io, mem};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Header {
pub citp_header: protocol::Header,
pub content_type: u32,
pub content_hint: u32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Message<T> {
pub fptc_header: Header,
pub message: T,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Ptch {
pub fixture_identifier: u16,
pub universe: u8,
pub reserved: u8,
pub channel: u16,
pub channel_count: u16,
pub fixture_make: CString,
pub fixture_name: CString,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct UPtc<'a> {
pub fixture_identifiers: Cow<'a, [u16]>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct SPtc<'a> {
pub fixture_identifiers: Cow<'a, [u16]>,
}
impl Header {
pub const CONTENT_TYPE: &'static [u8; 4] = b"FPTC";
}
impl Ptch {
pub const CONTENT_TYPE: &'static [u8; 4] = b"Ptch";
}
impl<'a> UPtc<'a> {
pub const CONTENT_TYPE: &'static [u8; 4] = b"UPtc";
}
impl<'a> SPtc<'a> {
pub const CONTENT_TYPE: &'static [u8; 4] = b"SPtc";
}
impl WriteToBytes for Header {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_bytes(self.citp_header)?;
writer.write_u32::<LE>(self.content_type)?;
writer.write_u32::<LE>(self.content_hint)?;
Ok(())
}
}
impl<T> WriteToBytes for Message<T>
where
T: WriteToBytes,
{
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_bytes(self.fptc_header)?;
writer.write_bytes(&self.message)?;
Ok(())
}
}
impl WriteToBytes for Ptch {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u16::<LE>(self.fixture_identifier)?;
writer.write_u8(self.universe)?;
writer.write_u8(self.reserved)?;
writer.write_u16::<LE>(self.channel)?;
writer.write_u16::<LE>(self.channel_count)?;
writer.write_bytes(&self.fixture_make)?;
writer.write_bytes(&self.fixture_name)?;
Ok(())
}
}
impl<'a> WriteToBytes for UPtc<'a> {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u16::<LE>(self.fixture_identifiers.len() as _)?;
for &id in self.fixture_identifiers.iter() {
writer.write_u16::<LE>(id)?;
}
Ok(())
}
}
impl<'a> WriteToBytes for SPtc<'a> {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u16::<LE>(self.fixture_identifiers.len() as _)?;
for &id in self.fixture_identifiers.iter() {
writer.write_u16::<LE>(id)?;
}
Ok(())
}
}
impl ReadFromBytes for Ptch {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let fixture_identifier = reader.read_u16::<LE>()?;
let universe = reader.read_u8()?;
let reserved = reader.read_u8()?;
let channel = reader.read_u16::<LE>()?;
let channel_count = reader.read_u16::<LE>()?;
let fixture_make = reader.read_bytes()?;
let fixture_name = reader.read_bytes()?;
let ptch = Ptch {
fixture_identifier,
universe,
reserved,
channel,
channel_count,
fixture_make,
fixture_name,
};
Ok(ptch)
}
}
impl ReadFromBytes for UPtc<'static> {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let fixture_count: u16 = reader.read_bytes()?;
let fixture_identifiers = protocol::read_new_vec(reader, fixture_count as _)?;
let fixture_identifiers = Cow::Owned(fixture_identifiers);
let uptc = UPtc {
fixture_identifiers,
};
Ok(uptc)
}
}
impl ReadFromBytes for SPtc<'static> {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let fixture_count: u16 = reader.read_bytes()?;
let fixture_identifiers = protocol::read_new_vec(reader, fixture_count as _)?;
let fixture_identifiers = Cow::Owned(fixture_identifiers);
let uptc = SPtc {
fixture_identifiers,
};
Ok(uptc)
}
}
impl SizeBytes for Ptch {
fn size_bytes(&self) -> usize {
mem::size_of::<u16>()
+ mem::size_of::<u8>()
+ mem::size_of::<u8>()
+ mem::size_of::<u16>()
+ mem::size_of::<u16>()
+ self.fixture_make.size_bytes()
+ self.fixture_name.size_bytes()
}
}
impl<'a> SizeBytes for UPtc<'a> {
fn size_bytes(&self) -> usize {
self.fixture_identifiers.len() * mem::size_of::<u16>()
}
}
impl<'a> SizeBytes for SPtc<'a> {
fn size_bytes(&self) -> usize {
self.fixture_identifiers.len() * mem::size_of::<u16>()
}
}