diff --git a/Cargo.toml b/Cargo.toml index 1f2cc3e..df2d682 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ version = "0.3.2" version = "0.2" [dependencies.nix] -version = "0.27" +version = "0.29" [dependencies.nom] version = "7" diff --git a/src/lib.rs b/src/lib.rs index 398658b..6b7c995 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,9 @@ // SPDX-License-Identifier: MIT //! The `libspa` crate provides a high-level API to interact with -//! [libspa](https://gitlab.freedesktop.org/pipewire/pipewire/-/tree/master/doc/spa). +//! [libspa]. +//! +//! [libspa]: https://docs.pipewire.org/page_spa.html pub mod buffer; pub mod param; @@ -11,6 +13,3 @@ pub mod support; pub mod utils; pub use spa_sys as sys; - -/// prelude module re-exporing all the traits providing public API. -pub mod prelude {} diff --git a/src/param/audio/mod.rs b/src/param/audio/mod.rs index 017fc09..f6d731d 100644 --- a/src/param/audio/mod.rs +++ b/src/param/audio/mod.rs @@ -51,6 +51,17 @@ impl AudioFormat { pub const ULAW: Self = Self(spa_sys::SPA_AUDIO_FORMAT_ULAW); pub const ALAW: Self = Self(spa_sys::SPA_AUDIO_FORMAT_ALAW); + pub const S16: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16); + pub const U16: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U16); + pub const S18: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S18); + pub const U18: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U18); + pub const S20: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S20); + pub const U20: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U20); + pub const S24: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24); + pub const U24: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24); + pub const S32: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S32); + pub const U32: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U32); + pub const U8P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U8P); pub const S16P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16P); pub const S24_32P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_32P); diff --git a/src/pod/builder.rs b/src/pod/builder.rs index 138caec..d0209af 100644 --- a/src/pod/builder.rs +++ b/src/pod/builder.rs @@ -141,7 +141,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -163,7 +163,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -177,7 +177,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -189,7 +189,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -201,7 +201,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -213,7 +213,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -225,7 +225,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -237,7 +237,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -256,7 +256,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -274,7 +274,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -290,7 +290,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -302,7 +302,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -314,7 +314,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -326,7 +326,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -344,7 +344,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -370,7 +370,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -394,7 +394,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -412,7 +412,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -438,7 +438,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -449,7 +449,7 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -468,13 +468,14 @@ impl<'d> Builder<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } pub fn add_control(&mut self, offset: u32, type_: u32) -> c_int { // Older versions of pipewire mistakenly had the return type as uint32_t, // so we need to use try_into().unwrap() to ensure those versions also work + #[allow(clippy::useless_conversion)] unsafe { spa_sys::spa_pod_builder_control(self.as_raw_ptr(), offset, type_) .try_into() @@ -511,7 +512,7 @@ impl<'d> Builder<'d> { /// Bytes(<&[u8]>), /// } /// ); -/// builder_add(<&mut libspa::pod::builder::Builder>, +/// builder_add!(<&mut libspa::pod::builder::Builder>, /// Object( /// , /// diff --git a/src/pod/mod.rs b/src/pod/mod.rs index 98c21ee..9f51ded 100644 --- a/src/pod/mod.rs +++ b/src/pod/mod.rs @@ -17,6 +17,7 @@ use std::{ io::{Seek, Write}, mem::MaybeUninit, os::fd::RawFd, + ptr::addr_of, }; use bitflags::bitflags; @@ -89,7 +90,18 @@ impl Pod { } pub fn as_raw_ptr(&self) -> *mut spa_sys::spa_pod { - std::ptr::addr_of!(self.0).cast_mut() + addr_of!(self.0).cast_mut() + } + + /// Returns a pointer to the pods body. + /// + /// If the pod has an empty body, this can be outside the pods allocation. + pub fn body(&self) -> *mut c_void { + unsafe { + self.as_raw_ptr() + .byte_add(std::mem::size_of::()) + .cast() + } } /// Construct a pod from raw bytes. @@ -158,7 +170,7 @@ impl Pod { if res >= 0 { Ok(b.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -176,7 +188,7 @@ impl Pod { if res >= 0 { Ok(Id(id.assume_init())) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -194,7 +206,7 @@ impl Pod { if res >= 0 { Ok(int.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -212,7 +224,7 @@ impl Pod { if res >= 0 { Ok(long.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -230,7 +242,7 @@ impl Pod { if res >= 0 { Ok(float.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -248,7 +260,7 @@ impl Pod { if res >= 0 { Ok(double.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -278,7 +290,7 @@ impl Pod { let bytes = std::slice::from_raw_parts(bytes.cast(), len.try_into().unwrap()); Ok(bytes) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -303,7 +315,7 @@ impl Pod { let pointer = pointer.assume_init(); Ok((pointer, _type)) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -323,7 +335,7 @@ impl Pod { let fd: RawFd = fd.try_into().unwrap(); Ok(fd) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -341,7 +353,7 @@ impl Pod { if res >= 0 { Ok(rectangle.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -359,7 +371,7 @@ impl Pod { if res >= 0 { Ok(fraction.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -384,17 +396,324 @@ impl Pod { res != 0 } + pub fn as_struct(&self) -> Result<&PodStruct, Errno> { + if self.is_struct() { + // Safety: We already know that the pod is valid, and since it is a struct, we can + // safely create a PodStruct from it + 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 } + // TODO: spa_pod_is_object_type, spa_pod_is_object_id + + pub fn as_object(&self) -> Result<&PodObject, Errno> { + if self.is_object() { + // Safety: We already know that the pod is valid, and since it is an object, we can + // safely create a PodObject from it + 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() + } +} + +/// A transparent wrapper around a `spa_sys::spa_pod_struct`. +#[repr(transparent)] +pub struct PodStruct(spa_sys::spa_pod_struct); + +impl PodStruct { + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned pod of type struct. + /// + /// All restrictions from [`Pod::from_raw`] also apply here. + pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_struct) -> &'static Self { + pod.cast::().as_ref().unwrap() + } + + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned pod of type struct. + /// + /// All restrictions from [`Pod::from_raw_mut`] also apply here. + pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_struct) -> &'static mut Self { + pod.cast::().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 { + // Safety: Since this is a valid spa_pod_object, it must also be a valid spa_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 { + value.as_struct() + } +} + +impl AsRef 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 { + // Check if the iterator has at least one element left that we can return + 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) }; + + // Advance iter to next property + self.next = unsafe { spa_sys::spa_pod_next(self.next) }; + + Some(res) + } else { + None + } + } +} + +/// A transparent wrapper around a `spa_sys::spa_pod_object`. +#[repr(transparent)] +pub struct PodObject(spa_sys::spa_pod_object); + +impl PodObject { + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned pod of type object. + /// + /// All restrictions from [`Pod::from_raw`] also apply here. + pub unsafe fn from_raw(pod: *const spa_sys::spa_pod_object) -> &'static Self { + pod.cast::().as_ref().unwrap() + } + + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned pod of type object. + /// + /// All restrictions from [`Pod::from_raw_mut`] also apply here. + pub unsafe fn from_raw_mut(pod: *mut spa_sys::spa_pod_object) -> &'static mut Self { + pod.cast::().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 { + // Safety: Since this is a valid spa_pod_object, it must also be a valid spa_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, /* TODO: start, */ 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()) }; + // C implementation always returns 0 + } + + #[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 { + value.as_object() + } +} + +impl AsRef 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 { + // Check if the iterator has at least one element left that we can return + 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()) }; + + // Advance iter to next property + 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; + } +} + +/// A transparent wrapper around a `spa_sys::spa_pod_prop`. +#[repr(transparent)] +pub struct PodProp(spa_sys::spa_pod_prop); + +impl PodProp { + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned [`spa_sys::spa_pod_prop`]. + /// + /// While this struct doesn't represent a full pod, all restrictions from [`Pod::from_raw`] also apply + /// to this struct and the contained `value` pod. + pub unsafe fn from_raw(prop: *const spa_sys::spa_pod_prop) -> &'static Self { + prop.cast::().as_ref().unwrap() + } + + /// # Safety + /// + /// The provided pointer must point to a valid, well-aligned pod of type object. + /// + /// While this struct doesn't represent a full pod, all restrictions from [`Pod::from_raw`] also apply + /// to this struct and the contained `value` pod. + pub unsafe fn from_raw_mut(prop: *mut spa_sys::spa_pod_prop) -> &'static mut Self { + prop.cast::().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 { + // Safety: Since PodProp may only be constructed around valid Pods, the contained value must also be valid. + // We don't mutate the pod and neither can the returned reference. + // The returned lifetime is properly shortened by this methods signature. + unsafe { Pod::from_raw(addr_of!(self.0.value)) } + } +} + /// Implementors of this trait are the canonical representation of a specific type of fixed sized SPA pod. /// /// They can be used as an output type for [`FixedSizedPod`] implementors diff --git a/src/pod/parser.rs b/src/pod/parser.rs index a909d57..7203ce5 100644 --- a/src/pod/parser.rs +++ b/src/pod/parser.rs @@ -134,7 +134,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -145,7 +145,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(b.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -157,7 +157,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(Id(id.assume_init())) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -169,7 +169,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(int.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -181,7 +181,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(long.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -193,7 +193,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(float.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -205,7 +205,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(double.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -220,7 +220,7 @@ impl<'d> Parser<'d> { let string = CStr::from_ptr(string); Ok(string) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -241,7 +241,7 @@ impl<'d> Parser<'d> { let bytes = std::slice::from_raw_parts(bytes, len.try_into().unwrap()); Ok(bytes) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -258,7 +258,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok((ptr.assume_init(), Id(type_.assume_init()))) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -270,7 +270,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(fd.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -282,7 +282,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(rect.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -294,7 +294,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(frac.assume_init()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -311,7 +311,7 @@ impl<'d> Parser<'d> { Ok(pod) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } @@ -329,7 +329,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(()) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } @@ -353,7 +353,7 @@ impl<'d> Parser<'d> { if res >= 0 { Ok(Id(id.assume_init())) } else { - Err(Errno::from_i32(-res)) + Err(Errno::from_raw(-res)) } } } diff --git a/src/utils/dict.rs b/src/utils/dict.rs index 7c02cff..4e99133 100644 --- a/src/utils/dict.rs +++ b/src/utils/dict.rs @@ -102,7 +102,6 @@ impl DictRef { /// /// # Examples /// ``` - /// use libspa::prelude::*; /// use libspa::{utils::dict::StaticDict, static_dict}; /// /// static DICT: StaticDict = static_dict! { @@ -145,9 +144,7 @@ impl std::fmt::Debug for DictRef { impl<'a> fmt::Debug for Entries<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_map() - .entries(self.0.clone().map(|(k, v)| (k, v))) - .finish() + f.debug_map().entries(self.0.clone()).finish() } } @@ -392,7 +389,7 @@ macro_rules! static_dict { }; unsafe { - let ptr = &RAW as *const _ as *mut _; + let ptr = std::ptr::addr_of!(RAW).cast_mut(); StaticDict::from_ptr(ptr::NonNull::new_unchecked(ptr)) } }}; @@ -421,7 +418,7 @@ unsafe impl Sync for StaticDict {} mod tests { use super::{DictRef, Flags, StaticDict}; use spa_sys::spa_dict; - use std::{ffi::CString, ptr}; + use std::ptr; #[test] fn test_empty_dict() { @@ -447,20 +444,8 @@ mod tests { }; let mut iter = dict.iter_cstr(); - assert_eq!( - ( - CString::new("K0").unwrap().as_c_str(), - CString::new("V0").unwrap().as_c_str() - ), - iter.next().unwrap() - ); - assert_eq!( - ( - CString::new("K1").unwrap().as_c_str(), - CString::new("V1").unwrap().as_c_str() - ), - iter.next().unwrap() - ); + assert_eq!((c"K0", c"V0"), iter.next().unwrap()); + assert_eq!((c"K1", c"V1"), iter.next().unwrap()); assert_eq!(None, iter.next()); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index c0c4051..6aa83f2 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -144,7 +144,7 @@ impl SpaTypes { Self(raw) } - /// Get the raw [`c_uint`](std::os::raw::c_uint) representing this `SpaTypes`. + /// Get the raw [`c_uint`] representing this `SpaTypes`. pub fn as_raw(&self) -> c_uint { self.0 } diff --git a/src/utils/result.rs b/src/utils/result.rs index 83d1e87..8d06636 100644 --- a/src/utils/result.rs +++ b/src/utils/result.rs @@ -133,7 +133,7 @@ impl Error { fn new(e: i32) -> Self { assert!(e > 0); - Self(Errno::from_i32(e)) + Self(Errno::from_raw(e)) } }