1use std::{
2 io,
3 mem::ManuallyDrop,
4 os::fd::{FromRawFd, IntoRawFd, OwnedFd},
5 ptr::NonNull,
6};
7
8use libcamera_sys::*;
9
10pub struct Fence {
12 ptr: NonNull<libcamera_fence_t>,
13}
14
15impl Fence {
16 pub fn from_fd(fd: OwnedFd) -> io::Result<Self> {
20 let raw = fd.into_raw_fd();
21 let ptr = unsafe { libcamera_fence_from_fd(raw) };
22 match NonNull::new(ptr) {
23 Some(ptr) => Ok(Self { ptr }),
24 None => {
25 unsafe { libc::close(raw) };
26 Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid fence fd"))
27 }
28 }
29 }
30
31 pub fn to_owned_fd(&self) -> io::Result<OwnedFd> {
33 let fd = unsafe { libcamera_fence_fd(self.ptr.as_ptr()) };
34 if fd < 0 {
35 Err(io::Error::last_os_error())
36 } else {
37 Ok(unsafe { OwnedFd::from_raw_fd(fd) })
38 }
39 }
40
41 pub fn into_owned_fd(self) -> io::Result<OwnedFd> {
43 let fd = self.to_owned_fd();
44 let ptr = self.ptr;
46 let _ = ManuallyDrop::new(self);
47 unsafe {
48 libcamera_fence_destroy(ptr.as_ptr());
49 }
50 fd
51 }
52
53 pub(crate) fn into_raw(self) -> *mut libcamera_fence_t {
54 let ptr = self.ptr.as_ptr();
55 std::mem::forget(self);
56 ptr
57 }
58
59 pub(crate) unsafe fn from_ptr(ptr: *mut libcamera_fence_t) -> Option<Self> {
60 NonNull::new(ptr).map(|ptr| Self { ptr })
61 }
62}
63
64impl Drop for Fence {
65 fn drop(&mut self) {
66 unsafe { libcamera_fence_destroy(self.ptr.as_ptr()) }
67 }
68}
69
70unsafe impl Send for Fence {}