libcamera/
utils.rs

1use std::{
2    ffi::c_int,
3    io,
4    ops::{Deref, DerefMut},
5    ptr::NonNull,
6};
7
8/// Provides only an immutable reference to the contained type T.
9///
10/// Used for FFI types to avoid having separate variants depending on mutability.
11pub struct Immutable<T: ?Sized>(pub(crate) T);
12
13impl<T> Immutable<T> {
14    pub fn value(&self) -> &T {
15        &self.0
16    }
17}
18
19impl<T> Deref for Immutable<T> {
20    type Target = T;
21
22    fn deref(&self) -> &Self::Target {
23        &self.0
24    }
25}
26
27impl<T: core::fmt::Debug> core::fmt::Debug for Immutable<T> {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.debug_tuple("Immutable").field(&self.0).finish()
30    }
31}
32
33/// Trait, which allows type to be used in [UniquePtr]
34pub trait UniquePtrTarget: Sized {
35    /// Allocates `Self` in the heap and returns pointer.
36    ///
37    /// # Safety
38    ///
39    /// Pointer must be deallocated by calling [Self::ptr_drop()] when no longer needed.
40    unsafe fn ptr_new() -> *mut Self;
41    /// Destroys pointer allocated in `ptr_new()`.
42    ///
43    /// # Safety
44    ///
45    /// Pointer must have been created by [Self::ptr_new()] and is no longer aliased.
46    unsafe fn ptr_drop(ptr: *mut Self);
47}
48
49/// Similar to [Box], but uses custom alloc and drop methods defined in [UniquePtrTarget].
50pub struct UniquePtr<T: UniquePtrTarget> {
51    ptr: NonNull<T>,
52}
53
54impl<T: UniquePtrTarget> UniquePtr<T> {
55    pub fn new() -> Self {
56        Self {
57            ptr: NonNull::new(unsafe { T::ptr_new() }).unwrap(),
58        }
59    }
60
61    /// # Safety
62    /// Caller must ensure `ptr` was allocated by `T::ptr_new` and owns it.
63    pub unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
64        NonNull::new(ptr).map(|p| Self { ptr: p })
65    }
66}
67
68impl<T: UniquePtrTarget> Default for UniquePtr<T> {
69    fn default() -> Self {
70        Self::new()
71    }
72}
73
74impl<T: UniquePtrTarget> Deref for UniquePtr<T> {
75    type Target = T;
76
77    fn deref(&self) -> &Self::Target {
78        unsafe { &*(self.ptr.as_ptr() as *const T) }
79    }
80}
81
82impl<T: UniquePtrTarget> DerefMut for UniquePtr<T> {
83    fn deref_mut(&mut self) -> &mut Self::Target {
84        unsafe { &mut *(self.ptr.as_mut() as *mut T) }
85    }
86}
87
88impl<T: UniquePtrTarget> Drop for UniquePtr<T> {
89    fn drop(&mut self) {
90        unsafe { T::ptr_drop(self.ptr.as_mut()) }
91    }
92}
93
94impl<T: UniquePtrTarget + core::fmt::Debug> core::fmt::Debug for UniquePtr<T> {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        self.deref().fmt(f)
97    }
98}
99
100#[inline]
101pub fn handle_result(ret: c_int) -> io::Result<()> {
102    if ret < 0 {
103        Err(io::Error::from_raw_os_error(-ret))
104    } else {
105        Ok(())
106    }
107}