pipewire/context/
box_.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use std::{marker::PhantomData, ops::Deref, ptr};
5
6use crate::{loop_::Loop, properties::PropertiesBox, Error};
7
8use super::Context;
9
10/// Smart pointer providing unique ownership of a PipeWire [context](super).
11///
12/// For shared ownership, see [`ContextRc`](super::ContextRc).
13///
14/// For an explanation of these, see [Smart pointers to PipeWire objects](crate#smart-pointers-to-pipewire-objects).
15#[derive(Debug)]
16pub struct ContextBox<'l> {
17    ptr: std::ptr::NonNull<pw_sys::pw_context>,
18    loop_: PhantomData<&'l Loop>,
19}
20
21impl<'l> ContextBox<'l> {
22    pub fn new(
23        loop_: &'l Loop,
24        properties: Option<PropertiesBox>,
25    ) -> Result<ContextBox<'l>, Error> {
26        unsafe {
27            let props = properties
28                .map_or(ptr::null(), |props| props.into_raw())
29                .cast_mut();
30            let raw = ptr::NonNull::new(pw_sys::pw_context_new((*loop_).as_raw_ptr(), props, 0))
31                .ok_or(Error::CreationFailed)?;
32
33            Ok(Self::from_raw(raw))
34        }
35    }
36
37    /// Create a `ContextBox` by taking ownership of a raw `pw_context`.
38    ///
39    /// # Safety
40    /// The provided pointer must point to a valid, well aligned [`pw_context`](`pw_sys::pw_context`).
41    ///
42    /// The raw context must not be manually destroyed or moved, as the new [`ContextBox`] takes
43    /// ownership of it.
44    ///
45    /// The lifetime of the returned box is unbounded. The caller is responsible to make sure
46    /// that the loop used with this context outlives the context.
47    pub unsafe fn from_raw(raw: std::ptr::NonNull<pw_sys::pw_context>) -> ContextBox<'l> {
48        Self {
49            ptr: raw,
50            loop_: PhantomData,
51        }
52    }
53
54    pub fn into_raw(self) -> std::ptr::NonNull<pw_sys::pw_context> {
55        std::mem::ManuallyDrop::new(self).ptr
56    }
57}
58
59impl<'l> std::ops::Deref for ContextBox<'l> {
60    type Target = Context;
61
62    fn deref(&self) -> &Self::Target {
63        unsafe { self.ptr.cast::<Context>().as_ref() }
64    }
65}
66
67impl<'l> AsRef<Context> for ContextBox<'l> {
68    fn as_ref(&self) -> &Context {
69        self.deref()
70    }
71}
72
73impl<'l> std::ops::Drop for ContextBox<'l> {
74    fn drop(&mut self) {
75        unsafe {
76            pw_sys::pw_context_destroy(self.as_raw_ptr());
77        }
78    }
79}