Skip to main content

leodos_libcfs/cfe/es/
lib.rs

1//! Safe wrappers for CFE Library query APIs.
2
3use crate::cfe::es::app::AppInfo;
4use crate::error::{CfsError, OsalError, Result};
5use crate::ffi;
6use crate::cstring;
7use crate::status::check;
8use core::mem::MaybeUninit;
9use heapless::String;
10
11/// A type-safe, zero-cost wrapper for a cFE Library ID.
12///
13/// This is a lightweight, `Copy`-able handle that represents a unique loaded library.
14/// It can be used to query information about that specific library.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[repr(transparent)]
17pub struct LibId(pub ffi::CFE_ES_LibId_t);
18
19impl LibId {
20    /// Retrieves the cFE Library ID for a given library name.
21    ///
22    /// # Arguments
23    /// * `name`: The registered name of the library to look up.
24    ///
25    /// # Errors
26    ///
27    /// Returns an error if no library with the given name is found.
28    pub fn from_name(name: &str) -> Result<Self> {
29        let c_name = cstring::<{ ffi::OS_MAX_API_NAME as usize }>(name)?;
30
31        let mut lib_id = MaybeUninit::uninit();
32        check(unsafe { ffi::CFE_ES_GetLibIDByName(lib_id.as_mut_ptr(), c_name.as_ptr()) })?;
33        Ok(Self(unsafe { lib_id.assume_init() }))
34    }
35
36    /// Retrieves the name for this library ID.
37    ///
38    /// # Errors
39    ///
40    /// Returns an error if the Lib ID is not valid, the buffer is too small
41    /// (unlikely with `heapless`), or the name is not valid UTF-8.
42    pub fn name(&self) -> Result<String<{ ffi::OS_MAX_API_NAME as usize }>> {
43        let mut buffer = [0u8; ffi::OS_MAX_API_NAME as usize];
44        check(unsafe {
45            ffi::CFE_ES_GetLibName(
46                buffer.as_mut_ptr() as *mut libc::c_char,
47                self.0,
48                buffer.len(),
49            )
50        })?;
51        let len = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
52        let vec = heapless::Vec::from_slice(&buffer[..len]).map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
53        String::from_utf8(vec).map_err(|_| CfsError::InvalidString)
54    }
55
56    /// Retrieves detailed information about the library with this ID.
57    ///
58    /// Note: This reuses the `AppInfo` struct, as the underlying FFI type is the same.
59    /// Fields related to tasks (e.g., `MainTaskId`) will not be meaningful for a library.
60    ///
61    /// # Errors
62    ///
63    /// Returns an error if the Lib ID is not valid or if the underlying
64    /// CFE call fails.
65    pub fn info(&self) -> Result<AppInfo> {
66        let mut lib_info_uninit = MaybeUninit::uninit();
67        check(unsafe { ffi::CFE_ES_GetLibInfo(lib_info_uninit.as_mut_ptr(), self.0) })?;
68        Ok(AppInfo {
69            inner: unsafe { lib_info_uninit.assume_init() },
70        })
71    }
72
73    /// Converts the Lib ID into a zero-based integer suitable for array indexing.
74    ///
75    /// # Errors
76    ///
77    /// Returns an error if the Lib ID is not valid or if the underlying
78    /// CFE call fails.
79    pub fn to_index(&self) -> Result<u32> {
80        let mut index = MaybeUninit::uninit();
81        check(unsafe { ffi::CFE_ES_LibID_ToIndex(self.0, index.as_mut_ptr()) })?;
82        Ok(unsafe { index.assume_init() })
83    }
84}