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}