flipperzero_sys/furi/
record.rs

1//! Low-level wrappers around Furi Record API.
2
3use core::ffi::CStr;
4use core::ptr::NonNull;
5
6/// Low-level wrapper of a record handle.
7///
8/// This effectively acts as a reference count for the open underlying Record.
9pub struct UnsafeRecord<T> {
10    name: &'static CStr,
11    raw: NonNull<T>,
12}
13
14impl<T> UnsafeRecord<T> {
15    /// Opens a record.
16    ///
17    /// # Safety
18    ///
19    /// `T` must be the correct C type for the record identified by `name`.
20    pub unsafe fn open(name: &'static CStr) -> Self {
21        Self {
22            name,
23            // SAFETY: `furi_record_open` blocks until the record is initialized with a valid value.
24            raw: unsafe { NonNull::new_unchecked(crate::furi_record_open(name.as_ptr()).cast()) },
25        }
26    }
27
28    /// Returns the record data as a raw pointer.
29    pub fn as_ptr(&self) -> *mut T {
30        self.raw.as_ptr()
31    }
32}
33
34impl<T> Clone for UnsafeRecord<T> {
35    fn clone(&self) -> Self {
36        // SAFETY: Opening a record multiple times just increases its reference count.
37        unsafe { Self::open(self.name) }
38    }
39}
40
41impl<T> Drop for UnsafeRecord<T> {
42    fn drop(&mut self) {
43        unsafe {
44            // decrement the holders count
45            crate::furi_record_close(self.name.as_ptr());
46        }
47    }
48}