Skip to main content

lv2_state/
storage.rs

1use crate::raw::{RetrieveHandle, StoreHandle};
2use std::collections::HashMap;
3use std::ffi::c_void;
4use std::ops::{Deref, DerefMut};
5use urid::*;
6
7/// A simple property store.
8///
9/// This is mostly used to test this crate, but can be used to store properties too. It contains a map from property URIDs to a tuple of a type URID and a vector of bytes. You can access this map by dereferencing the storage.
10///
11/// You can also directly create [`StoreHandle`s](struct.StoreHandle.html) and [`RetrieveHandle`s](struct.RetrieveHandle.html) that access the storage.
12pub struct Storage {
13    items: HashMap<URID, (URID, Vec<u8>)>,
14}
15
16impl Default for Storage {
17    fn default() -> Self {
18        Self {
19            items: HashMap::new(),
20        }
21    }
22}
23
24impl Storage {
25    /// Store a property.
26    pub fn store<K: ?Sized, T: ?Sized>(&mut self, key: URID<K>, type_: URID<T>, value: &[u8]) {
27        self.items
28            .insert(key.into_general(), (type_.into_general(), value.to_owned()));
29    }
30
31    /// External version of [`store`](#method.store).
32    ///
33    /// This function has the appropriate signature to be used as a storage callback.
34    ///
35    /// # Safety
36    ///
37    /// This method is unsafe since it dereferences raw pointers.
38    ///
39    /// The `handle` has to be a pointer to a `Storage` instance and `value` must point to a slice of bytes with the length of `size`.
40    pub unsafe extern "C" fn extern_store(
41        handle: sys::LV2_State_Handle,
42        key: u32,
43        value: *const c_void,
44        size: usize,
45        type_: u32,
46        _: u32,
47    ) -> sys::LV2_State_Status {
48        let handle = (handle as *mut Self).as_mut().unwrap();
49        let key = URID::new(key).unwrap();
50        let value = std::slice::from_raw_parts(value as *const u8, size);
51        let type_ = URID::new(type_).unwrap();
52        handle.store(key, type_, value);
53        sys::LV2_State_Status_LV2_STATE_SUCCESS
54    }
55
56    /// Create a `StoreHandle` that saves it's properties to this storage.
57    pub fn store_handle(&mut self) -> StoreHandle {
58        StoreHandle::new(Some(Self::extern_store), self as *mut Self as *mut c_void)
59    }
60
61    /// Try to retrieve a property.
62    ///
63    /// If the property doesn't exist, `None` is returned.
64    pub fn retrieve<K: ?Sized>(&self, key: URID<K>) -> Option<(URID, &[u8])> {
65        self.items
66            .get(&key.into_general())
67            .map(|(urid, data)| (*urid, data.as_ref()))
68    }
69
70    /// External version of [`retrieve`](#method.retrieve).
71    ///
72    /// This function has the appropriate signature to be used as a storage callback.
73    ///
74    /// # Safety
75    ///
76    /// This method is unsafe since it dereferences raw pointers.
77    ///
78    /// The `handle` has to be a pointer to a `Storage` instance and `size`, `type_` and `flags` must be valid pointers to instances of their respective types.
79    pub unsafe extern "C" fn extern_retrieve(
80        handle: sys::LV2_State_Handle,
81        key: u32,
82        size: *mut usize,
83        type_: *mut u32,
84        flags: *mut u32,
85    ) -> *const c_void {
86        if !flags.is_null() {
87            *flags = (sys::LV2_State_Flags::LV2_STATE_IS_POD
88                | sys::LV2_State_Flags::LV2_STATE_IS_PORTABLE)
89                .into();
90        }
91
92        let handle = (handle as *mut Self).as_mut().unwrap();
93        let key = URID::new(key).unwrap();
94        if let Some((type_urid, data)) = handle.retrieve(key) {
95            *size = data.len();
96            *type_ = type_urid.get();
97            data.as_ptr() as *const c_void
98        } else {
99            std::ptr::null()
100        }
101    }
102
103    /// Create a `RetrieveHandle` that retrieves the properties from this storage.
104    pub fn retrieve_handle(&mut self) -> RetrieveHandle {
105        RetrieveHandle::new(
106            Some(Self::extern_retrieve),
107            self as *mut Self as *mut c_void,
108        )
109    }
110}
111
112impl Deref for Storage {
113    type Target = HashMap<URID, (URID, Vec<u8>)>;
114
115    fn deref(&self) -> &Self::Target {
116        &self.items
117    }
118}
119
120impl DerefMut for Storage {
121    fn deref_mut(&mut self) -> &mut Self::Target {
122        &mut self.items
123    }
124}