1use std::{
5 ffi::{c_char, c_double, c_float, c_void, CStr},
6 marker::PhantomData,
7 mem::MaybeUninit,
8};
9
10use nix::errno::Errno;
11
12use crate::utils::{Fraction, Id, Rectangle};
13
14#[repr(transparent)]
19pub struct Parser<'d> {
20 parser: spa_sys::spa_pod_parser,
21 data: PhantomData<&'d [u8]>,
22}
23
24impl<'d> Parser<'d> {
25 pub fn new(data: &'d [u8]) -> Self {
26 unsafe {
27 let mut parser: MaybeUninit<spa_sys::spa_pod_parser> = MaybeUninit::uninit();
28 spa_sys::spa_pod_parser_init(
29 parser.as_mut_ptr(),
30 data.as_ptr().cast(),
31 data.len()
32 .try_into()
33 .expect("data length does not fit in a u32"),
34 );
35 Self {
36 parser: parser.assume_init(),
37 data: PhantomData,
38 }
39 }
40 }
41
42 pub fn from_pod(pod: &'d crate::pod::Pod) -> Self {
43 unsafe {
44 let mut parser: MaybeUninit<spa_sys::spa_pod_parser> = MaybeUninit::uninit();
45 spa_sys::spa_pod_parser_pod(parser.as_mut_ptr(), pod.as_raw_ptr());
46 Self {
47 parser: parser.assume_init(),
48 data: PhantomData,
49 }
50 }
51 }
52
53 pub fn as_raw(&self) -> &spa_sys::spa_pod_parser {
54 &self.parser
55 }
56
57 pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod_parser {
58 std::ptr::addr_of!(self.parser).cast_mut()
59 }
60
61 pub fn into_raw(self) -> spa_sys::spa_pod_parser {
62 self.parser
63 }
64
65 pub unsafe fn state(&self) -> spa_sys::spa_pod_parser_state {
70 let mut state: MaybeUninit<spa_sys::spa_pod_parser_state> = MaybeUninit::uninit();
71 spa_sys::spa_pod_parser_get_state(self.as_raw_ptr(), state.as_mut_ptr());
72 state.assume_init()
73 }
74
75 pub unsafe fn reset(&mut self, state: *mut spa_sys::spa_pod_parser_state) {
79 spa_sys::spa_pod_parser_reset(self.as_raw_ptr(), state)
80 }
81
82 pub unsafe fn deref(&mut self, offset: u32, size: u32) -> *mut spa_sys::spa_pod {
86 spa_sys::spa_pod_parser_deref(self.as_raw_ptr(), offset, size)
87 }
88
89 pub unsafe fn frame(&mut self, frame: *mut spa_sys::spa_pod_frame) -> *mut spa_sys::spa_pod {
93 spa_sys::spa_pod_parser_frame(self.as_raw_ptr(), frame)
94 }
95
96 pub unsafe fn push(
100 &mut self,
101 frame: *mut spa_sys::spa_pod_frame,
102 pod: *const spa_sys::spa_pod,
103 offset: u32,
104 ) {
105 spa_sys::spa_pod_parser_push(self.as_raw_ptr(), frame, pod, offset)
106 }
107
108 pub fn current(&mut self) -> *mut spa_sys::spa_pod {
109 unsafe { spa_sys::spa_pod_parser_current(self.as_raw_ptr()) }
110 }
111
112 pub unsafe fn advance(&mut self, pod: *const spa_sys::spa_pod) {
118 spa_sys::spa_pod_parser_advance(self.as_raw_ptr(), pod)
119 }
120
121 pub unsafe fn next(&mut self) -> *mut spa_sys::spa_pod {
125 spa_sys::spa_pod_parser_next(self.as_raw_ptr())
126 }
127
128 pub unsafe fn pop(&mut self, frame: &mut spa_sys::spa_pod_frame) -> Result<(), Errno> {
132 let res = spa_sys::spa_pod_parser_pop(self.as_raw_ptr(), frame as *mut _);
133
134 if res >= 0 {
135 Ok(())
136 } else {
137 Err(Errno::from_raw(-res))
138 }
139 }
140
141 pub fn get_bool(&mut self) -> Result<bool, Errno> {
142 unsafe {
143 let mut b: MaybeUninit<bool> = MaybeUninit::uninit();
144 let res = spa_sys::spa_pod_parser_get_bool(self.as_raw_ptr(), b.as_mut_ptr());
145 if res >= 0 {
146 Ok(b.assume_init())
147 } else {
148 Err(Errno::from_raw(-res))
149 }
150 }
151 }
152
153 pub fn get_id(&mut self) -> Result<Id, Errno> {
154 unsafe {
155 let mut id: MaybeUninit<u32> = MaybeUninit::uninit();
156 let res = spa_sys::spa_pod_parser_get_id(self.as_raw_ptr(), id.as_mut_ptr());
157 if res >= 0 {
158 Ok(Id(id.assume_init()))
159 } else {
160 Err(Errno::from_raw(-res))
161 }
162 }
163 }
164
165 pub fn get_int(&mut self) -> Result<i32, Errno> {
166 unsafe {
167 let mut int: MaybeUninit<i32> = MaybeUninit::uninit();
168 let res = spa_sys::spa_pod_parser_get_int(self.as_raw_ptr(), int.as_mut_ptr());
169 if res >= 0 {
170 Ok(int.assume_init())
171 } else {
172 Err(Errno::from_raw(-res))
173 }
174 }
175 }
176
177 pub fn get_long(&mut self) -> Result<i64, Errno> {
178 unsafe {
179 let mut long: MaybeUninit<i64> = MaybeUninit::uninit();
180 let res = spa_sys::spa_pod_parser_get_long(self.as_raw_ptr(), long.as_mut_ptr());
181 if res >= 0 {
182 Ok(long.assume_init())
183 } else {
184 Err(Errno::from_raw(-res))
185 }
186 }
187 }
188
189 pub fn get_float(&mut self) -> Result<c_float, Errno> {
190 unsafe {
191 let mut float: MaybeUninit<c_float> = MaybeUninit::uninit();
192 let res = spa_sys::spa_pod_parser_get_float(self.as_raw_ptr(), float.as_mut_ptr());
193 if res >= 0 {
194 Ok(float.assume_init())
195 } else {
196 Err(Errno::from_raw(-res))
197 }
198 }
199 }
200
201 pub fn get_double(&mut self) -> Result<c_double, Errno> {
202 unsafe {
203 let mut double: MaybeUninit<c_double> = MaybeUninit::uninit();
204 let res = spa_sys::spa_pod_parser_get_double(self.as_raw_ptr(), double.as_mut_ptr());
205 if res >= 0 {
206 Ok(double.assume_init())
207 } else {
208 Err(Errno::from_raw(-res))
209 }
210 }
211 }
212
213 pub fn get_string_raw(&mut self) -> Result<&'d CStr, Errno> {
214 unsafe {
215 let mut string: MaybeUninit<*const c_char> = MaybeUninit::uninit();
216 let res = spa_sys::spa_pod_parser_get_string(self.as_raw_ptr(), string.as_mut_ptr());
217 if res >= 0 {
218 let string = string.assume_init();
219 let string = CStr::from_ptr(string);
221 Ok(string)
222 } else {
223 Err(Errno::from_raw(-res))
224 }
225 }
226 }
227
228 pub fn get_bytes(&mut self) -> Result<&'d [u8], Errno> {
229 unsafe {
230 let mut bytes: MaybeUninit<*const u8> = MaybeUninit::uninit();
231 let mut len: MaybeUninit<u32> = MaybeUninit::uninit();
232 let res = spa_sys::spa_pod_parser_get_bytes(
233 self.as_raw_ptr(),
234 bytes.as_mut_ptr().cast(),
235 len.as_mut_ptr(),
236 );
237 if res >= 0 {
238 let bytes = bytes.assume_init();
239 let len = len.assume_init();
240 let bytes = std::slice::from_raw_parts(bytes, len.try_into().unwrap());
242 Ok(bytes)
243 } else {
244 Err(Errno::from_raw(-res))
245 }
246 }
247 }
248
249 pub fn get_pointer(&mut self) -> Result<(*const c_void, Id), Errno> {
250 unsafe {
251 let mut ptr: MaybeUninit<*const c_void> = MaybeUninit::uninit();
252 let mut type_: MaybeUninit<u32> = MaybeUninit::uninit();
253 let res = spa_sys::spa_pod_parser_get_pointer(
254 self.as_raw_ptr(),
255 type_.as_mut_ptr(),
256 ptr.as_mut_ptr(),
257 );
258 if res >= 0 {
259 Ok((ptr.assume_init(), Id(type_.assume_init())))
260 } else {
261 Err(Errno::from_raw(-res))
262 }
263 }
264 }
265
266 pub fn get_fd(&mut self) -> Result<i64, Errno> {
267 unsafe {
268 let mut fd: MaybeUninit<i64> = MaybeUninit::uninit();
269 let res = spa_sys::spa_pod_parser_get_fd(self.as_raw_ptr(), fd.as_mut_ptr());
270 if res >= 0 {
271 Ok(fd.assume_init())
272 } else {
273 Err(Errno::from_raw(-res))
274 }
275 }
276 }
277
278 pub fn get_rectangle(&mut self) -> Result<Rectangle, Errno> {
279 unsafe {
280 let mut rect: MaybeUninit<spa_sys::spa_rectangle> = MaybeUninit::uninit();
281 let res = spa_sys::spa_pod_parser_get_rectangle(self.as_raw_ptr(), rect.as_mut_ptr());
282 if res >= 0 {
283 Ok(rect.assume_init())
284 } else {
285 Err(Errno::from_raw(-res))
286 }
287 }
288 }
289
290 pub fn get_fraction(&mut self) -> Result<Fraction, Errno> {
291 unsafe {
292 let mut frac: MaybeUninit<spa_sys::spa_fraction> = MaybeUninit::uninit();
293 let res = spa_sys::spa_pod_parser_get_fraction(self.as_raw_ptr(), frac.as_mut_ptr());
294 if res >= 0 {
295 Ok(frac.assume_init())
296 } else {
297 Err(Errno::from_raw(-res))
298 }
299 }
300 }
301
302 pub fn get_pod(&mut self) -> Result<&'d crate::pod::Pod, Errno> {
303 unsafe {
304 let mut pod: MaybeUninit<*mut spa_sys::spa_pod> = MaybeUninit::uninit();
305 let res = spa_sys::spa_pod_parser_get_pod(self.as_raw_ptr(), pod.as_mut_ptr());
306 if res >= 0 {
307 let pod = crate::pod::Pod::from_raw(pod.assume_init());
311
312 Ok(pod)
313 } else {
314 Err(Errno::from_raw(-res))
315 }
316 }
317 }
318
319 pub unsafe fn push_struct(
324 &mut self,
325 frame: &mut MaybeUninit<spa_sys::spa_pod_frame>,
326 ) -> Result<(), Errno> {
327 let res = spa_sys::spa_pod_parser_push_struct(self.as_raw_ptr(), frame.as_mut_ptr());
328
329 if res >= 0 {
330 Ok(())
331 } else {
332 Err(Errno::from_raw(-res))
333 }
334 }
335
336 pub unsafe fn push_object(
341 &mut self,
342 frame: &mut MaybeUninit<spa_sys::spa_pod_frame>,
343 _type: u32,
344 ) -> Result<Id, Errno> {
345 let mut id: MaybeUninit<u32> = MaybeUninit::uninit();
346 let res = spa_sys::spa_pod_parser_push_object(
347 self.as_raw_ptr(),
348 frame.as_mut_ptr(),
349 _type,
350 id.as_mut_ptr(),
351 );
352
353 if res >= 0 {
354 Ok(Id(id.assume_init()))
355 } else {
356 Err(Errno::from_raw(-res))
357 }
358 }
359}
360
361#[macro_export]
396macro_rules! __parser_get__ {
397 ($parser:expr, Bool($val:expr)) => {
398 {
399 let val: &mut bool = $val;
400 let res = $crate::pod::parser::Parser::get_bool($parser);
401 if let Ok(bool) = res {
402 *val = bool;
403 }
404 res.map(|_| {})
405 }
406 };
407 ($parser:expr, Id($val:expr)) => {
408 {
409 let val: &mut $crate::utils::Id = $val;
410 let res = $crate::pod::parser::Parser::get_id($parser);
411 if let Ok(id) = res {
412 *val = id;
413 }
414 res.map(|_| {})
415 }
416 };
417 ($parser:expr, Int($val:expr)) => {
418 {
419 let val: &mut i32 = $val;
420 let res = $crate::pod::parser::Parser::get_int($parser);
421 if let Ok(int) = res {
422 *val = int;
423 }
424 res.map(|_| {})
425 }
426 };
427 ($parser:expr, Long($val:expr)) => {
428 {
429 let val: &mut i64 = $val;
430 let res = $crate::pod::parser::Parser::get_long($parser);
431 if let Ok(long) = res {
432 *val = long;
433 }
434 res.map(|_| {})
435 }
436 };
437 ($parser:expr, Float($val:expr)) => {
438 {
439 let val: &mut f32 = $val;
440 let res = $crate::pod::parser::Parser::get_float($parser);
441 if let Ok(float) = res {
442 *val = float;
443 }
444 res.map(|_| {})
445 }
446 };
447 ($parser:expr, Double($val:expr)) => {
448 {
449 let val: &mut f64 = $val;
450 let res = $crate::pod::parser::Parser::get_double($parser);
451 if let Ok(double) = res {
452 *val = double;
453 }
454 res.map(|_| {})
455 }
456 };
457 ($parser:expr, Bytes($val:expr)) => {
459 {
460 let val: &mut &[u8] = $val;
461 let res = $crate::pod::parser::Parser::get_bytes($parser);
462 if let Ok(bytes) = res {
463 *val = bytes;
464 }
465 res.map(|_| {})
466 }
467 };
468 ($parser:expr, Pointer($val:expr)) => {
469 {
470 let val: &mut (*const c_void, Id) = $val;
471 let res = $crate::pod::parser::Parser::get_pointer($parser);
472 if let Ok(ptr) = res {
473 *val = ptr;
474 }
475 res.map(|_| {})
476 }
477 };
478 ($parser:expr, Fd($val:expr)) => {
479 {
480 let val: &mut i64 = $val;
481 let res = $crate::pod::parser::Parser::get_fd($parser);
482 if let Ok(fd) = res {
483 *val = fd;
484 }
485 res.map(|_| {})
486 }
487 };
488 ($parser:expr, Rectangle($val:expr)) => {
489 {
490 let val: &mut $crate::utils::Rectangle = $val;
491 let res = $crate::pod::parser::Parser::get_rectangle($parser);
492 if let Ok(rect) = res {
493 *val = rect;
494 }
495 res.map(|_| {})
496 }
497 };
498 ($parser:expr, Fraction($val:expr)) => {
499 {
500 let val: &mut $crate::utils::Fraction = $val;
501 let res = $crate::pod::parser::Parser::get_fraction($parser);
502 if let Ok(fraction) = res {
503 *val = fraction;
504 }
505 res.map(|_| {})
506 }
507 };
508 ($parser:expr, Pod($val:expr)) => {
509 {
510 let val: &mut $crate::pod::Pod = $val;
511 let res = $crate::pod::parser::Parser::get_pod($parser);
512 if let Ok(pod) = res {
513 *val = pod;
514 }
515 res.map(|_| {})
516 }
517 };
518 ($parser:expr, Struct { $( $field_type:tt $field:tt ),* $(,)? }) => {
519 'outer: {
520 if false {
522 let _ = $parser;
523 }
524
525 let mut frame: ::std::mem::MaybeUninit<$crate::sys::spa_pod_frame> = ::std::mem::MaybeUninit::uninit();
526 let res = unsafe { $crate::pod::parser::Parser::push_struct($parser, &mut frame) };
527 if res.is_err() {
528 break 'outer res;
529 }
530
531 $(
532 let res = $crate::__parser_get__!($parser, $field_type $field);
533 if res.is_err() {
534 break 'outer res.map(|_| {});
536 }
537 )*
538
539 unsafe { $crate::pod::parser::Parser::pop($parser, frame.assume_init_mut()) }
540 }
541 };
542 }
545pub use __parser_get__ as parser_get;
546
547#[cfg(test)]
548mod tests {
549 use super::{parser_get, Parser};
550
551 #[test]
555 #[cfg_attr(miri, ignore)]
556 fn parse_bool() {
557 let pod: Vec<u8> = [
558 &4u32.to_ne_bytes(), &2u32.to_ne_bytes(), &1u32.to_ne_bytes(), &[0, 0, 0, 0], ]
563 .into_iter()
564 .flatten()
565 .copied()
566 .collect();
567
568 let mut parser = Parser::new(&pod);
569 let mut bool = false;
570
571 let res = parser_get!(&mut parser, Bool(&mut bool));
572
573 assert!(res.is_ok());
574 assert!(bool);
575 }
576
577 #[test]
578 #[cfg_attr(miri, ignore)]
579 fn parse_empty_struct() {
580 let pod: Vec<u8> = [
581 &0u32.to_ne_bytes(), &14u32.to_ne_bytes(), ]
584 .into_iter()
585 .flatten()
586 .copied()
587 .collect();
588
589 let mut parser = Parser::new(&pod);
590
591 let res = parser_get!(&mut parser, Struct {});
592
593 assert!(res.is_ok());
594 }
595
596 #[test]
597 #[cfg_attr(miri, ignore)]
598 fn parse_complicated_struct() {
599 let pod: &[&[u8]] = &[
600 &168u32.to_ne_bytes(), &14u32.to_ne_bytes(), &96u32.to_ne_bytes(), &14u32.to_ne_bytes(), &4u32.to_ne_bytes(), &2u32.to_ne_bytes(), &1u32.to_ne_bytes(), &[0, 0, 0, 0], &4u32.to_ne_bytes(), &3u32.to_ne_bytes(), &313u32.to_ne_bytes(), &[0, 0, 0, 0], &4u32.to_ne_bytes(), &4u32.to_ne_bytes(), &313i32.to_ne_bytes(), &[0, 0, 0, 0], &8u32.to_ne_bytes(), &5u32.to_ne_bytes(), &313i64.to_ne_bytes(), &4u32.to_ne_bytes(), &6u32.to_ne_bytes(), &31.3f32.to_ne_bytes(), &[0, 0, 0, 0], &8u32.to_ne_bytes(), &7u32.to_ne_bytes(), &31.3f64.to_ne_bytes(), &3u32.to_ne_bytes(), &9u32.to_ne_bytes(), &[3, 1, 3], &[0, 0, 0, 0, 0], &8u32.to_ne_bytes(), &18u32.to_ne_bytes(), &313i64.to_ne_bytes(), &8u32.to_ne_bytes(), &10u32.to_ne_bytes(), &313u32.to_ne_bytes(), &131u32.to_ne_bytes(), &8u32.to_ne_bytes(), &11u32.to_ne_bytes(), &313u32.to_ne_bytes(), &131u32.to_ne_bytes(), ];
644 let pod: Vec<u8> = pod.iter().flat_map(|f| *f).copied().collect();
645
646 let mut parser = Parser::new(&pod);
647
648 let mut bool = false;
649 let mut id = crate::utils::Id(0);
650 let mut int = 0i32;
651 let mut long = 0i64;
652 let mut float = 0.0f32;
653 let mut double = 0.0f64;
654 let mut bytes: &[u8] = &[];
655 let mut fd = 0i64;
656 let mut rect = crate::utils::Rectangle {
657 width: 0,
658 height: 0,
659 };
660 let mut frac = crate::utils::Fraction { num: 0, denom: 1 };
661
662 let res = parser_get!(
663 &mut parser,
664 Struct {
665 Struct {
666 Bool(&mut bool),
667 Id(&mut id),
668 Int(&mut int),
669 Long(&mut long),
670 Float(&mut float),
671 Double(&mut double),
672 },
673 Bytes(&mut bytes),
674 Fd(&mut fd),
675 Rectangle(&mut rect),
676 Fraction(&mut frac),
677 }
678 );
679
680 assert!(res.is_ok());
681 assert!(bool);
682 assert_eq!(id, crate::utils::Id(313));
683 assert_eq!(int, 313);
684 assert_eq!(long, 313);
685 assert_eq!(float, 31.3);
686 assert_eq!(double, 31.3);
687 assert_eq!(bytes, &[3, 1, 3]);
688 assert_eq!(fd, 313);
689 assert_eq!(
690 rect,
691 crate::utils::Rectangle {
692 width: 313,
693 height: 131
694 }
695 );
696 assert_eq!(
697 frac,
698 crate::utils::Fraction {
699 num: 313,
700 denom: 131
701 }
702 );
703 }
704}