pub mod deserialize;
pub mod serialize;
use std::{
ffi::c_void,
io::{Seek, Write},
};
use bitflags::bitflags;
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::{BoolVisitor, NoneVisitor, PodDeserialize, PodDeserializer};
use serialize::{PodSerialize, PodSerializer};
use crate::utils::{Choice, Fd, Fraction, Id, Rectangle};
use self::deserialize::{
ChoiceDoubleVisitor, ChoiceFdVisitor, ChoiceFloatVisitor, ChoiceFractionVisitor,
ChoiceIdVisitor, ChoiceIntVisitor, ChoiceLongVisitor, ChoiceRectangleVisitor, DoubleVisitor,
FdVisitor, FloatVisitor, FractionVisitor, IdVisitor, IntVisitor, LongVisitor, PointerVisitor,
RectangleVisitor,
};
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 CanonicalFixedSizedPodSeal for super::Id {}
impl CanonicalFixedSizedPodSeal for super::Fd {}
}
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)
}
}
impl CanonicalFixedSizedPod for Id {
const TYPE: u32 = spa_sys::SPA_TYPE_Id;
const SIZE: u32 = 4;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_u32(self.0), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
map(u32(Endianness::Native), Id)(input)
}
}
impl CanonicalFixedSizedPod for Fd {
const TYPE: u32 = spa_sys::SPA_TYPE_Fd;
const SIZE: u32 = 8;
fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
gen_simple(ne_i64(self.0), out)
}
fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized,
{
map(i64(Endianness::Native), Fd)(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> PodDeserialize<'de> for () {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_none(NoneVisitor)
}
}
impl<'de> PodDeserialize<'de> for bool {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_bool(BoolVisitor)
}
}
impl<'de> PodDeserialize<'de> for i32 {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_int(IntVisitor)
}
}
impl<'de> PodDeserialize<'de> for i64 {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_long(LongVisitor)
}
}
impl<'de> PodDeserialize<'de> for f32 {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_float(FloatVisitor)
}
}
impl<'de> PodDeserialize<'de> for f64 {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_double(DoubleVisitor)
}
}
impl<'de> PodDeserialize<'de> for Rectangle {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_rectangle(RectangleVisitor)
}
}
impl<'de> PodDeserialize<'de> for Fraction {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_fraction(FractionVisitor)
}
}
impl<'de> PodDeserialize<'de> for Id {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_id(IdVisitor)
}
}
impl<'de> PodDeserialize<'de> for Fd {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_fd(FdVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<i32> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceIntVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<i64> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceLongVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<f32> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceFloatVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<f64> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceDoubleVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<Id> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceIdVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<Rectangle> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceRectangleVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<Fraction> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceFractionVisitor)
}
}
impl<'de> PodDeserialize<'de> for Choice<Fd> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceFdVisitor)
}
}
impl<'de, T> PodDeserialize<'de> for (u32, *const T) {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_pointer(PointerVisitor::<T>::default())
}
}
impl<'de> PodDeserialize<'de> for Value {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_any()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
None,
Bool(bool),
Id(Id),
Int(i32),
Long(i64),
Float(f32),
Double(f64),
String(String),
Bytes(Vec<u8>),
Rectangle(Rectangle),
Fraction(Fraction),
Fd(Fd),
ValueArray(ValueArray),
Struct(Vec<Value>),
Object(Object),
Choice(ChoiceValue),
Pointer(u32, *const c_void),
}
#[derive(Debug, Clone, PartialEq)]
pub enum ValueArray {
None(Vec<()>),
Bool(Vec<bool>),
Id(Vec<Id>),
Int(Vec<i32>),
Long(Vec<i64>),
Float(Vec<f32>),
Double(Vec<f64>),
Rectangle(Vec<Rectangle>),
Fraction(Vec<Fraction>),
Fd(Vec<Fd>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum ChoiceValue {
Int(Choice<i32>),
Long(Choice<i64>),
Float(Choice<f32>),
Double(Choice<f64>),
Id(Choice<Id>),
Rectangle(Choice<Rectangle>),
Fraction(Choice<Fraction>),
Fd(Choice<Fd>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Object {
pub type_: u32,
pub id: u32,
pub properties: Vec<Property>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Property {
pub key: u32,
pub flags: PropertyFlags,
pub value: Value,
}
bitflags! {
pub struct PropertyFlags: u32 {
const READONLY = spa_sys::SPA_POD_PROP_FLAG_READONLY;
const HARDWARE = spa_sys::SPA_POD_PROP_FLAG_HARDWARE;
const HINT_DICT = spa_sys::SPA_POD_PROP_FLAG_HINT_DICT;
}
}