pub mod builder;
pub mod deserialize;
pub mod parser;
pub mod serialize;
use std::{
ffi::c_void,
io::{Seek, Write},
mem::MaybeUninit,
os::fd::RawFd,
ptr::addr_of,
};
use bitflags::bitflags;
use cookie_factory::{
bytes::{ne_f32, ne_f64, ne_i32, ne_i64, ne_u32},
gen_simple,
sequence::pair,
GenError,
};
use nix::errno::Errno;
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, SpaTypes};
use self::deserialize::{
ChoiceBoolVisitor, ChoiceDoubleVisitor, ChoiceFdVisitor, ChoiceFloatVisitor,
ChoiceFractionVisitor, ChoiceIdVisitor, ChoiceIntVisitor, ChoiceLongVisitor,
ChoiceRectangleVisitor, DoubleVisitor, FdVisitor, FloatVisitor, FractionVisitor, IdVisitor,
IntVisitor, LongVisitor, PointerVisitor, RectangleVisitor,
};
#[repr(transparent)]
pub struct Pod(spa_sys::spa_pod);
impl Pod {
pub unsafe fn from_raw(pod: *const spa_sys::spa_pod) -> &'static Self {
pod.cast::<Self>().as_ref().unwrap()
}
pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod) -> &'static mut Self {
pod.cast::<Self>().as_mut().unwrap()
}
pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod {
addr_of!(self.0).cast_mut()
}
pub fn body(&self) -> *mut c_void {
unsafe {
self.as_raw_ptr()
.byte_add(std::mem::size_of::<spa_sys::spa_pod>())
.cast()
}
}
pub fn from_bytes(bytes: &[u8]) -> Option<&Self> {
const HEADER_SIZE: usize = std::mem::size_of::<spa_sys::spa_pod>();
if bytes.len() < HEADER_SIZE {
return None;
}
let pod: *const spa_sys::spa_pod = bytes.as_ptr().cast();
let size: usize = unsafe { *pod }.size.try_into().unwrap();
let padding = (8 - (size % 8)) % 8;
if HEADER_SIZE + size + padding <= bytes.len() {
Some(unsafe { Self::from_raw(pod) })
} else {
None
}
}
pub fn as_bytes(&self) -> &[u8] {
let ptr: *const u8 = self.as_raw_ptr().cast();
let size: usize = self.size().try_into().unwrap();
let size = size + std::mem::size_of::<spa_sys::spa_pod>();
unsafe { std::slice::from_raw_parts(ptr, size) }
}
pub fn type_(&self) -> SpaTypes {
SpaTypes::from_raw(self.0.type_)
}
pub fn size(&self) -> u32 {
self.0.size
}
pub fn is_none(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_none(self.as_raw_ptr()) };
res != 0
}
pub fn is_bool(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_bool(self.as_raw_ptr()) };
res != 0
}
pub fn get_bool(&self) -> Result<bool, Errno> {
unsafe {
let mut b: MaybeUninit<bool> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_bool(self.as_raw_ptr(), b.as_mut_ptr());
if res >= 0 {
Ok(b.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_id(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_id(self.as_raw_ptr()) };
res != 0
}
pub fn get_id(&self) -> Result<Id, Errno> {
unsafe {
let mut id: MaybeUninit<u32> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_id(self.as_raw_ptr(), id.as_mut_ptr());
if res >= 0 {
Ok(Id(id.assume_init()))
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_int(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_int(self.as_raw_ptr()) };
res != 0
}
pub fn get_int(&self) -> Result<i32, Errno> {
unsafe {
let mut int: MaybeUninit<i32> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_int(self.as_raw_ptr(), int.as_mut_ptr());
if res >= 0 {
Ok(int.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_long(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_long(self.as_raw_ptr()) };
res != 0
}
pub fn get_long(&self) -> Result<i64, Errno> {
unsafe {
let mut long: MaybeUninit<i64> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_long(self.as_raw_ptr(), long.as_mut_ptr());
if res >= 0 {
Ok(long.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_float(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_float(self.as_raw_ptr()) };
res != 0
}
pub fn get_float(&self) -> Result<f32, Errno> {
unsafe {
let mut float: MaybeUninit<f32> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_float(self.as_raw_ptr(), float.as_mut_ptr());
if res >= 0 {
Ok(float.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_double(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_double(self.as_raw_ptr()) };
res != 0
}
pub fn get_double(&self) -> Result<f64, Errno> {
unsafe {
let mut double: MaybeUninit<f64> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_double(self.as_raw_ptr(), double.as_mut_ptr());
if res >= 0 {
Ok(double.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_string(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_string(self.as_raw_ptr()) };
res != 0
}
pub fn is_bytes(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_bytes(self.as_raw_ptr()) };
res != 0
}
pub fn get_bytes(&self) -> Result<&[u8], Errno> {
unsafe {
let mut bytes: MaybeUninit<*const c_void> = MaybeUninit::uninit();
let mut len: MaybeUninit<u32> = MaybeUninit::uninit();
let res =
spa_sys::spa_pod_get_bytes(self.as_raw_ptr(), bytes.as_mut_ptr(), len.as_mut_ptr());
if res >= 0 {
let bytes = bytes.assume_init();
let len = len.assume_init();
let bytes = std::slice::from_raw_parts(bytes.cast(), len.try_into().unwrap());
Ok(bytes)
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_pointer(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_pointer(self.as_raw_ptr()) };
res != 0
}
pub fn get_pointer(&self) -> Result<(*const c_void, Id), Errno> {
unsafe {
let mut _type: MaybeUninit<u32> = MaybeUninit::uninit();
let mut pointer: MaybeUninit<*const c_void> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_pointer(
self.as_raw_ptr(),
_type.as_mut_ptr(),
pointer.as_mut_ptr(),
);
if res >= 0 {
let _type = Id(_type.assume_init());
let pointer = pointer.assume_init();
Ok((pointer, _type))
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_fd(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_fd(self.as_raw_ptr()) };
res != 0
}
pub fn get_fd(&self) -> Result<RawFd, Errno> {
unsafe {
let mut fd: MaybeUninit<i64> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_fd(self.as_raw_ptr(), fd.as_mut_ptr());
if res >= 0 {
let fd = fd.assume_init();
let fd: RawFd = fd.try_into().unwrap();
Ok(fd)
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_rectangle(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_rectangle(self.as_raw_ptr()) };
res != 0
}
pub fn get_rectangle(&self) -> Result<Rectangle, Errno> {
unsafe {
let mut rectangle: MaybeUninit<spa_sys::spa_rectangle> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_rectangle(self.as_raw_ptr(), rectangle.as_mut_ptr());
if res >= 0 {
Ok(rectangle.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_fraction(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_fraction(self.as_raw_ptr()) };
res != 0
}
pub fn get_fraction(&self) -> Result<Fraction, Errno> {
unsafe {
let mut fraction: MaybeUninit<spa_sys::spa_fraction> = MaybeUninit::uninit();
let res = spa_sys::spa_pod_get_fraction(self.as_raw_ptr(), fraction.as_mut_ptr());
if res >= 0 {
Ok(fraction.assume_init())
} else {
Err(Errno::from_i32(-res))
}
}
}
pub fn is_bitmap(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_bitmap(self.as_raw_ptr()) };
res != 0
}
pub fn is_array(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_array(self.as_raw_ptr()) };
res != 0
}
pub fn is_choice(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_choice(self.as_raw_ptr()) };
res != 0
}
pub fn is_struct(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_struct(self.as_raw_ptr()) };
res != 0
}
pub fn as_struct(&self) -> Result<&PodStruct, Errno> {
if self.is_struct() {
Ok(unsafe { PodStruct::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_struct) })
} else {
Err(Errno::EINVAL)
}
}
pub fn is_object(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_object(self.as_raw_ptr()) };
res != 0
}
pub fn as_object(&self) -> Result<&PodObject, Errno> {
if self.is_object() {
Ok(unsafe { PodObject::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_object) })
} else {
Err(Errno::EINVAL)
}
}
pub fn is_sequence(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_is_sequence(self.as_raw_ptr()) };
res != 0
}
}
impl<'p> From<&'p PodStruct> for &'p Pod {
fn from(value: &'p PodStruct) -> Self {
value.as_pod()
}
}
impl<'p> From<&'p PodObject> for &'p Pod {
fn from(value: &'p PodObject) -> Self {
value.as_pod()
}
}
#[repr(transparent)]
pub struct PodStruct(spa_sys::spa_pod_struct);
impl PodStruct {
pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_struct) -> &'static Self {
pod.cast::<Self>().as_ref().unwrap()
}
pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_struct) -> &'static mut Self {
pod.cast::<Self>().as_mut().unwrap()
}
pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_struct {
std::ptr::addr_of!(self.0).cast_mut()
}
pub fn as_pod(&self) -> &Pod {
unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
}
pub fn fields(&self) -> PodStructIter<'_> {
PodStructIter::new(self)
}
}
impl<'p> TryFrom<&'p Pod> for &'p PodStruct {
type Error = Errno;
fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
value.as_struct()
}
}
impl AsRef<Pod> for PodStruct {
fn as_ref(&self) -> &Pod {
self.as_pod()
}
}
pub struct PodStructIter<'s> {
struct_pod: &'s PodStruct,
next: *mut c_void,
}
impl<'s> PodStructIter<'s> {
fn new(struct_pod: &'s PodStruct) -> Self {
let first_field = struct_pod.as_pod().body();
Self {
struct_pod,
next: first_field,
}
}
}
impl<'s> Iterator for PodStructIter<'s> {
type Item = &'s Pod;
fn next(&mut self) -> Option<Self::Item> {
let has_next = unsafe {
spa_sys::spa_pod_is_inside(
self.struct_pod.as_pod().body(),
self.struct_pod.0.pod.size,
self.next,
)
};
if has_next {
let res = unsafe { Pod::from_raw(self.next as *const spa_sys::spa_pod) };
self.next = unsafe { spa_sys::spa_pod_next(self.next) };
Some(res)
} else {
None
}
}
}
#[repr(transparent)]
pub struct PodObject(spa_sys::spa_pod_object);
impl PodObject {
pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_object) -> &'static Self {
pod.cast::<Self>().as_ref().unwrap()
}
pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_object) -> &'static mut Self {
pod.cast::<Self>().as_mut().unwrap()
}
pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_object {
std::ptr::addr_of!(self.0).cast_mut()
}
pub fn as_pod(&self) -> &Pod {
unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
}
pub fn type_(&self) -> SpaTypes {
SpaTypes::from_raw(self.0.body.type_)
}
pub fn id(&self) -> Id {
Id(self.0.body.id)
}
pub fn props(&self) -> PodObjectIter<'_> {
PodObjectIter::new(self)
}
pub fn find_prop(&self, key: Id) -> Option<&PodProp> {
let prop = unsafe {
spa_sys::spa_pod_object_find_prop(self.as_raw_ptr(), std::ptr::null(), key.0)
};
if !prop.is_null() {
unsafe { Some(PodProp::from_raw(prop)) }
} else {
None
}
}
pub fn fixate(&mut self) {
let _res = unsafe { spa_sys::spa_pod_object_fixate(self.as_raw_ptr()) };
}
#[cfg(feature = "v0_3_40")]
pub fn is_fixated(&self) -> bool {
let res = unsafe { spa_sys::spa_pod_object_is_fixated(self.as_raw_ptr()) };
res != 0
}
}
impl<'p> TryFrom<&'p Pod> for &'p PodObject {
type Error = Errno;
fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
value.as_object()
}
}
impl AsRef<Pod> for PodObject {
fn as_ref(&self) -> &Pod {
self.as_pod()
}
}
pub struct PodObjectIter<'o> {
object: &'o PodObject,
next: *mut spa_sys::spa_pod_prop,
}
impl<'o> PodObjectIter<'o> {
fn new(object: &'o PodObject) -> Self {
let first_prop = unsafe { spa_sys::spa_pod_prop_first(addr_of!(object.0.body)) };
Self {
object,
next: first_prop,
}
}
}
impl<'o> Iterator for PodObjectIter<'o> {
type Item = &'o PodProp;
fn next(&mut self) -> Option<Self::Item> {
let has_next = unsafe {
spa_sys::spa_pod_prop_is_inside(
addr_of!(self.object.0.body),
self.object.0.pod.size,
self.next,
)
};
if has_next {
let res = unsafe { PodProp::from_raw(self.next.cast_const()) };
self.next = unsafe { spa_sys::spa_pod_prop_next(self.next) };
Some(res)
} else {
None
}
}
}
bitflags! {
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct PodPropFlags: 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;
const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
}
}
#[repr(transparent)]
pub struct PodProp(spa_sys::spa_pod_prop);
impl PodProp {
pub unsafe fn from_raw(prop: *const spa_sys::spa_pod_prop) -> &'static Self {
prop.cast::<Self>().as_ref().unwrap()
}
pub unsafe fn from_raw_mut(prop: *mut spa_sys::spa_pod_prop) -> &'static mut Self {
prop.cast::<Self>().as_mut().unwrap()
}
pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_prop {
std::ptr::addr_of!(self.0).cast_mut()
}
pub fn key(&self) -> Id {
Id(self.0.key)
}
pub fn flags(&self) -> PodPropFlags {
PodPropFlags::from_bits_retain(self.0.flags)
}
pub fn value(&self) -> &Pod {
unsafe { Pod::from_raw(addr_of!(self.0.value)) }
}
}
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(u32::from(*self)), 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<bool> {
fn deserialize(
deserializer: PodDeserializer<'de>,
) -> Result<
(Self, deserialize::DeserializeSuccess<'de>),
deserialize::DeserializeError<&'de [u8]>,
>
where
Self: Sized,
{
deserializer.deserialize_choice(ChoiceBoolVisitor)
}
}
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 {
Bool(Choice<bool>),
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>,
}
#[doc(hidden)]
#[macro_export]
macro_rules! __object__ {
($type_:expr, $id:expr, $($properties:expr),* $(,)?) => {
pipewire::spa::pod::Object {
type_: $type_.as_raw(),
id: $id.as_raw(),
properties: [ $( $properties, )* ].to_vec(),
}
};
}
#[doc(inline)]
pub use __object__ as object;
#[derive(Debug, Clone, PartialEq)]
pub struct Property {
pub key: u32,
pub flags: PropertyFlags,
pub value: Value,
}
impl Property {
pub fn new(key: u32, value: Value) -> Self {
Self {
key,
value,
flags: PropertyFlags::empty(),
}
}
}
bitflags! {
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
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;
const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
#[cfg(feature = "v0_3_33")]
const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __property__ {
($key:expr, $value:expr) => {
pipewire::spa::pod::Property {
key: $key.as_raw(),
flags: pipewire::spa::pod::PropertyFlags::empty(),
value: $value,
}
};
($key:expr, Id, $value:expr) => {
pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::Id(pipewire::spa::utils::Id($value.as_raw())))
};
($key:expr, $type_:ident, $value:expr) => {
pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::$type_($value))
};
($key:expr, Choice, Enum, Id, $default:expr, $($alternative:expr),+ $(,)?) => {
pipewire::spa::pod::property!(
$key,
pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::Id(
pipewire::spa::utils::Choice::<pipewire::spa::utils::Id>(
pipewire::spa::utils::ChoiceFlags::empty(),
pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::Id>::Enum {
default: pipewire::spa::utils::Id($default.as_raw()),
alternatives: [ $( pipewire::spa::utils::Id($alternative.as_raw()), )+ ].to_vec()
}
)
))
)
};
($key:expr, Choice, Enum, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
pipewire::spa::pod::property!(
$key,
pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
pipewire::spa::utils::ChoiceFlags::empty(),
pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Enum {
default: $default,
alternatives: [ $( $alternative, )+ ].to_vec()
}
)
))
)
};
($key:expr, Choice, Flags, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
pipewire::spa::pod::property!(
$key,
pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
pipewire::spa::utils::ChoiceFlags::empty(),
pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Flags {
default: $default,
flags: [ $( $alternative, )+ ].to_vec()
}
)
))
)
};
($key:expr, Choice, Step, $type_:ident, $default:expr, $min:expr, $max:expr, $step:expr) => {
pipewire::spa::pod::property!(
$key,
pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
pipewire::spa::utils::ChoiceFlags::empty(),
pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Step {
default: $default,
min: $min,
max: $max,
step: $step,
}
)
))
)
};
($key:expr, Choice, Range, $type_:ident, $default:expr, $min:expr, $max:expr) => {
pipewire::spa::pod::property!(
$key,
pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
pipewire::spa::utils::ChoiceFlags::empty(),
pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Range {
default: $default,
min: $min,
max: $max,
}
)
))
)
};
}
#[doc(inline)]
pub use __property__ as property;