use crate::protocol::{
self, ReadBytes, ReadBytesExt, ReadFromBytes, SizeBytes, WriteBytes, WriteBytesExt,
WriteToBytes, LE,
};
use std::borrow::Cow;
use std::ffi::CString;
use std::{self, io, mem};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Header {
pub citp_header: protocol::Header,
pub content_type: u32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Message<T> {
pub sdmx_header: Header,
pub message: T,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Capa<'a> {
pub capabilities: Cow<'a, [u16]>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct UNam {
pub universe_index: u8,
pub universe_name: CString,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct EnId {
pub identifier: CString,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct ChBk<'a> {
pub blind: u8,
pub universe_index: u8,
pub first_channel: u16,
pub channel_levels: Cow<'a, [u8]>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct ChLs<'a> {
pub channel_levels: Cow<'a, [ChannelLevel]>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct ChannelLevel {
universe_index: u8,
channel: u16,
channel_level: u8,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct SXSr {
pub connection_string: CString,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Sxus {
pub universe_index: u8,
pub connection_string: CString,
}
impl Header {
pub const CONTENT_TYPE: &'static [u8; 4] = b"SDMX";
}
impl<'a> Capa<'a> {
pub const CONTENT_TYPE: &'static [u8; 4] = b"Capa";
pub const CHANNEL_LIST: u16 = 1;
pub const EXTERNAL_SOURCE: u16 = 2;
pub const PER_UNIVERSE_EXTERNAL_SOURCES: u16 = 3;
pub const ART_NET_EXTERNAL_SOURCES: u16 = 101;
pub const BSR_E131_EXTERNAL_SOURCES: u16 = 102;
pub const ETC_NET2_EXTERNAL_SOURCES: u16 = 103;
pub const MA_NET_EXTERNAL_SOURCES: u16 = 103;
}
impl UNam {
pub const CONTENT_TYPE: &'static [u8; 4] = b"UNam";
}
impl EnId {
pub const CONTENT_TYPE: &'static [u8; 4] = b"EnId";
}
impl<'a> ChBk<'a> {
pub const CONTENT_TYPE: &'static [u8; 4] = b"ChBk";
}
impl<'a> ChLs<'a> {
pub const CONTENT_TYPE: &'static [u8; 4] = b"ChLs";
}
impl SXSr {
pub const CONTENT_TYPE: &'static [u8; 4] = b"SXSr";
}
impl Sxus {
pub const CONTENT_TYPE: &'static [u8; 4] = b"SXUS";
}
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)?;
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.sdmx_header)?;
writer.write_bytes(&self.message)?;
Ok(())
}
}
impl<'a> WriteToBytes for Capa<'a> {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
if self.capabilities.len() > std::u16::MAX as usize {
let err_msg = "the number of capabilities exceeds the maximum possible `u16` value";
return Err(io::Error::new(io::ErrorKind::InvalidData, err_msg));
}
writer.write_u16::<LE>(self.capabilities.len() as u16)?;
for &cap in self.capabilities.iter() {
writer.write_u16::<LE>(cap)?;
}
Ok(())
}
}
impl WriteToBytes for UNam {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u8(self.universe_index)?;
writer.write_bytes(&self.universe_name)?;
Ok(())
}
}
impl WriteToBytes for EnId {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_bytes(&self.identifier)?;
Ok(())
}
}
impl<'a> WriteToBytes for ChBk<'a> {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u8(self.blind)?;
writer.write_u8(self.universe_index)?;
writer.write_u16::<LE>(self.first_channel)?;
writer.write_u16::<LE>(self.channel_levels.len() as _)?;
for &lvl in self.channel_levels.iter() {
writer.write_u8(lvl)?;
}
Ok(())
}
}
impl WriteToBytes for ChannelLevel {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u8(self.universe_index)?;
writer.write_u16::<LE>(self.channel)?;
writer.write_u8(self.channel_level)?;
Ok(())
}
}
impl<'a> WriteToBytes for ChLs<'a> {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u16::<LE>(self.channel_levels.len() as _)?;
for ch in self.channel_levels.iter() {
writer.write_bytes(ch)?;
}
Ok(())
}
}
impl WriteToBytes for SXSr {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_bytes(&self.connection_string)?;
Ok(())
}
}
impl WriteToBytes for Sxus {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u8(self.universe_index)?;
writer.write_bytes(&self.connection_string)?;
Ok(())
}
}
impl ReadFromBytes for Capa<'static> {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let capability_count: u16 = reader.read_bytes()?;
let capabilities = protocol::read_new_vec(reader, capability_count as _)?;
let capabilities = Capa {
capabilities: Cow::Owned(capabilities),
};
Ok(capabilities)
}
}
impl ReadFromBytes for UNam {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let universe_index = reader.read_u8()?;
let universe_name = reader.read_bytes()?;
let unam = UNam {
universe_index,
universe_name,
};
Ok(unam)
}
}
impl ReadFromBytes for EnId {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let identifier = reader.read_bytes()?;
let enid = EnId { identifier };
Ok(enid)
}
}
impl ReadFromBytes for ChBk<'static> {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let blind = reader.read_u8()?;
let universe_index = reader.read_u8()?;
let first_channel = reader.read_u16::<LE>()?;
let channel_level_count: u16 = reader.read_u16::<LE>()?;
let channel_levels = protocol::read_new_vec(reader, channel_level_count as _)?;
let channel_levels = Cow::Owned(channel_levels);
let chbk = ChBk {
blind,
universe_index,
first_channel,
channel_levels,
};
Ok(chbk)
}
}
impl ReadFromBytes for ChannelLevel {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let universe_index = reader.read_u8()?;
let channel = reader.read_u16::<LE>()?;
let channel_level = reader.read_u8()?;
let ch = ChannelLevel {
universe_index,
channel,
channel_level,
};
Ok(ch)
}
}
impl ReadFromBytes for ChLs<'static> {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let channel_level_count = reader.read_u16::<LE>()?;
let channel_levels = protocol::read_new_vec(reader, channel_level_count as _)?;
let channel_levels = Cow::Owned(channel_levels);
let chls = ChLs { channel_levels };
Ok(chls)
}
}
impl ReadFromBytes for SXSr {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let connection_string = reader.read_bytes()?;
let sxsr = SXSr { connection_string };
Ok(sxsr)
}
}
impl ReadFromBytes for Sxus {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let universe_index = reader.read_u8()?;
let connection_string = reader.read_bytes()?;
let sxus = Sxus {
universe_index,
connection_string,
};
Ok(sxus)
}
}
impl<'a> SizeBytes for Capa<'a> {
fn size_bytes(&self) -> usize {
mem::size_of::<u16>() + self.capabilities.len() * mem::size_of::<u16>()
}
}
impl SizeBytes for UNam {
fn size_bytes(&self) -> usize {
mem::size_of::<u8>() + self.universe_name.size_bytes()
}
}
impl SizeBytes for EnId {
fn size_bytes(&self) -> usize {
self.identifier.size_bytes()
}
}
impl<'a> SizeBytes for ChBk<'a> {
fn size_bytes(&self) -> usize {
mem::size_of::<u8>()
+ mem::size_of::<u8>()
+ mem::size_of::<u16>()
+ mem::size_of::<u16>()
+ self.channel_levels.len() * mem::size_of::<u8>()
}
}
impl<'a> SizeBytes for ChLs<'a> {
fn size_bytes(&self) -> usize {
mem::size_of::<u16>() + self.channel_levels.len() * mem::size_of::<ChannelLevel>()
}
}
impl SizeBytes for SXSr {
fn size_bytes(&self) -> usize {
self.connection_string.size_bytes()
}
}
impl SizeBytes for Sxus {
fn size_bytes(&self) -> usize {
mem::size_of::<u8>() + self.connection_string.size_bytes()
}
}