libobs_wrapper\data/
immutable.rs

1use std::{ffi::CStr, sync::Arc};
2
3use libobs::obs_data_t;
4
5use crate::{
6    impl_obs_drop, run_with_obs, runtime::ObsRuntime, unsafe_send::Sendable, utils::ObsError,
7};
8
9use super::{ObsData, _ObsDataDropGuard};
10
11#[derive(Clone, Debug)]
12/// Immutable wrapper around obs_data_t to be prevent modification and to be used in creation of other objects.
13/// This should not be updated directly using the pointer, but instead through the corresponding update methods on the holder of this data.
14pub struct ImmutableObsData {
15    ptr: Sendable<*mut obs_data_t>,
16    runtime: ObsRuntime,
17    _drop_guard: Arc<_ObsDataDropGuard>,
18}
19
20impl ImmutableObsData {
21    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
22    pub async fn new(runtime: &ObsRuntime) -> Result<Self, ObsError> {
23        let ptr = run_with_obs!(runtime, move || unsafe {
24            Sendable(libobs::obs_data_create())
25        }).await?;
26
27        Ok(ImmutableObsData {
28            ptr: ptr.clone(),
29            runtime: runtime.clone(),
30            _drop_guard: Arc::new(_ObsDataDropGuard {
31                obs_data: ptr,
32                runtime: runtime.clone(),
33            }),
34        })
35    }
36
37    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
38    pub async fn from_raw(data: Sendable<*mut obs_data_t>, runtime: ObsRuntime) -> Self {
39        ImmutableObsData {
40            ptr: data.clone(),
41            runtime: runtime.clone(),
42            _drop_guard: Arc::new(_ObsDataDropGuard {
43                obs_data: data.clone(),
44                runtime,
45            }),
46        }
47    }
48
49    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
50    pub async fn to_mutable(&self) -> Result<ObsData, ObsError> {
51        let ptr = self.ptr.clone();
52        let json = run_with_obs!(self.runtime, (ptr), move || unsafe {
53            Sendable(libobs::obs_data_get_json(ptr))
54        }).await?;
55
56        let json = unsafe { CStr::from_ptr(json.0) }.to_str()
57            .map_err(|_| ObsError::JsonParseError)?
58            .to_string();
59
60        ObsData::from_json(json.as_ref(), self.runtime.clone()).await
61    }
62
63    pub fn as_ptr(&self) -> Sendable<*mut obs_data_t> {
64        self.ptr.clone()
65    }
66}
67
68impl From<ObsData> for ImmutableObsData {
69    fn from(mut data: ObsData) -> Self {
70        // Set to null pointer to prevent double free
71        let ptr = data.obs_data.0;
72
73        data.obs_data.0 = std::ptr::null_mut();
74        ImmutableObsData {
75            ptr: Sendable(ptr),
76            runtime: data.runtime.clone(),
77            _drop_guard: data._drop_guard,
78        }
79    }
80}
81
82impl_obs_drop!(ImmutableObsData, (ptr), move || unsafe {
83    libobs::obs_data_release(ptr)
84});