1use crate::StateErr;
2use atom::prelude::*;
3use atom::space::*;
4use std::collections::HashMap;
5use std::ffi::c_void;
6use std::marker::PhantomData;
7use urid::*;
8
9pub struct StoreHandle<'a> {
15 properties: HashMap<URID, SpaceElement>,
16 store_fn: sys::LV2_State_Store_Function,
17 handle: sys::LV2_State_Handle,
18 lifetime: PhantomData<&'a mut c_void>,
19}
20
21impl<'a> StoreHandle<'a> {
22 pub fn new(store_fn: sys::LV2_State_Store_Function, handle: sys::LV2_State_Handle) -> Self {
24 StoreHandle {
25 properties: HashMap::new(),
26 store_fn,
27 handle,
28 lifetime: PhantomData,
29 }
30 }
31
32 pub fn draft<K: ?Sized>(&mut self, property_key: URID<K>) -> StatePropertyWriter {
38 let property_key = property_key.into_general();
39 self.properties
40 .insert(property_key.into_general(), SpaceElement::default());
41 StatePropertyWriter::new(SpaceHead::new(
42 self.properties
43 .get_mut(&property_key.into_general())
44 .unwrap(),
45 ))
46 }
47
48 pub fn commit_pair<K: ?Sized>(
50 store_fn: sys::LV2_State_Store_Function,
51 handle: sys::LV2_State_Handle,
52 key: URID<K>,
53 space: SpaceElement,
54 ) -> Result<(), StateErr> {
55 let store_fn = store_fn.ok_or(StateErr::BadCallback)?;
56 let space: Vec<u8> = space.to_vec();
57 let space = Space::from_slice(space.as_ref());
58 let (header, data) = space
59 .split_type::<sys::LV2_Atom>()
60 .ok_or(StateErr::BadData)?;
61 let data = data
62 .split_raw(header.size as usize)
63 .map(|(data, _)| data)
64 .ok_or(StateErr::BadData)?;
65
66 let key = key.get();
67 let data_ptr = data as *const _ as *const c_void;
68 let data_size = header.size as usize;
69 let data_type = header.type_;
70 let flags: u32 = (sys::LV2_State_Flags::LV2_STATE_IS_POD
71 | sys::LV2_State_Flags::LV2_STATE_IS_PORTABLE)
72 .into();
73 StateErr::from(unsafe { (store_fn)(handle, key, data_ptr, data_size, data_type, flags) })
74 }
75
76 pub fn commit_all(&mut self) -> Result<(), StateErr> {
80 for (key, space) in self.properties.drain() {
81 Self::commit_pair(self.store_fn, self.handle, key, space)?;
82 }
83 Ok(())
84 }
85
86 pub fn commit<K: ?Sized>(&mut self, key: URID<K>) -> Option<Result<(), StateErr>> {
90 let key = key.into_general();
91 let space = self.properties.remove(&key)?;
92 Some(Self::commit_pair(self.store_fn, self.handle, key, space))
93 }
94
95 pub fn discard_all(&mut self) {
97 self.properties.clear();
98 }
99
100 pub fn discard<K: ?Sized>(&mut self, key: URID<K>) {
104 self.properties.remove(&key.into_general());
105 }
106}
107
108pub struct StatePropertyWriter<'a> {
110 head: SpaceHead<'a>,
111 initialized: bool,
112}
113
114impl<'a> StatePropertyWriter<'a> {
115 pub fn new(head: SpaceHead<'a>) -> Self {
117 Self {
118 head,
119 initialized: false,
120 }
121 }
122
123 pub fn init<'b, A: Atom<'a, 'b>>(
127 &'b mut self,
128 urid: URID<A>,
129 parameter: A::WriteParameter,
130 ) -> Result<A::WriteHandle, StateErr> {
131 if !self.initialized {
132 self.initialized = true;
133 (&mut self.head as &mut dyn MutSpace)
134 .init(urid, parameter)
135 .ok_or(StateErr::Unknown)
136 } else {
137 Err(StateErr::Unknown)
138 }
139 }
140}
141
142pub struct RetrieveHandle<'a> {
144 retrieve_fn: sys::LV2_State_Retrieve_Function,
145 handle: sys::LV2_State_Handle,
146 lifetime: PhantomData<&'a mut c_void>,
147}
148
149impl<'a> RetrieveHandle<'a> {
150 pub fn new(
152 retrieve_fn: sys::LV2_State_Retrieve_Function,
153 handle: sys::LV2_State_Handle,
154 ) -> Self {
155 RetrieveHandle {
156 retrieve_fn,
157 handle,
158 lifetime: PhantomData,
159 }
160 }
161
162 pub fn retrieve<K: ?Sized>(&self, key: URID<K>) -> Result<StatePropertyReader, StateErr> {
166 let mut size: usize = 0;
167 let mut type_: u32 = 0;
168 let property_ptr: *const std::ffi::c_void = unsafe {
169 (self.retrieve_fn.ok_or(StateErr::BadCallback)?)(
170 self.handle,
171 key.get(),
172 &mut size,
173 &mut type_,
174 std::ptr::null_mut(),
175 )
176 };
177
178 let type_ = URID::new(type_).ok_or(StateErr::Unknown)?;
179 let space = if !property_ptr.is_null() {
180 unsafe { std::slice::from_raw_parts(property_ptr as *const u8, size) }
181 } else {
182 return Err(StateErr::NoProperty);
183 };
184
185 Ok(StatePropertyReader::new(type_, Space::from_slice(space)))
186 }
187}
188
189pub struct StatePropertyReader<'a> {
193 type_: URID,
194 body: Space<'a>,
195}
196
197impl<'a> StatePropertyReader<'a> {
198 pub fn new<T: ?Sized>(type_: URID<T>, body: Space<'a>) -> Self {
200 Self {
201 type_: type_.into_general(),
202 body,
203 }
204 }
205
206 pub fn type_(&self) -> URID {
208 self.type_
209 }
210
211 pub fn body(&self) -> Space {
213 self.body
214 }
215
216 pub fn read<A: Atom<'a, 'a>>(
222 &self,
223 urid: URID<A>,
224 parameter: A::ReadParameter,
225 ) -> Result<A::ReadHandle, StateErr> {
226 if urid == self.type_ {
227 A::read(self.body, parameter).ok_or(StateErr::Unknown)
228 } else {
229 Err(StateErr::BadType)
230 }
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use crate::raw::*;
237 use crate::storage::Storage;
238 use atom::space::Space;
239
240 fn store(storage: &mut Storage, urids: &AtomURIDCollection) {
241 let mut store_handle = storage.store_handle();
242
243 store_handle
244 .draft(URID::new(1).unwrap())
245 .init(urids.int, 17)
246 .unwrap();
247 store_handle
248 .draft(URID::new(2).unwrap())
249 .init(urids.float, 1.0)
250 .unwrap();
251
252 store_handle.commit(URID::new(1).unwrap()).unwrap().unwrap();
253
254 let mut vector_writer = store_handle.draft(URID::new(3).unwrap());
255 let mut vector_writer = vector_writer.init(urids.vector(), urids.int).unwrap();
256 vector_writer.append(&[1, 2, 3, 4]).unwrap();
257
258 store_handle.commit_all().unwrap();
259
260 store_handle
261 .draft(URID::new(4).unwrap())
262 .init(urids.int, 0)
263 .unwrap();
264 }
265
266 fn retrieve(storage: &mut Storage, urids: &AtomURIDCollection) {
267 let retrieve_handle = storage.retrieve_handle();
268
269 assert_eq!(
270 17,
271 retrieve_handle
272 .retrieve(URID::new(1).unwrap())
273 .unwrap()
274 .read(urids.int, ())
275 .unwrap()
276 );
277 assert_eq!(
278 1.0,
279 retrieve_handle
280 .retrieve(URID::new(2).unwrap())
281 .unwrap()
282 .read(urids.float, ())
283 .unwrap()
284 );
285 assert_eq!(
286 [1, 2, 3, 4],
287 retrieve_handle
288 .retrieve(URID::new(3).unwrap())
289 .unwrap()
290 .read(urids.vector(), urids.int)
291 .unwrap()
292 );
293 assert!(retrieve_handle.retrieve(URID::new(4).unwrap()).is_err());
294 }
295
296 #[test]
297 fn test_storage() {
298 let map = HashURIDMapper::new();
299 let urids = AtomURIDCollection::from_map(&map).unwrap();
300
301 let mut storage = Storage::default();
302
303 store(&mut storage, &urids);
304
305 for (key, (type_, value)) in storage.iter() {
306 match key.get() {
307 1 => {
308 assert_eq!(urids.int, *type_);
309 assert_eq!(17, unsafe { *(value.as_slice() as *const _ as *const i32) });
310 }
311 2 => {
312 assert_eq!(urids.float, *type_);
313 assert_eq!(1.0, unsafe {
314 *(value.as_slice() as *const _ as *const f32)
315 });
316 }
317 3 => {
318 assert_eq!(urids.vector::<Int>(), *type_);
319 let space = Space::from_slice(value.as_slice());
320 let data = Vector::read(space, urids.int).unwrap();
321 assert_eq!([1, 2, 3, 4], data);
322 }
323 _ => panic!("Invalid key!"),
324 }
325 }
326
327 retrieve(&mut storage, &urids);
328 }
329}