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