1pub mod builder;
11pub mod deserialize;
12pub mod parser;
13pub mod serialize;
14
15use std::{
16 ffi::{c_char, c_void, CStr},
17 io::{Seek, Write},
18 mem::MaybeUninit,
19 os::fd::RawFd,
20 ptr::addr_of,
21};
22
23use bitflags::bitflags;
24use cookie_factory::{
25 bytes::{ne_f32, ne_f64, ne_i32, ne_i64, ne_u32},
26 gen_simple,
27 sequence::pair,
28 GenError,
29};
30use nix::errno::Errno;
31use nom::{
32 combinator::map,
33 number::{
34 complete::{f32, f64, i32, i64, u32},
35 Endianness,
36 },
37 IResult, Parser,
38};
39
40use deserialize::{BoolVisitor, NoneVisitor, PodDeserialize, PodDeserializer};
41use serialize::{PodSerialize, PodSerializer};
42
43use crate::utils::{Choice, Fd, Fraction, Id, Rectangle, SpaTypes};
44
45use self::deserialize::{
46 ChoiceBoolVisitor, ChoiceDoubleVisitor, ChoiceFdVisitor, ChoiceFloatVisitor,
47 ChoiceFractionVisitor, ChoiceIdVisitor, ChoiceIntVisitor, ChoiceLongVisitor,
48 ChoiceRectangleVisitor, DoubleVisitor, FdVisitor, FloatVisitor, FractionVisitor, IdVisitor,
49 IntVisitor, LongVisitor, PointerVisitor, RectangleVisitor,
50};
51
52#[repr(transparent)]
54pub struct Pod(spa_sys::spa_pod);
55
56impl Pod {
57 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod) -> &'static Self {
72 pod.cast::<Self>().as_ref().unwrap()
73 }
74
75 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod) -> &'static mut Self {
89 pod.cast::<Self>().as_mut().unwrap()
90 }
91
92 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod {
93 addr_of!(self.0).cast_mut()
94 }
95
96 pub fn body(&self) -> *mut c_void {
100 unsafe {
101 self.as_raw_ptr()
102 .byte_add(std::mem::size_of::<spa_sys::spa_pod>())
103 .cast()
104 }
105 }
106
107 pub fn from_bytes(bytes: &[u8]) -> Option<&Self> {
111 const HEADER_SIZE: usize = std::mem::size_of::<spa_sys::spa_pod>();
115
116 if bytes.len() < HEADER_SIZE {
117 return None;
118 }
119
120 let pod: *const spa_sys::spa_pod = bytes.as_ptr().cast();
121
122 let size: usize = unsafe { *pod }.size.try_into().unwrap();
124
125 let padding = (8 - (size % 8)) % 8;
126
127 if HEADER_SIZE + size + padding <= bytes.len() {
129 Some(unsafe { Self::from_raw(pod) })
132 } else {
133 None
134 }
135 }
136
137 pub fn as_bytes(&self) -> &[u8] {
138 let ptr: *const u8 = self.as_raw_ptr().cast();
139 let size: usize = self.size().try_into().unwrap();
140 let size = size + std::mem::size_of::<spa_sys::spa_pod>();
141
142 unsafe { std::slice::from_raw_parts(ptr, size) }
143 }
144
145 pub fn type_(&self) -> SpaTypes {
146 SpaTypes::from_raw(self.0.type_)
147 }
148
149 pub fn size(&self) -> u32 {
150 self.0.size
151 }
152
153 pub fn is_none(&self) -> bool {
156 let res = unsafe { spa_sys::spa_pod_is_none(self.as_raw_ptr()) };
157 res != 0
158 }
159
160 pub fn is_bool(&self) -> bool {
161 let res = unsafe { spa_sys::spa_pod_is_bool(self.as_raw_ptr()) };
162 res != 0
163 }
164
165 pub fn get_bool(&self) -> Result<bool, Errno> {
166 unsafe {
167 let mut b: MaybeUninit<bool> = MaybeUninit::uninit();
168 let res = spa_sys::spa_pod_get_bool(self.as_raw_ptr(), b.as_mut_ptr());
169
170 if res >= 0 {
171 Ok(b.assume_init())
172 } else {
173 Err(Errno::from_raw(-res))
174 }
175 }
176 }
177
178 pub fn is_id(&self) -> bool {
179 let res = unsafe { spa_sys::spa_pod_is_id(self.as_raw_ptr()) };
180 res != 0
181 }
182
183 pub fn get_id(&self) -> Result<Id, Errno> {
184 unsafe {
185 let mut id: MaybeUninit<u32> = MaybeUninit::uninit();
186 let res = spa_sys::spa_pod_get_id(self.as_raw_ptr(), id.as_mut_ptr());
187
188 if res >= 0 {
189 Ok(Id(id.assume_init()))
190 } else {
191 Err(Errno::from_raw(-res))
192 }
193 }
194 }
195
196 pub fn is_int(&self) -> bool {
197 let res = unsafe { spa_sys::spa_pod_is_int(self.as_raw_ptr()) };
198 res != 0
199 }
200
201 pub fn get_int(&self) -> Result<i32, Errno> {
202 unsafe {
203 let mut int: MaybeUninit<i32> = MaybeUninit::uninit();
204 let res = spa_sys::spa_pod_get_int(self.as_raw_ptr(), int.as_mut_ptr());
205
206 if res >= 0 {
207 Ok(int.assume_init())
208 } else {
209 Err(Errno::from_raw(-res))
210 }
211 }
212 }
213
214 pub fn is_long(&self) -> bool {
215 let res = unsafe { spa_sys::spa_pod_is_long(self.as_raw_ptr()) };
216 res != 0
217 }
218
219 pub fn get_long(&self) -> Result<i64, Errno> {
220 unsafe {
221 let mut long: MaybeUninit<i64> = MaybeUninit::uninit();
222 let res = spa_sys::spa_pod_get_long(self.as_raw_ptr(), long.as_mut_ptr());
223
224 if res >= 0 {
225 Ok(long.assume_init())
226 } else {
227 Err(Errno::from_raw(-res))
228 }
229 }
230 }
231
232 pub fn is_float(&self) -> bool {
233 let res = unsafe { spa_sys::spa_pod_is_float(self.as_raw_ptr()) };
234 res != 0
235 }
236
237 pub fn get_float(&self) -> Result<f32, Errno> {
238 unsafe {
239 let mut float: MaybeUninit<f32> = MaybeUninit::uninit();
240 let res = spa_sys::spa_pod_get_float(self.as_raw_ptr(), float.as_mut_ptr());
241
242 if res >= 0 {
243 Ok(float.assume_init())
244 } else {
245 Err(Errno::from_raw(-res))
246 }
247 }
248 }
249
250 pub fn is_double(&self) -> bool {
251 let res = unsafe { spa_sys::spa_pod_is_double(self.as_raw_ptr()) };
252 res != 0
253 }
254
255 pub fn get_double(&self) -> Result<f64, Errno> {
256 unsafe {
257 let mut double: MaybeUninit<f64> = MaybeUninit::uninit();
258 let res = spa_sys::spa_pod_get_double(self.as_raw_ptr(), double.as_mut_ptr());
259
260 if res >= 0 {
261 Ok(double.assume_init())
262 } else {
263 Err(Errno::from_raw(-res))
264 }
265 }
266 }
267
268 pub fn is_string(&self) -> bool {
269 let res = unsafe { spa_sys::spa_pod_is_string(self.as_raw_ptr()) };
270 res != 0
271 }
272
273 pub fn get_string_raw(&self) -> Result<Option<&CStr>, Errno> {
274 unsafe {
275 let mut value: MaybeUninit<*const c_char> = MaybeUninit::uninit();
276 let res = spa_sys::spa_pod_get_string(self.as_raw_ptr(), value.as_mut_ptr());
277
278 if res >= 0 {
279 let value = value.assume_init();
280 if value.is_null() {
281 Ok(None)
282 } else {
283 Ok(Some(CStr::from_ptr(value)))
284 }
285 } else {
286 Err(Errno::from_raw(-res))
287 }
288 }
289 }
290
291 pub fn is_bytes(&self) -> bool {
292 let res = unsafe { spa_sys::spa_pod_is_bytes(self.as_raw_ptr()) };
293 res != 0
294 }
295
296 pub fn get_bytes(&self) -> Result<&[u8], Errno> {
297 unsafe {
298 let mut bytes: MaybeUninit<*const c_void> = MaybeUninit::uninit();
299 let mut len: MaybeUninit<u32> = MaybeUninit::uninit();
300 let res =
301 spa_sys::spa_pod_get_bytes(self.as_raw_ptr(), bytes.as_mut_ptr(), len.as_mut_ptr());
302
303 if res >= 0 {
304 let bytes = bytes.assume_init();
305 let len = len.assume_init();
306 let bytes = std::slice::from_raw_parts(bytes.cast(), len.try_into().unwrap());
307 Ok(bytes)
308 } else {
309 Err(Errno::from_raw(-res))
310 }
311 }
312 }
313
314 pub fn is_pointer(&self) -> bool {
315 let res = unsafe { spa_sys::spa_pod_is_pointer(self.as_raw_ptr()) };
316 res != 0
317 }
318
319 pub fn get_pointer(&self) -> Result<(*const c_void, Id), Errno> {
320 unsafe {
321 let mut _type: MaybeUninit<u32> = MaybeUninit::uninit();
322 let mut pointer: MaybeUninit<*const c_void> = MaybeUninit::uninit();
323 let res = spa_sys::spa_pod_get_pointer(
324 self.as_raw_ptr(),
325 _type.as_mut_ptr(),
326 pointer.as_mut_ptr(),
327 );
328
329 if res >= 0 {
330 let _type = Id(_type.assume_init());
331 let pointer = pointer.assume_init();
332 Ok((pointer, _type))
333 } else {
334 Err(Errno::from_raw(-res))
335 }
336 }
337 }
338
339 pub fn is_fd(&self) -> bool {
340 let res = unsafe { spa_sys::spa_pod_is_fd(self.as_raw_ptr()) };
341 res != 0
342 }
343
344 pub fn get_fd(&self) -> Result<RawFd, Errno> {
345 unsafe {
346 let mut fd: MaybeUninit<i64> = MaybeUninit::uninit();
347 let res = spa_sys::spa_pod_get_fd(self.as_raw_ptr(), fd.as_mut_ptr());
348
349 if res >= 0 {
350 let fd = fd.assume_init();
351 let fd: RawFd = fd.try_into().unwrap();
352 Ok(fd)
353 } else {
354 Err(Errno::from_raw(-res))
355 }
356 }
357 }
358
359 pub fn is_rectangle(&self) -> bool {
360 let res = unsafe { spa_sys::spa_pod_is_rectangle(self.as_raw_ptr()) };
361 res != 0
362 }
363
364 pub fn get_rectangle(&self) -> Result<Rectangle, Errno> {
365 unsafe {
366 let mut rectangle: MaybeUninit<spa_sys::spa_rectangle> = MaybeUninit::uninit();
367 let res = spa_sys::spa_pod_get_rectangle(self.as_raw_ptr(), rectangle.as_mut_ptr());
368
369 if res >= 0 {
370 Ok(rectangle.assume_init())
371 } else {
372 Err(Errno::from_raw(-res))
373 }
374 }
375 }
376
377 pub fn is_fraction(&self) -> bool {
378 let res = unsafe { spa_sys::spa_pod_is_fraction(self.as_raw_ptr()) };
379 res != 0
380 }
381
382 pub fn get_fraction(&self) -> Result<Fraction, Errno> {
383 unsafe {
384 let mut fraction: MaybeUninit<spa_sys::spa_fraction> = MaybeUninit::uninit();
385 let res = spa_sys::spa_pod_get_fraction(self.as_raw_ptr(), fraction.as_mut_ptr());
386
387 if res >= 0 {
388 Ok(fraction.assume_init())
389 } else {
390 Err(Errno::from_raw(-res))
391 }
392 }
393 }
394
395 pub fn is_bitmap(&self) -> bool {
396 let res = unsafe { spa_sys::spa_pod_is_bitmap(self.as_raw_ptr()) };
397 res != 0
398 }
399
400 pub fn is_array(&self) -> bool {
401 let res = unsafe { spa_sys::spa_pod_is_array(self.as_raw_ptr()) };
402 res != 0
403 }
404
405 pub fn is_choice(&self) -> bool {
406 let res = unsafe { spa_sys::spa_pod_is_choice(self.as_raw_ptr()) };
407 res != 0
408 }
409
410 pub fn is_struct(&self) -> bool {
411 let res = unsafe { spa_sys::spa_pod_is_struct(self.as_raw_ptr()) };
412 res != 0
413 }
414
415 pub fn as_struct(&self) -> Result<&PodStruct, Errno> {
416 if self.is_struct() {
417 Ok(unsafe { PodStruct::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_struct) })
420 } else {
421 Err(Errno::EINVAL)
422 }
423 }
424
425 pub fn is_object(&self) -> bool {
426 let res = unsafe { spa_sys::spa_pod_is_object(self.as_raw_ptr()) };
427 res != 0
428 }
429
430 pub fn as_object(&self) -> Result<&PodObject, Errno> {
433 if self.is_object() {
434 Ok(unsafe { PodObject::from_raw(self.as_raw_ptr() as *const spa_sys::spa_pod_object) })
437 } else {
438 Err(Errno::EINVAL)
439 }
440 }
441
442 pub fn is_sequence(&self) -> bool {
443 let res = unsafe { spa_sys::spa_pod_is_sequence(self.as_raw_ptr()) };
444 res != 0
445 }
446}
447
448impl<'p> From<&'p PodStruct> for &'p Pod {
449 fn from(value: &'p PodStruct) -> Self {
450 value.as_pod()
451 }
452}
453
454impl<'p> From<&'p PodObject> for &'p Pod {
455 fn from(value: &'p PodObject) -> Self {
456 value.as_pod()
457 }
458}
459
460#[repr(transparent)]
462pub struct PodStruct(spa_sys::spa_pod_struct);
463
464impl PodStruct {
465 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_struct) -> &'static Self {
471 pod.cast::<Self>().as_ref().unwrap()
472 }
473
474 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_struct) -> &'static mut Self {
480 pod.cast::<Self>().as_mut().unwrap()
481 }
482
483 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_struct {
484 std::ptr::addr_of!(self.0).cast_mut()
485 }
486
487 pub fn as_pod(&self) -> &Pod {
488 unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
490 }
491
492 pub fn fields(&self) -> PodStructIter<'_> {
493 PodStructIter::new(self)
494 }
495}
496
497impl<'p> TryFrom<&'p Pod> for &'p PodStruct {
498 type Error = Errno;
499
500 fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
501 value.as_struct()
502 }
503}
504
505impl AsRef<Pod> for PodStruct {
506 fn as_ref(&self) -> &Pod {
507 self.as_pod()
508 }
509}
510
511pub struct PodStructIter<'s> {
512 struct_pod: &'s PodStruct,
513 next: *mut c_void,
514}
515
516impl<'s> PodStructIter<'s> {
517 fn new(struct_pod: &'s PodStruct) -> Self {
518 let first_field = struct_pod.as_pod().body();
519
520 Self {
521 struct_pod,
522 next: first_field,
523 }
524 }
525}
526
527impl<'s> Iterator for PodStructIter<'s> {
528 type Item = &'s Pod;
529
530 fn next(&mut self) -> Option<Self::Item> {
531 let has_next = unsafe {
533 spa_sys::spa_pod_is_inside(
534 self.struct_pod.as_pod().body(),
535 self.struct_pod.0.pod.size,
536 self.next,
537 )
538 };
539
540 if has_next {
541 let res = unsafe { Pod::from_raw(self.next as *const spa_sys::spa_pod) };
542
543 self.next = unsafe { spa_sys::spa_pod_next(self.next) };
545
546 Some(res)
547 } else {
548 None
549 }
550 }
551}
552
553#[repr(transparent)]
555pub struct PodObject(spa_sys::spa_pod_object);
556
557impl PodObject {
558 pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_object) -> &'static Self {
564 pod.cast::<Self>().as_ref().unwrap()
565 }
566
567 pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_object) -> &'static mut Self {
573 pod.cast::<Self>().as_mut().unwrap()
574 }
575
576 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_object {
577 std::ptr::addr_of!(self.0).cast_mut()
578 }
579
580 pub fn as_pod(&self) -> &Pod {
581 unsafe { Pod::from_raw(addr_of!(self.0.pod)) }
583 }
584
585 pub fn type_(&self) -> SpaTypes {
586 SpaTypes::from_raw(self.0.body.type_)
587 }
588
589 pub fn id(&self) -> Id {
590 Id(self.0.body.id)
591 }
592
593 pub fn props(&self) -> PodObjectIter<'_> {
594 PodObjectIter::new(self)
595 }
596
597 pub fn find_prop(&self, key: Id) -> Option<&PodProp> {
598 let prop = unsafe {
599 spa_sys::spa_pod_object_find_prop(self.as_raw_ptr(), std::ptr::null(), key.0)
600 };
601
602 if !prop.is_null() {
603 unsafe { Some(PodProp::from_raw(prop)) }
604 } else {
605 None
606 }
607 }
608
609 pub fn fixate(&mut self) {
610 let _res = unsafe { spa_sys::spa_pod_object_fixate(self.as_raw_ptr()) };
611 }
613
614 #[cfg(feature = "v0_3_40")]
615 pub fn is_fixated(&self) -> bool {
616 let res = unsafe { spa_sys::spa_pod_object_is_fixated(self.as_raw_ptr()) };
617 res != 0
618 }
619}
620
621impl<'p> TryFrom<&'p Pod> for &'p PodObject {
622 type Error = Errno;
623
624 fn try_from(value: &'p Pod) -> Result<Self, Self::Error> {
625 value.as_object()
626 }
627}
628
629impl AsRef<Pod> for PodObject {
630 fn as_ref(&self) -> &Pod {
631 self.as_pod()
632 }
633}
634
635pub struct PodObjectIter<'o> {
636 object: &'o PodObject,
637 next: *mut spa_sys::spa_pod_prop,
638}
639
640impl<'o> PodObjectIter<'o> {
641 fn new(object: &'o PodObject) -> Self {
642 let first_prop = unsafe { spa_sys::spa_pod_prop_first(addr_of!(object.0.body)) };
643
644 Self {
645 object,
646 next: first_prop,
647 }
648 }
649}
650
651impl<'o> Iterator for PodObjectIter<'o> {
652 type Item = &'o PodProp;
653
654 fn next(&mut self) -> Option<Self::Item> {
655 let has_next = unsafe {
657 spa_sys::spa_pod_prop_is_inside(
658 addr_of!(self.object.0.body),
659 self.object.0.pod.size,
660 self.next,
661 )
662 };
663
664 if has_next {
665 let res = unsafe { PodProp::from_raw(self.next.cast_const()) };
666
667 self.next = unsafe { spa_sys::spa_pod_prop_next(self.next) };
669
670 Some(res)
671 } else {
672 None
673 }
674 }
675}
676
677bitflags! {
678 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
679 pub struct PodPropFlags: u32 {
680 const READONLY = spa_sys::SPA_POD_PROP_FLAG_READONLY;
681 const HARDWARE = spa_sys::SPA_POD_PROP_FLAG_HARDWARE;
682 const HINT_DICT = spa_sys::SPA_POD_PROP_FLAG_HINT_DICT;
683 const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
684 const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
685 }
686}
687
688#[repr(transparent)]
690pub struct PodProp(spa_sys::spa_pod_prop);
691
692impl PodProp {
693 pub unsafe fn from_raw(prop: *const spa_sys::spa_pod_prop) -> &'static Self {
700 prop.cast::<Self>().as_ref().unwrap()
701 }
702
703 pub unsafe fn from_raw_mut(prop: *mut spa_sys::spa_pod_prop) -> &'static mut Self {
710 prop.cast::<Self>().as_mut().unwrap()
711 }
712
713 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_prop {
714 std::ptr::addr_of!(self.0).cast_mut()
715 }
716
717 pub fn key(&self) -> Id {
718 Id(self.0.key)
719 }
720
721 pub fn flags(&self) -> PodPropFlags {
722 PodPropFlags::from_bits_retain(self.0.flags)
723 }
724
725 pub fn value(&self) -> &Pod {
726 unsafe { Pod::from_raw(addr_of!(self.0.value)) }
730 }
731}
732
733pub trait CanonicalFixedSizedPod: private::CanonicalFixedSizedPodSeal {
744 #[doc(hidden)]
746 const TYPE: u32;
747 #[doc(hidden)]
749 const SIZE: u32;
750 #[doc(hidden)]
751 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError>;
752 #[doc(hidden)]
753 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
754 where
755 Self: Sized;
756}
757
758mod private {
759 pub trait CanonicalFixedSizedPodSeal {}
762 impl CanonicalFixedSizedPodSeal for () {}
763 impl CanonicalFixedSizedPodSeal for bool {}
764 impl CanonicalFixedSizedPodSeal for i32 {}
765 impl CanonicalFixedSizedPodSeal for i64 {}
766 impl CanonicalFixedSizedPodSeal for f32 {}
767 impl CanonicalFixedSizedPodSeal for f64 {}
768 impl CanonicalFixedSizedPodSeal for super::Rectangle {}
769 impl CanonicalFixedSizedPodSeal for super::Fraction {}
770 impl CanonicalFixedSizedPodSeal for super::Id {}
771 impl CanonicalFixedSizedPodSeal for super::Fd {}
772}
773
774impl<T: CanonicalFixedSizedPod + Copy> FixedSizedPod for T {
775 type CanonicalType = Self;
776
777 fn as_canonical_type(&self) -> Self::CanonicalType {
778 *self
779 }
780
781 fn from_canonical_type(canonical: &Self::CanonicalType) -> Self {
782 *canonical
783 }
784}
785
786impl CanonicalFixedSizedPod for () {
788 const TYPE: u32 = spa_sys::SPA_TYPE_None;
789 const SIZE: u32 = 0;
790
791 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
792 Ok(out)
793 }
794
795 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
796 where
797 Self: Sized,
798 {
799 Ok((input, ()))
800 }
801}
802
803impl CanonicalFixedSizedPod for bool {
805 const TYPE: u32 = spa_sys::SPA_TYPE_Bool;
806 const SIZE: u32 = 4;
807
808 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
809 gen_simple(ne_u32(u32::from(*self)), out)
810 }
811
812 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
813 where
814 Self: Sized,
815 {
816 map(u32(Endianness::Native), |b| b != 0).parse(input)
817 }
818}
819
820impl CanonicalFixedSizedPod for i32 {
822 const TYPE: u32 = spa_sys::SPA_TYPE_Int;
823 const SIZE: u32 = 4;
824
825 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
826 gen_simple(ne_i32(*self), out)
827 }
828
829 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
830 where
831 Self: Sized,
832 {
833 i32(Endianness::Native)(input)
834 }
835}
836
837impl CanonicalFixedSizedPod for i64 {
839 const TYPE: u32 = spa_sys::SPA_TYPE_Long;
840 const SIZE: u32 = 8;
841
842 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
843 gen_simple(ne_i64(*self), out)
844 }
845
846 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
847 where
848 Self: Sized,
849 {
850 i64(Endianness::Native)(input)
851 }
852}
853
854impl CanonicalFixedSizedPod for f32 {
856 const TYPE: u32 = spa_sys::SPA_TYPE_Float;
857 const SIZE: u32 = 4;
858
859 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
860 gen_simple(ne_f32(*self), out)
861 }
862
863 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
864 where
865 Self: Sized,
866 {
867 f32(Endianness::Native)(input)
868 }
869}
870
871impl CanonicalFixedSizedPod for f64 {
873 const TYPE: u32 = spa_sys::SPA_TYPE_Double;
874 const SIZE: u32 = 8;
875
876 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
877 gen_simple(ne_f64(*self), out)
878 }
879
880 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
881 where
882 Self: Sized,
883 {
884 f64(Endianness::Native)(input)
885 }
886}
887
888impl CanonicalFixedSizedPod for Rectangle {
890 const TYPE: u32 = spa_sys::SPA_TYPE_Rectangle;
891 const SIZE: u32 = 8;
892
893 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
894 gen_simple(pair(ne_u32(self.width), ne_u32(self.height)), out)
895 }
896
897 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
898 where
899 Self: Sized,
900 {
901 map(
902 nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
903 |(width, height)| Rectangle { width, height },
904 )
905 .parse(input)
906 }
907}
908
909impl CanonicalFixedSizedPod for Fraction {
911 const TYPE: u32 = spa_sys::SPA_TYPE_Fraction;
912 const SIZE: u32 = 8;
913
914 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
915 gen_simple(pair(ne_u32(self.num), ne_u32(self.denom)), out)
916 }
917
918 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
919 where
920 Self: Sized,
921 {
922 map(
923 nom::sequence::pair(u32(Endianness::Native), u32(Endianness::Native)),
924 |(num, denom)| Fraction { num, denom },
925 )
926 .parse(input)
927 }
928}
929
930impl CanonicalFixedSizedPod for Id {
931 const TYPE: u32 = spa_sys::SPA_TYPE_Id;
932 const SIZE: u32 = 4;
933
934 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
935 gen_simple(ne_u32(self.0), out)
936 }
937
938 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
939 where
940 Self: Sized,
941 {
942 map(u32(Endianness::Native), Id).parse(input)
943 }
944}
945
946impl CanonicalFixedSizedPod for Fd {
947 const TYPE: u32 = spa_sys::SPA_TYPE_Fd;
948 const SIZE: u32 = 8;
949
950 fn serialize_body<O: Write>(&self, out: O) -> Result<O, GenError> {
951 gen_simple(ne_i64(self.0), out)
952 }
953
954 fn deserialize_body(input: &[u8]) -> IResult<&[u8], Self>
955 where
956 Self: Sized,
957 {
958 map(i64(Endianness::Native), Fd).parse(input)
959 }
960}
961
962pub trait FixedSizedPod {
1001 type CanonicalType: CanonicalFixedSizedPod;
1003
1004 fn as_canonical_type(&self) -> Self::CanonicalType;
1006 fn from_canonical_type(_: &Self::CanonicalType) -> Self;
1008}
1009
1010impl<T: FixedSizedPod> PodSerialize for T {
1011 fn serialize<O: Write + Seek>(
1012 &self,
1013 serializer: PodSerializer<O>,
1014 ) -> Result<serialize::SerializeSuccess<O>, GenError> {
1015 serializer.serialized_fixed_sized_pod(self)
1016 }
1017}
1018
1019impl<'de> PodDeserialize<'de> for () {
1020 fn deserialize(
1021 deserializer: PodDeserializer<'de>,
1022 ) -> Result<
1023 (Self, deserialize::DeserializeSuccess<'de>),
1024 deserialize::DeserializeError<&'de [u8]>,
1025 >
1026 where
1027 Self: Sized,
1028 {
1029 deserializer.deserialize_none(NoneVisitor)
1030 }
1031}
1032
1033impl<'de> PodDeserialize<'de> for bool {
1034 fn deserialize(
1035 deserializer: PodDeserializer<'de>,
1036 ) -> Result<
1037 (Self, deserialize::DeserializeSuccess<'de>),
1038 deserialize::DeserializeError<&'de [u8]>,
1039 >
1040 where
1041 Self: Sized,
1042 {
1043 deserializer.deserialize_bool(BoolVisitor)
1044 }
1045}
1046
1047impl<'de> PodDeserialize<'de> for i32 {
1048 fn deserialize(
1049 deserializer: PodDeserializer<'de>,
1050 ) -> Result<
1051 (Self, deserialize::DeserializeSuccess<'de>),
1052 deserialize::DeserializeError<&'de [u8]>,
1053 >
1054 where
1055 Self: Sized,
1056 {
1057 deserializer.deserialize_int(IntVisitor)
1058 }
1059}
1060
1061impl<'de> PodDeserialize<'de> for i64 {
1062 fn deserialize(
1063 deserializer: PodDeserializer<'de>,
1064 ) -> Result<
1065 (Self, deserialize::DeserializeSuccess<'de>),
1066 deserialize::DeserializeError<&'de [u8]>,
1067 >
1068 where
1069 Self: Sized,
1070 {
1071 deserializer.deserialize_long(LongVisitor)
1072 }
1073}
1074
1075impl<'de> PodDeserialize<'de> for f32 {
1076 fn deserialize(
1077 deserializer: PodDeserializer<'de>,
1078 ) -> Result<
1079 (Self, deserialize::DeserializeSuccess<'de>),
1080 deserialize::DeserializeError<&'de [u8]>,
1081 >
1082 where
1083 Self: Sized,
1084 {
1085 deserializer.deserialize_float(FloatVisitor)
1086 }
1087}
1088
1089impl<'de> PodDeserialize<'de> for f64 {
1090 fn deserialize(
1091 deserializer: PodDeserializer<'de>,
1092 ) -> Result<
1093 (Self, deserialize::DeserializeSuccess<'de>),
1094 deserialize::DeserializeError<&'de [u8]>,
1095 >
1096 where
1097 Self: Sized,
1098 {
1099 deserializer.deserialize_double(DoubleVisitor)
1100 }
1101}
1102
1103impl<'de> PodDeserialize<'de> for Rectangle {
1104 fn deserialize(
1105 deserializer: PodDeserializer<'de>,
1106 ) -> Result<
1107 (Self, deserialize::DeserializeSuccess<'de>),
1108 deserialize::DeserializeError<&'de [u8]>,
1109 >
1110 where
1111 Self: Sized,
1112 {
1113 deserializer.deserialize_rectangle(RectangleVisitor)
1114 }
1115}
1116
1117impl<'de> PodDeserialize<'de> for Fraction {
1118 fn deserialize(
1119 deserializer: PodDeserializer<'de>,
1120 ) -> Result<
1121 (Self, deserialize::DeserializeSuccess<'de>),
1122 deserialize::DeserializeError<&'de [u8]>,
1123 >
1124 where
1125 Self: Sized,
1126 {
1127 deserializer.deserialize_fraction(FractionVisitor)
1128 }
1129}
1130
1131impl<'de> PodDeserialize<'de> for Id {
1132 fn deserialize(
1133 deserializer: PodDeserializer<'de>,
1134 ) -> Result<
1135 (Self, deserialize::DeserializeSuccess<'de>),
1136 deserialize::DeserializeError<&'de [u8]>,
1137 >
1138 where
1139 Self: Sized,
1140 {
1141 deserializer.deserialize_id(IdVisitor)
1142 }
1143}
1144
1145impl<'de> PodDeserialize<'de> for Fd {
1146 fn deserialize(
1147 deserializer: PodDeserializer<'de>,
1148 ) -> Result<
1149 (Self, deserialize::DeserializeSuccess<'de>),
1150 deserialize::DeserializeError<&'de [u8]>,
1151 >
1152 where
1153 Self: Sized,
1154 {
1155 deserializer.deserialize_fd(FdVisitor)
1156 }
1157}
1158
1159impl<'de> PodDeserialize<'de> for Choice<bool> {
1160 fn deserialize(
1161 deserializer: PodDeserializer<'de>,
1162 ) -> Result<
1163 (Self, deserialize::DeserializeSuccess<'de>),
1164 deserialize::DeserializeError<&'de [u8]>,
1165 >
1166 where
1167 Self: Sized,
1168 {
1169 deserializer.deserialize_choice(ChoiceBoolVisitor)
1170 }
1171}
1172
1173impl<'de> PodDeserialize<'de> for Choice<i32> {
1174 fn deserialize(
1175 deserializer: PodDeserializer<'de>,
1176 ) -> Result<
1177 (Self, deserialize::DeserializeSuccess<'de>),
1178 deserialize::DeserializeError<&'de [u8]>,
1179 >
1180 where
1181 Self: Sized,
1182 {
1183 deserializer.deserialize_choice(ChoiceIntVisitor)
1184 }
1185}
1186
1187impl<'de> PodDeserialize<'de> for Choice<i64> {
1188 fn deserialize(
1189 deserializer: PodDeserializer<'de>,
1190 ) -> Result<
1191 (Self, deserialize::DeserializeSuccess<'de>),
1192 deserialize::DeserializeError<&'de [u8]>,
1193 >
1194 where
1195 Self: Sized,
1196 {
1197 deserializer.deserialize_choice(ChoiceLongVisitor)
1198 }
1199}
1200
1201impl<'de> PodDeserialize<'de> for Choice<f32> {
1202 fn deserialize(
1203 deserializer: PodDeserializer<'de>,
1204 ) -> Result<
1205 (Self, deserialize::DeserializeSuccess<'de>),
1206 deserialize::DeserializeError<&'de [u8]>,
1207 >
1208 where
1209 Self: Sized,
1210 {
1211 deserializer.deserialize_choice(ChoiceFloatVisitor)
1212 }
1213}
1214
1215impl<'de> PodDeserialize<'de> for Choice<f64> {
1216 fn deserialize(
1217 deserializer: PodDeserializer<'de>,
1218 ) -> Result<
1219 (Self, deserialize::DeserializeSuccess<'de>),
1220 deserialize::DeserializeError<&'de [u8]>,
1221 >
1222 where
1223 Self: Sized,
1224 {
1225 deserializer.deserialize_choice(ChoiceDoubleVisitor)
1226 }
1227}
1228
1229impl<'de> PodDeserialize<'de> for Choice<Id> {
1230 fn deserialize(
1231 deserializer: PodDeserializer<'de>,
1232 ) -> Result<
1233 (Self, deserialize::DeserializeSuccess<'de>),
1234 deserialize::DeserializeError<&'de [u8]>,
1235 >
1236 where
1237 Self: Sized,
1238 {
1239 deserializer.deserialize_choice(ChoiceIdVisitor)
1240 }
1241}
1242
1243impl<'de> PodDeserialize<'de> for Choice<Rectangle> {
1244 fn deserialize(
1245 deserializer: PodDeserializer<'de>,
1246 ) -> Result<
1247 (Self, deserialize::DeserializeSuccess<'de>),
1248 deserialize::DeserializeError<&'de [u8]>,
1249 >
1250 where
1251 Self: Sized,
1252 {
1253 deserializer.deserialize_choice(ChoiceRectangleVisitor)
1254 }
1255}
1256
1257impl<'de> PodDeserialize<'de> for Choice<Fraction> {
1258 fn deserialize(
1259 deserializer: PodDeserializer<'de>,
1260 ) -> Result<
1261 (Self, deserialize::DeserializeSuccess<'de>),
1262 deserialize::DeserializeError<&'de [u8]>,
1263 >
1264 where
1265 Self: Sized,
1266 {
1267 deserializer.deserialize_choice(ChoiceFractionVisitor)
1268 }
1269}
1270
1271impl<'de> PodDeserialize<'de> for Choice<Fd> {
1272 fn deserialize(
1273 deserializer: PodDeserializer<'de>,
1274 ) -> Result<
1275 (Self, deserialize::DeserializeSuccess<'de>),
1276 deserialize::DeserializeError<&'de [u8]>,
1277 >
1278 where
1279 Self: Sized,
1280 {
1281 deserializer.deserialize_choice(ChoiceFdVisitor)
1282 }
1283}
1284
1285impl<'de, T> PodDeserialize<'de> for (u32, *const T) {
1286 fn deserialize(
1287 deserializer: PodDeserializer<'de>,
1288 ) -> Result<
1289 (Self, deserialize::DeserializeSuccess<'de>),
1290 deserialize::DeserializeError<&'de [u8]>,
1291 >
1292 where
1293 Self: Sized,
1294 {
1295 deserializer.deserialize_pointer(PointerVisitor::<T>::default())
1296 }
1297}
1298
1299impl<'de> PodDeserialize<'de> for Value {
1300 fn deserialize(
1301 deserializer: PodDeserializer<'de>,
1302 ) -> Result<
1303 (Self, deserialize::DeserializeSuccess<'de>),
1304 deserialize::DeserializeError<&'de [u8]>,
1305 >
1306 where
1307 Self: Sized,
1308 {
1309 deserializer.deserialize_any()
1310 }
1311}
1312
1313#[derive(Debug, Clone, PartialEq)]
1315pub enum Value {
1316 None,
1318 Bool(bool),
1320 Id(Id),
1322 Int(i32),
1324 Long(i64),
1326 Float(f32),
1328 Double(f64),
1330 String(String),
1332 Bytes(Vec<u8>),
1334 Rectangle(Rectangle),
1336 Fraction(Fraction),
1338 Fd(Fd),
1340 ValueArray(ValueArray),
1342 Struct(Vec<Value>),
1344 Object(Object),
1346 Choice(ChoiceValue),
1348 Pointer(u32, *const c_void),
1350}
1351
1352#[derive(Debug, Clone, PartialEq)]
1354pub enum ValueArray {
1355 None(Vec<()>),
1357 Bool(Vec<bool>),
1359 Id(Vec<Id>),
1361 Int(Vec<i32>),
1363 Long(Vec<i64>),
1365 Float(Vec<f32>),
1367 Double(Vec<f64>),
1369 Rectangle(Vec<Rectangle>),
1371 Fraction(Vec<Fraction>),
1373 Fd(Vec<Fd>),
1375}
1376
1377#[derive(Debug, Clone, PartialEq)]
1379pub enum ChoiceValue {
1380 Bool(Choice<bool>),
1382 Int(Choice<i32>),
1384 Long(Choice<i64>),
1386 Float(Choice<f32>),
1388 Double(Choice<f64>),
1390 Id(Choice<Id>),
1392 Rectangle(Choice<Rectangle>),
1394 Fraction(Choice<Fraction>),
1396 Fd(Choice<Fd>),
1398}
1399
1400#[derive(Debug, Clone, PartialEq)]
1402pub struct Object {
1403 pub type_: u32,
1405 pub id: u32,
1407 pub properties: Vec<Property>,
1409}
1410
1411#[doc(hidden)]
1436#[macro_export]
1437macro_rules! __object__ {
1438 ($type_:expr, $id:expr, $($properties:expr),* $(,)?) => {
1439 pipewire::spa::pod::Object {
1440 type_: $type_.as_raw(),
1441 id: $id.as_raw(),
1442 properties: [ $( $properties, )* ].to_vec(),
1443 }
1444 };
1445}
1446#[doc(inline)]
1447pub use __object__ as object;
1448
1449#[derive(Debug, Clone, PartialEq)]
1451pub struct Property {
1452 pub key: u32,
1454 pub flags: PropertyFlags,
1456 pub value: Value,
1458}
1459
1460impl Property {
1461 pub fn new(key: u32, value: Value) -> Self {
1462 Self {
1463 key,
1464 value,
1465 flags: PropertyFlags::empty(),
1466 }
1467 }
1468}
1469
1470bitflags! {
1471 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
1473 pub struct PropertyFlags: u32 {
1474 const READONLY = spa_sys::SPA_POD_PROP_FLAG_READONLY;
1478 const HARDWARE = spa_sys::SPA_POD_PROP_FLAG_HARDWARE;
1480 const HINT_DICT = spa_sys::SPA_POD_PROP_FLAG_HINT_DICT;
1482 const MANDATORY = spa_sys::SPA_POD_PROP_FLAG_MANDATORY;
1484 #[cfg(feature = "v0_3_33")]
1486 const DONT_FIXATE = spa_sys::SPA_POD_PROP_FLAG_DONT_FIXATE;
1487 }
1488}
1489
1490#[doc(hidden)]
1512#[macro_export]
1513macro_rules! __property__ {
1514 ($key:expr, $value:expr) => {
1515 pipewire::spa::pod::Property {
1516 key: $key.as_raw(),
1517 flags: pipewire::spa::pod::PropertyFlags::empty(),
1518 value: $value,
1519 }
1520 };
1521
1522 ($key:expr, Id, $value:expr) => {
1523 pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::Id(pipewire::spa::utils::Id($value.as_raw())))
1524 };
1525
1526 ($key:expr, $type_:ident, $value:expr) => {
1527 pipewire::spa::pod::property!($key, pipewire::spa::pod::Value::$type_($value))
1528 };
1529
1530 ($key:expr, Choice, Enum, Id, $default:expr, $($alternative:expr),+ $(,)?) => {
1531 pipewire::spa::pod::property!(
1532 $key,
1533 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::Id(
1534 pipewire::spa::utils::Choice::<pipewire::spa::utils::Id>(
1535 pipewire::spa::utils::ChoiceFlags::empty(),
1536 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::Id>::Enum {
1537 default: pipewire::spa::utils::Id($default.as_raw()),
1538 alternatives: [ $( pipewire::spa::utils::Id($alternative.as_raw()), )+ ].to_vec()
1539 }
1540 )
1541 ))
1542 )
1543 };
1544
1545 ($key:expr, Choice, Enum, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
1546 pipewire::spa::pod::property!(
1547 $key,
1548 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1549 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1550 pipewire::spa::utils::ChoiceFlags::empty(),
1551 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Enum {
1552 default: $default,
1553 alternatives: [ $( $alternative, )+ ].to_vec()
1554 }
1555 )
1556 ))
1557 )
1558 };
1559
1560 ($key:expr, Choice, Flags, $type_:ident, $default:expr, $($alternative:expr),+ $(,)?) => {
1561 pipewire::spa::pod::property!(
1562 $key,
1563 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1564 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1565 pipewire::spa::utils::ChoiceFlags::empty(),
1566 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Flags {
1567 default: $default,
1568 flags: [ $( $alternative, )+ ].to_vec()
1569 }
1570 )
1571 ))
1572 )
1573 };
1574
1575 ($key:expr, Choice, Step, $type_:ident, $default:expr, $min:expr, $max:expr, $step:expr) => {
1576 pipewire::spa::pod::property!(
1577 $key,
1578 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1579 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1580 pipewire::spa::utils::ChoiceFlags::empty(),
1581 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Step {
1582 default: $default,
1583 min: $min,
1584 max: $max,
1585 step: $step,
1586 }
1587 )
1588 ))
1589 )
1590 };
1591
1592 ($key:expr, Choice, Range, $type_:ident, $default:expr, $min:expr, $max:expr) => {
1593 pipewire::spa::pod::property!(
1594 $key,
1595 pipewire::spa::pod::Value::Choice(pipewire::spa::pod::ChoiceValue::$type_(
1596 pipewire::spa::utils::Choice::<pipewire::spa::utils::$type_>(
1597 pipewire::spa::utils::ChoiceFlags::empty(),
1598 pipewire::spa::utils::ChoiceEnum::<pipewire::spa::utils::$type_>::Range {
1599 default: $default,
1600 min: $min,
1601 max: $max,
1602 }
1603 )
1604 ))
1605 )
1606 };
1607}
1608#[doc(inline)]
1609pub use __property__ as property;