pipewire/properties/
mod.rs1use std::{ffi::CString, fmt, ptr};
9
10mod box_;
11pub use box_::*;
12
13#[repr(transparent)]
22pub struct Properties(pw_sys::pw_properties);
23
24impl Properties {
25 pub fn as_raw(&self) -> &pw_sys::pw_properties {
26 &self.0
27 }
28
29 pub fn as_raw_ptr(&self) -> *mut pw_sys::pw_properties {
36 std::ptr::addr_of!(self.0).cast_mut()
37 }
38
39 pub fn dict(&self) -> &spa::utils::dict::DictRef {
40 unsafe { &*(&self.0.dict as *const spa_sys::spa_dict as *const spa::utils::dict::DictRef) }
41 }
42
43 pub fn to_owned(&self) -> PropertiesBox {
45 unsafe {
46 let ptr = pw_sys::pw_properties_copy(self.as_raw_ptr());
47 PropertiesBox::from_raw(ptr::NonNull::new_unchecked(ptr))
48 }
49 }
50
51 pub fn get(&self, key: &str) -> Option<&str> {
52 let key = CString::new(key).expect("key contains null byte");
53
54 let res =
55 unsafe { pw_sys::pw_properties_get(self.as_raw_ptr().cast_const(), key.as_ptr()) };
56
57 let res = if !res.is_null() {
58 unsafe { Some(std::ffi::CStr::from_ptr(res)) }
59 } else {
60 None
61 };
62
63 res.and_then(|res| res.to_str().ok())
65 }
66
67 pub fn insert<K, V>(&mut self, key: K, value: V)
68 where
69 K: Into<Vec<u8>>,
70 V: Into<Vec<u8>>,
71 {
72 let k = CString::new(key).unwrap();
73 let v = CString::new(value).unwrap();
74 unsafe { pw_sys::pw_properties_set(self.as_raw_ptr(), k.as_ptr(), v.as_ptr()) };
75 }
76
77 pub fn remove<T>(&mut self, key: T)
78 where
79 T: Into<Vec<u8>>,
80 {
81 let key = CString::new(key).unwrap();
82 unsafe { pw_sys::pw_properties_set(self.as_raw_ptr(), key.as_ptr(), std::ptr::null()) };
83 }
84
85 pub fn clear(&mut self) {
86 unsafe { pw_sys::pw_properties_clear(self.as_raw_ptr()) }
87 }
88}
89
90impl AsRef<spa::utils::dict::DictRef> for Properties {
91 fn as_ref(&self) -> &spa::utils::dict::DictRef {
92 self.dict()
93 }
94}
95
96impl fmt::Debug for Properties {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f.debug_tuple("Properties").field(self.as_ref()).finish()
100 }
101}
102
103impl<K, V> Extend<(K, V)> for Properties
104where
105 K: Into<Vec<u8>>,
106 V: Into<Vec<u8>>,
107{
108 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
109 for (k, v) in iter {
110 self.insert(k, v);
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn new() {
121 let props = properties! {
122 "K0" => "V0"
123 };
124
125 let mut iter = props.dict().iter();
126 assert_eq!(("K0", "V0"), iter.next().unwrap());
127 assert_eq!(None, iter.next());
128 }
129
130 #[test]
131 fn remove() {
132 let mut props = properties! {
133 "K0" => "V0"
134 };
135
136 assert_eq!(Some("V0"), props.dict().get("K0"));
137 props.remove("K0");
138 assert_eq!(None, props.dict().get("K0"));
139 }
140
141 #[test]
142 fn insert() {
143 let mut props = properties! {
144 "K0" => "V0"
145 };
146
147 assert_eq!(None, props.dict().get("K1"));
148 props.insert("K1", "V1");
149 assert_eq!(Some("V1"), props.dict().get("K1"));
150 }
151
152 #[test]
153 fn clone() {
154 let props1 = properties! {
155 "K0" => "V0"
156 };
157 let mut props2 = props1.clone();
158
159 props2.insert("K1", "V1");
160
161 assert_eq!(None, props1.dict().get("K1"));
164 assert_eq!(Some("V1"), props2.dict().get("K1"));
165 }
166
167 #[test]
168 fn from_dict() {
169 use spa::static_dict;
170
171 let mut props = {
172 let dict = static_dict! { "K0" => "V0" };
173
174 PropertiesBox::from_dict(&dict)
175 };
176
177 assert_eq!(props.dict().len(), 1);
178 assert_eq!(props.dict().get("K0"), Some("V0"));
179
180 props.insert("K1", "V1");
181 assert_eq!(props.dict().len(), 2);
182 assert_eq!(props.dict().get("K1"), Some("V1"));
183 }
184
185 #[test]
186 fn properties_ref() {
187 use std::ops::Deref;
188
189 let props = properties! {
190 "K0" => "V0"
191 };
192 println!("{:?}", &props);
193 let props_ref: &Properties = props.deref();
194
195 assert_eq!(props_ref.dict().len(), 1);
196 assert_eq!(props_ref.dict().get("K0"), Some("V0"));
197 dbg!(&props_ref);
198
199 let props_copy = props_ref.to_owned();
200 assert_eq!(props_copy.dict().len(), 1);
201 assert_eq!(props_copy.dict().get("K0"), Some("V0"));
202 }
203}