pub mod deserialize;
pub mod serialize;
use std::io::{Seek, Write};
use cookie_factory::{
bytes::{ne_f32, ne_f64, ne_i32, ne_i64, ne_u32},
gen_simple,
sequence::pair,
GenError,
};
use nom::{
combinator::map,
number::{
complete::{f32, f64, i32, i64, u32},
Endianness,
},
IResult,
};
use deserialize::{PodDeserialize, PodDeserializer};
use serialize::{PodSerialize, PodSerializer};
use crate::utils::{Fraction, Rectangle};
pub trait CanonicalFixedSizedPod: private::CanonicalFixedSizedPodSeal {
#[doc(hidden)]
const TYPE: u32;
#[doc(hidden)]
const SIZE: u32;
#[doc(hidden)]
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError>;
#[doc(hidden)]
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized;
}
mod private {
pub trait CanonicalFixedSizedPodSeal {}
impl CanonicalFixedSizedPodSeal for () {}
impl CanonicalFixedSizedPodSeal for bool {}
impl CanonicalFixedSizedPodSeal for i32 {}
impl CanonicalFixedSizedPodSeal for i64 {}
impl CanonicalFixedSizedPodSeal for f32 {}
impl CanonicalFixedSizedPodSeal for f64 {}
impl CanonicalFixedSizedPodSeal for super::Rectangle {}
impl CanonicalFixedSizedPodSeal for super::Fraction {}
}
impl<T: CanonicalFixedSizedPod + Copy> FixedSizedPod for T {
type CanonicalType = Self;
fn as_canonical_type(&self) -> Self::CanonicalType {
*self
}
fn from_canonical_type(canonical: &Self::CanonicalType) -> Self {
*canonical
}
}
impl CanonicalFixedSizedPod for () {
const TYPE: u32 = spa_sys::SPA_TYPE_None;
const SIZE: u32 = 0;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
Ok(out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
Ok((input, ()))
}
}
impl CanonicalFixedSizedPod for bool {
const TYPE: u32 = spa_sys::SPA_TYPE_Bool;
const SIZE: u32 = 4;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_u32(if *self { 1u32 } else { 0u32 }), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
map(u32(Endianness::Native), |b| b != 0)(input)
}
}
impl CanonicalFixedSizedPod for i32 {
const TYPE: u32 = spa_sys::SPA_TYPE_Int;
const SIZE: u32 = 4;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_i32(*self), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
i32(Endianness::Native)(input)
}
}
impl CanonicalFixedSizedPod for i64 {
const TYPE: u32 = spa_sys::SPA_TYPE_Long;
const SIZE: u32 = 8;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_i64(*self), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
i64(Endianness::Native)(input)
}
}
impl CanonicalFixedSizedPod for f32 {
const TYPE: u32 = spa_sys::SPA_TYPE_Float;
const SIZE: u32 = 4;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_f32(*self), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
f32(Endianness::Native)(input)
}
}
impl CanonicalFixedSizedPod for f64 {
const TYPE: u32 = spa_sys::SPA_TYPE_Double;
const SIZE: u32 = 8;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_f64(*self), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
f64(Endianness::Native)(input)
}
}
impl CanonicalFixedSizedPod for Rectangle {
const TYPE: u32 = spa_sys::SPA_TYPE_Rectangle;
const SIZE: u32 = 8;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(pair(ne_u32(self.width), ne_u32(self.height)), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
map(
nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
|(width, height)| Rectangle { width, height },
)(input)
}
}
impl CanonicalFixedSizedPod for Fraction {
const TYPE: u32 = spa_sys::SPA_TYPE_Fraction;
const SIZE: u32 = 8;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(pair(ne_u32(self.num), ne_u32(self.denom)), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
map(
nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
|(num, denom)| Fraction { num, denom },
)(input)
}
}
pub trait FixedSizedPod {
type CanonicalType: CanonicalFixedSizedPod;
fn as_canonical_type(&self) -> Self::CanonicalType;
fn from_canonical_type(_: &Self::CanonicalType) -> Self;
}
impl<T: FixedSizedPod> PodSerialize for T {
fn serialize<O: Write + Seek>(
&self,
serializer: PodSerializer<O>,
) -> Result<serialize::SerializeSuccess<O>, GenError> {
serializer.serialized_fixed_sized_pod(self)
}
}
impl<'de, T: FixedSizedPod> PodDeserialize<'de> for T {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<(Self, deserialize::DeserializeSuccess<'de>), nom::Err<nom::error::Error<&'de [u8]>>>
where
Self: Sized,
{
deserializer.deserialize_fixed_sized_pod::<Self>()
}
}