pub use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use std::{
ffi::CString,
fmt,
hash::{Hash, Hasher},
io, mem,
str::FromStr,
};
pub mod pinf;
pub mod sdmx;
pub mod fptc;
pub mod fsel;
pub mod finf;
pub mod msex;
pub mod caex;
pub trait WriteBytes {
fn write_bytes<P: WriteToBytes>(&mut self, protocol: P) -> io::Result<()>;
}
pub trait ReadBytes {
fn read_bytes<P: ReadFromBytes>(&mut self) -> io::Result<P>;
}
pub trait WriteToBytes {
fn write_to_bytes<W: WriteBytesExt>(&self, writer: W) -> io::Result<()>;
}
pub trait ReadFromBytes: Sized {
fn read_from_bytes<R: ReadBytesExt>(reader: R) -> io::Result<Self>;
}
pub trait ConstSizeBytes: SizeBytes {
const SIZE_BYTES: usize;
}
pub trait SizeBytes {
fn size_bytes(&self) -> usize;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub struct Header {
pub cookie: u32,
pub version_major: u8,
pub version_minor: u8,
pub kind: Kind,
pub message_size: u32,
pub message_part_count: u16,
pub message_part: u16,
pub content_type: u32,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union Kind {
pub request_index: u16,
pub in_response_to: u16,
}
impl WriteToBytes for Kind {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
unsafe { writer.write_u16::<LE>(self.request_index) }
}
}
impl WriteToBytes for Header {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
writer.write_u32::<LE>(self.cookie)?;
writer.write_u8(self.version_major)?;
writer.write_u8(self.version_minor)?;
writer.write_bytes(self.kind)?;
writer.write_u32::<LE>(self.message_size)?;
writer.write_u16::<LE>(self.message_part_count)?;
writer.write_u16::<LE>(self.message_part)?;
writer.write_u32::<LE>(self.content_type)?;
Ok(())
}
}
impl ReadFromBytes for Kind {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let request_index = reader.read_u16::<LE>()?;
Ok(Kind { request_index })
}
}
impl ReadFromBytes for Header {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let cookie = reader.read_u32::<LE>()?;
let version_major = reader.read_u8()?;
let version_minor = reader.read_u8()?;
let kind = reader.read_bytes()?;
let message_size = reader.read_u32::<LE>()?;
let message_part_count = reader.read_u16::<LE>()?;
let message_part = reader.read_u16::<LE>()?;
let content_type = reader.read_u32::<LE>()?;
let header = Header {
cookie,
version_major,
version_minor,
kind,
message_size,
message_part_count,
message_part,
content_type,
};
Ok(header)
}
}
impl<W> WriteBytes for W
where
W: WriteBytesExt,
{
fn write_bytes<P: WriteToBytes>(&mut self, protocol: P) -> io::Result<()> {
protocol.write_to_bytes(self)
}
}
impl<R> ReadBytes for R
where
R: ReadBytesExt,
{
fn read_bytes<P: ReadFromBytes>(&mut self) -> io::Result<P> {
P::read_from_bytes(self)
}
}
impl<'a, T> WriteToBytes for &'a T
where
T: WriteToBytes,
{
fn write_to_bytes<W: WriteBytesExt>(&self, writer: W) -> io::Result<()> {
(**self).write_to_bytes(writer)
}
}
impl WriteToBytes for CString {
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
let bytes = self.as_bytes_with_nul();
for &byte in bytes {
writer.write_u8(byte)?;
}
Ok(())
}
}
impl ReadFromBytes for CString {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
let mut bytes = vec![];
loop {
match reader.read_u8()? {
b'\0' => break,
byte => bytes.push(byte),
}
}
let cstring = unsafe { CString::from_vec_unchecked(bytes) };
Ok(cstring)
}
}
impl ReadFromBytes for u8 {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
reader.read_u8()
}
}
impl ReadFromBytes for u16 {
fn read_from_bytes<R: ReadBytesExt>(mut reader: R) -> io::Result<Self> {
reader.read_u16::<LE>()
}
}
impl SizeBytes for CString {
fn size_bytes(&self) -> usize {
self.as_bytes_with_nul().len()
}
}
impl SizeBytes for Kind {
fn size_bytes(&self) -> usize {
mem::size_of::<Kind>()
}
}
impl SizeBytes for Header {
fn size_bytes(&self) -> usize {
mem::size_of::<Header>()
}
}
impl fmt::Debug for Kind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe { write!(f, "{:?}", self.request_index) }
}
}
impl Eq for Kind {}
impl PartialEq for Kind {
fn eq(&self, other: &Self) -> bool {
unsafe { self.request_index == other.request_index }
}
}
impl Hash for Kind {
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe {
self.request_index.hash(state);
}
}
}
pub fn read_vec<R, T>(mut reader: R, mut len: usize, vec: &mut Vec<T>) -> io::Result<()>
where
R: ReadBytesExt,
T: ReadFromBytes,
{
while len > 0 {
let elem = reader.read_bytes()?;
vec.push(elem);
len -= 1;
}
Ok(())
}
pub fn read_new_vec<R, T>(reader: R, len: usize) -> io::Result<Vec<T>>
where
R: ReadBytesExt,
T: ReadFromBytes,
{
let mut vec = Vec::with_capacity(len);
read_vec(reader, len, &mut vec)?;
Ok(vec)
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Ucs2(Vec<u16>);
impl Ucs2 {
fn read_from_bytes<R: ReadBytesExt>(reader: R) -> io::Result<Self> {
let mut ucs2: Ucs2 = Ucs2(Vec::new());
let mut bytes = reader.bytes();
while let Some(curr) = bytes.next() {
if let Some(next) = bytes.next() {
let val = [curr?, next?];
let y = u16::from_le_bytes(val);
if y == 0 {
break;
} else {
ucs2.0.push(y);
}
}
}
Ok(ucs2)
}
fn write_to_bytes<W: WriteBytesExt>(&self, mut writer: W) -> io::Result<()> {
for n in &self.0 {
writer.write_u16::<LE>(*n)?;
}
writer.write_u16::<LE>(0)?;
Ok(())
}
pub fn to_string(&self) -> Result<String, ucs2::Error> {
let mut utf8_buf = vec![0u8; self.0.len()];
ucs2::decode(&self.0, &mut utf8_buf)?;
let name = std::str::from_utf8(&utf8_buf).unwrap().clone().to_string();
Ok(name)
}
}
impl FromStr for Ucs2 {
type Err = ucs2::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut ucs2_buf = vec![0u16; s.len()];
ucs2::encode(s, &mut ucs2_buf)?;
Ok(Ucs2(ucs2_buf))
}
}
impl SizeBytes for Ucs2 {
fn size_bytes(&self) -> usize {
let null_terminated_bytes_len = 2;
mem::size_of::<u16>() * self.0.len() + null_terminated_bytes_len
}
}
impl fmt::Debug for Ucs2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match self.to_string() {
Ok(n) => n,
Err(_) => "unable to read string from Ucs2".to_string(),
};
write!(f, "{}", name)
}
}