Skip to main content

leodos_libcfs/
error.rs

1//! Error types for cFS.
2
3use crate::ffi;
4use crate::status::check;
5use heapless::CString;
6
7/// A specialized `Result` type for CFE operations.
8pub type Result<T> = core::result::Result<T, CfsError>;
9
10// ── Sub-error enums ─────────────────────────────────────────
11
12/// CFE Event Services errors.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
14pub enum EvsError {
15    /// An unknown filter scheme was requested.
16    #[error("CFE-EVS: Unknown Filter scheme")]
17    UnknownFilter,
18    /// The application has not been registered with EVS.
19    #[error("CFE-EVS: Application not registered")]
20    AppNotRegistered,
21    /// An illegal application ID was provided.
22    #[error("CFE-EVS: Illegal Application ID")]
23    AppIllegalAppId,
24    /// The application filter has been overloaded.
25    #[error("CFE-EVS: Application filter overload")]
26    AppFilterOverload,
27    /// Failed to access the reset area pointer.
28    #[error("CFE-EVS: Reset Area Pointer Failure")]
29    ResetAreaPointer,
30    /// The event is not registered for filtering.
31    #[error("CFE-EVS: Event not registered for filtering")]
32    EvtNotRegistered,
33    /// A file write error occurred.
34    #[error("CFE-EVS: File write error")]
35    FileWriteError,
36    /// An invalid parameter was supplied in a command.
37    #[error("CFE-EVS: Invalid parameter in command")]
38    InvalidParameter,
39    /// The event was squelched due to a high event rate.
40    #[error("CFE-EVS: Event squelched due to high rate")]
41    AppSquelched,
42    /// The requested function is not implemented.
43    #[error("CFE-EVS: Not Implemented")]
44    NotImplemented,
45}
46
47/// CFE Executive Services errors.
48#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
49pub enum EsError {
50    /// The resource ID is not valid.
51    #[error("CFE-ES: Resource ID is not valid")]
52    ResourceIdNotValid,
53    /// The resource name was not found.
54    #[error("CFE-ES: Resource Name not found")]
55    NameNotFound,
56    /// Failed to create the application.
57    #[error("CFE-ES: Application Create Error")]
58    AppCreate,
59    /// Failed to create a child task.
60    #[error("CFE-ES: Child Task Create Error")]
61    ChildTaskCreate,
62    /// The system log is full.
63    #[error("CFE-ES: System Log Full")]
64    SysLogFull,
65    /// The memory block size is invalid.
66    #[error("CFE-ES: Memory Block Size Error")]
67    MemBlockSize,
68    /// Failed to load the library.
69    #[error("CFE-ES: Load Library Error")]
70    LoadLib,
71    /// A bad argument was provided.
72    #[error("CFE-ES: Bad Argument")]
73    BadArgument,
74    /// Failed to register a child task.
75    #[error("CFE-ES: Child Task Register Error")]
76    ChildTaskRegister,
77    /// Insufficient memory available in CDS.
78    #[error("CFE-ES: CDS Insufficient Memory")]
79    CdsInsufficientMemory,
80    /// The CDS name is invalid.
81    #[error("CFE-ES: CDS Invalid Name")]
82    CdsInvalidName,
83    /// The CDS size is invalid.
84    #[error("CFE-ES: CDS Invalid Size")]
85    CdsInvalidSize,
86    /// The CDS is invalid.
87    #[error("CFE-ES: CDS Invalid")]
88    CdsInvalid,
89    /// Failed to access the CDS.
90    #[error("CFE-ES: CDS Access Error")]
91    CdsAccessError,
92    /// A file I/O error occurred.
93    #[error("CFE-ES: File IO Error")]
94    FileIoErr,
95    /// Failed to access the reset area.
96    #[error("CFE-ES: Reset Area Access Error")]
97    RstAccessErr,
98    /// Failed to register the application.
99    #[error("CFE-ES: Application Register Error")]
100    AppRegister,
101    /// Failed to delete a child task.
102    #[error("CFE-ES: Child Task Delete Error")]
103    ChildTaskDelete,
104    /// Attempted to delete a main task with the child
105    /// task delete API.
106    #[error("CFE-ES: Attempted to delete a main task")]
107    ChildTaskDeleteMainTask,
108    /// The CDS block CRC check failed.
109    #[error("CFE-ES: CDS Block CRC Error")]
110    CdsBlockCrcErr,
111    /// Failed to delete a mutex semaphore.
112    #[error("CFE-ES: Mutex Semaphore Delete Error")]
113    MutSemDeleteErr,
114    /// Failed to delete a binary semaphore.
115    #[error("CFE-ES: Binary Semaphore Delete Error")]
116    BinSemDeleteErr,
117    /// Failed to delete a counting semaphore.
118    #[error("CFE-ES: Counting Semaphore Delete Error")]
119    CountSemDeleteErr,
120    /// Failed to delete a queue.
121    #[error("CFE-ES: Queue Delete Error")]
122    QueueDeleteErr,
123    /// Failed to close a file.
124    #[error("CFE-ES: File Close Error")]
125    FileCloseErr,
126    /// The CDS type does not match the expected type.
127    #[error("CFE-ES: CDS Wrong Type Error")]
128    CdsWrongTypeErr,
129    /// The CDS owner is still active.
130    #[error("CFE-ES: CDS Owner Active Error")]
131    CdsOwnerActiveErr,
132    /// Failed to clean up the application.
133    #[error("CFE-ES: Application Cleanup Error")]
134    AppCleanupErr,
135    /// Failed to delete a timer.
136    #[error("CFE-ES: Timer Delete Error")]
137    TimerDeleteErr,
138    /// The buffer is not in the pool.
139    #[error("CFE-ES: Buffer Not In Pool")]
140    BufferNotInPool,
141    /// Failed to delete a task.
142    #[error("CFE-ES: Task Delete Error")]
143    TaskDeleteErr,
144    /// The operation timed out.
145    #[error("CFE-ES: Operation Timed Out")]
146    OperationTimedOut,
147    /// No resource IDs are available.
148    #[error("CFE-ES: No Resource IDs Available")]
149    NoResourceIdsAvailable,
150    /// The pool block is invalid.
151    #[error("CFE-ES: Invalid pool block")]
152    PoolBlockInvalid,
153    /// A resource with that name already exists.
154    #[error("CFE-ES: Duplicate Name Error")]
155    DuplicateName,
156    /// The requested function is not implemented.
157    #[error("CFE-ES: Not Implemented")]
158    NotImplemented,
159}
160
161/// CFE Software Bus errors.
162#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
163pub enum SbError {
164    /// The receive operation timed out.
165    #[error("CFE-SB: Time Out")]
166    TimeOut,
167    /// No message is available on the pipe.
168    #[error("CFE-SB: No Message")]
169    NoMessage,
170    /// A bad argument was provided.
171    #[error("CFE-SB: Bad Argument")]
172    BadArgument,
173    /// The maximum number of pipes has been reached.
174    #[error("CFE-SB: Max Pipes Met")]
175    MaxPipesMet,
176    /// Failed to create a pipe.
177    #[error("CFE-SB: Pipe Create Error")]
178    PipeCrErr,
179    /// Failed to read from a pipe.
180    #[error("CFE-SB: Pipe Read Error")]
181    PipeRdErr,
182    /// The message exceeds the maximum allowed size.
183    #[error("CFE-SB: Message Too Big")]
184    MsgTooBig,
185    /// The SB message buffer pool has been depleted.
186    #[error("CFE-SB: Buffer Allocation Error")]
187    BufAllocErr,
188    /// The maximum number of messages has been reached.
189    #[error("CFE-SB: Max Messages Met")]
190    MaxMsgsMet,
191    /// The maximum number of destinations has been reached.
192    #[error("CFE-SB: Max Destinations Met")]
193    MaxDestsMet,
194    /// An internal SB error occurred.
195    #[error("CFE-SB: CFE-Internal Error")]
196    InternalErr,
197    /// The message type is incorrect for the operation.
198    #[error("CFE-SB: Wrong Message Type")]
199    WrongMsgType,
200    /// The buffer reference is invalid.
201    #[error("CFE-SB: Buffer Invalid")]
202    BufferInvalid,
203    /// The requested function is not implemented.
204    #[error("CFE-SB: Not Implemented")]
205    NotImplemented,
206}
207
208/// CFE File Services errors.
209#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
210pub enum FsError {
211    /// A bad argument was provided.
212    #[error("CFE-FS: Bad Argument")]
213    BadArgument,
214    /// The file path is invalid.
215    #[error("CFE-FS: Invalid Path")]
216    InvalidPath,
217    /// The filename exceeds the maximum allowed length.
218    #[error("CFE-FS: Filename Too Long")]
219    FnameTooLong,
220    /// The requested function is not implemented.
221    #[error("CFE-FS: Not Implemented")]
222    NotImplemented,
223}
224
225/// CFE Table Services errors.
226#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
227pub enum TblError {
228    /// The table handle is invalid.
229    #[error("CFE-TBL: Invalid Handle")]
230    InvalidHandle,
231    /// The table name is invalid.
232    #[error("CFE-TBL: Invalid Name")]
233    InvalidName,
234    /// The table size is invalid.
235    #[error("CFE-TBL: Invalid Size")]
236    InvalidSize,
237    /// The table has never been loaded.
238    #[error("CFE-TBL: Never Loaded")]
239    NeverLoaded,
240    /// The table registry is full.
241    #[error("CFE-TBL: Registry Full")]
242    RegistryFull,
243    /// Access to the table was denied.
244    #[error("CFE-TBL: No Access")]
245    NoAccess,
246    /// The table is not registered.
247    #[error("CFE-TBL: Unregistered")]
248    Unregistered,
249    /// All available table handles are in use.
250    #[error("CFE-TBL: Handles Full")]
251    HandlesFull,
252    /// A duplicate table with a different size was found.
253    #[error("CFE-TBL: Duplicate Table With Different Size")]
254    DuplicateDiffSize,
255    /// A duplicate table was found but is not owned by the
256    /// calling application.
257    #[error("CFE-TBL: Duplicate Table And Not Owned")]
258    DuplicateNotOwned,
259    /// No working buffer is available.
260    #[error("CFE-TBL: No Buffer Available")]
261    NoBufferAvail,
262    /// The table is dump-only; load is not permitted.
263    #[error("CFE-TBL: Dump Only Error")]
264    DumpOnly,
265    /// The source type is illegal for this operation.
266    #[error("CFE-TBL: Illegal Source Type")]
267    IllegalSrcType,
268    /// A table load is already in progress.
269    #[error("CFE-TBL: Load In Progress")]
270    LoadInProgress,
271    /// The file is too large for the table.
272    #[error("CFE-TBL: File Too Large")]
273    FileTooLarge,
274    /// The content ID in the file header is invalid.
275    #[error("CFE-TBL: Bad Content ID")]
276    BadContentId,
277    /// The subtype ID in the file header is invalid.
278    #[error("CFE-TBL: Bad Subtype ID")]
279    BadSubtypeId,
280    /// The file size is inconsistent with the table size.
281    #[error("CFE-TBL: File Size Inconsistent")]
282    FileSizeInconsistent,
283    /// The file is missing a standard header.
284    #[error("CFE-TBL: No Standard Header")]
285    NoStdHeader,
286    /// The file is missing a table header.
287    #[error("CFE-TBL: No Table Header")]
288    NoTblHeader,
289    /// The filename exceeds the maximum allowed length.
290    #[error("CFE-TBL: Filename Too Long")]
291    FilenameTooLong,
292    /// The file is intended for a different table.
293    #[error("CFE-TBL: File For Wrong Table")]
294    FileForWrongTable,
295    /// The table load did not complete.
296    #[error("CFE-TBL: Load Incomplete")]
297    LoadIncomplete,
298    /// Only a partial load was performed.
299    #[error("CFE-TBL: Partial Load Error")]
300    PartialLoad,
301    /// The table options are invalid.
302    #[error("CFE-TBL: Invalid Options")]
303    InvalidOptions,
304    /// The spacecraft ID in the file header does not match.
305    #[error("CFE-TBL: Bad Spacecraft ID")]
306    BadSpacecraftId,
307    /// The processor ID in the file header does not match.
308    #[error("CFE-TBL: Bad Processor ID")]
309    BadProcessorId,
310    /// A message error occurred during table operations.
311    #[error("CFE-TBL: Message Error")]
312    MessageError,
313    /// The file is shorter than expected.
314    #[error("CFE-TBL: Short File")]
315    ShortFile,
316    /// A table access error occurred.
317    #[error("CFE-TBL: Access error")]
318    Access,
319    /// A bad argument was provided.
320    #[error("CFE-TBL: Bad Argument")]
321    BadArgument,
322    /// The requested function is not implemented.
323    #[error("CFE-TBL: Not Implemented")]
324    NotImplemented,
325}
326
327/// CFE Time Services errors.
328#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
329pub enum TimeError {
330    /// The requested function is not implemented.
331    #[error("CFE-TIME: Not Implemented")]
332    NotImplemented,
333    /// The time function is for internal use only.
334    #[error("CFE-TIME: Internal Only")]
335    InternalOnly,
336    /// The time value is out of the valid range.
337    #[error("CFE-TIME: Out Of Range")]
338    OutOfRange,
339    /// Too many synchronization callbacks have been
340    /// registered.
341    #[error("CFE-TIME: Too Many Sync Callbacks")]
342    TooManySynchCallbacks,
343    /// The callback was not previously registered.
344    #[error("CFE-TIME: Callback Not Registered")]
345    CallbackNotRegistered,
346    /// A bad argument was provided.
347    #[error("CFE-TIME: Bad Argument")]
348    BadArgument,
349}
350
351/// OSAL errors.
352#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
353pub enum OsalError {
354    /// A generic OSAL error occurred.
355    #[error("OSAL: Generic error")]
356    Error,
357    /// An invalid pointer was provided.
358    #[error("OSAL: Invalid pointer")]
359    InvalidPointer,
360    /// The address is not properly aligned.
361    #[error("OSAL: Address misalignment")]
362    AddressMisaligned,
363    /// The operation timed out.
364    #[error("OSAL: Timeout")]
365    Timeout,
366    /// The interrupt number is invalid.
367    #[error("OSAL: Invalid Interrupt number")]
368    InvalidIntNum,
369    /// A semaphore operation failed.
370    #[error("OSAL: Semaphore failure")]
371    SemFailure,
372    /// A semaphore operation timed out.
373    #[error("OSAL: Semaphore timeout")]
374    SemTimeout,
375    /// The queue is empty.
376    #[error("OSAL: Queue empty")]
377    QueueEmpty,
378    /// The queue is full.
379    #[error("OSAL: Queue full")]
380    QueueFull,
381    /// A queue operation timed out.
382    #[error("OSAL: Queue timeout")]
383    QueueTimeout,
384    /// The queue size is invalid.
385    #[error("OSAL: Queue invalid size")]
386    QueueInvalidSize,
387    /// The queue ID is invalid.
388    #[error("OSAL: Queue ID error")]
389    QueueIdError,
390    /// The name exceeds the maximum allowed length.
391    #[error("OSAL: Name length too long")]
392    NameTooLong,
393    /// No free IDs are available.
394    #[error("OSAL: No free IDs")]
395    NoFreeIds,
396    /// The requested name is already taken.
397    #[error("OSAL: Name taken")]
398    NameTaken,
399    /// The object ID is invalid.
400    #[error("OSAL: Invalid ID")]
401    InvalidId,
402    /// The name was not found.
403    #[error("OSAL: Name not found")]
404    NameNotFound,
405    /// The semaphore is not full.
406    #[error("OSAL: Semaphore not full")]
407    SemNotFull,
408    /// The priority value is invalid.
409    #[error("OSAL: Invalid priority")]
410    InvalidPriority,
411    /// The semaphore value is invalid.
412    #[error("OSAL: Invalid semaphore value")]
413    InvalidSemValue,
414    /// A file operation error occurred.
415    #[error("OSAL: File error")]
416    File,
417    /// The requested function is not implemented.
418    #[error("OSAL: Not implemented")]
419    NotImplemented,
420    /// Invalid arguments were passed to a timer function.
421    #[error("OSAL: Timer invalid arguments")]
422    TimerInvalidArgs,
423    /// The timer ID is invalid.
424    #[error("OSAL: Timer ID error")]
425    TimerIdError,
426    /// The timer is unavailable.
427    #[error("OSAL: Timer unavailable")]
428    TimerUnavailable,
429    /// An internal timer error occurred.
430    #[error("OSAL: Timer internal error")]
431    TimerInternal,
432    /// The object is currently in use.
433    #[error("OSAL: Object in use")]
434    ObjectInUse,
435    /// The address is invalid.
436    #[error("OSAL: Bad address")]
437    BadAddress,
438    /// The object is in an incorrect state for the
439    /// requested operation.
440    #[error("OSAL: Incorrect object state")]
441    IncorrectObjState,
442    /// The object type is incorrect for the requested
443    /// operation.
444    #[error("OSAL: Incorrect object type")]
445    IncorrectObjType,
446    /// The stream has been disconnected.
447    #[error("OSAL: Stream disconnected")]
448    StreamDisconnected,
449    /// The requested operation is not supported on the
450    /// supplied objects.
451    #[error("OSAL: Requested operation not supported on supplied object(s)")]
452    OperationNotSupported,
453    /// The size is invalid.
454    #[error("OSAL: Invalid Size")]
455    InvalidSize,
456    /// The output size exceeds the limit.
457    #[error("OSAL: Size of output exceeds limit")]
458    OutputTooLarge,
459    /// The argument value is invalid.
460    #[error("OSAL: Invalid argument value")]
461    InvalidArgument,
462    /// The filesystem path exceeds the maximum length.
463    #[error("OSAL: FS path too long")]
464    FsPathTooLong,
465    /// The filesystem name exceeds the maximum length.
466    #[error("OSAL: FS name too long")]
467    FsNameTooLong,
468    /// The filesystem drive was not created.
469    #[error("OSAL: FS drive not created")]
470    FsDriveNotCreated,
471    /// The filesystem device is not free.
472    #[error("OSAL: FS device not free")]
473    FsDeviceNotFree,
474    /// The filesystem path is invalid.
475    #[error("OSAL: FS path invalid")]
476    FsPathInvalid,
477}
478
479// ── Top-level Error ─────────────────────────────────────────
480
481/// Represents all possible errors and status codes from the
482/// CFE and OSAL APIs.
483#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
484#[non_exhaustive]
485pub enum CfsError {
486    /// An EVS (Event Services) error.
487    #[error(transparent)]
488    Evs(#[from] EvsError),
489    /// An ES (Executive Services) error.
490    #[error(transparent)]
491    Es(#[from] EsError),
492    /// An SB (Software Bus) error.
493    #[error(transparent)]
494    Sb(#[from] SbError),
495    /// An FS (File Services) error.
496    #[error(transparent)]
497    Fs(#[from] FsError),
498    /// A TBL (Table Services) error.
499    #[error(transparent)]
500    Tbl(#[from] TblError),
501    /// A TIME (Time Services) error.
502    #[error(transparent)]
503    Time(#[from] TimeError),
504    /// An OSAL error.
505    #[error(transparent)]
506    Osal(#[from] OsalError),
507
508    /// A hardware bus error (SPI, I2C, UART, CAN, GPIO, etc.).
509    #[cfg(feature = "nos3")]
510    #[error(transparent)]
511    Bus(#[from] crate::nos3::buses::BusError),
512
513    // --- Generic CFE Status ---
514    /// The message length is incorrect.
515    #[error("CFE: Wrong Message Length")]
516    WrongMsgLength,
517    /// The message ID is unknown.
518    #[error("CFE: Unknown Message ID")]
519    UnknownMsgId,
520    /// The command code is invalid.
521    #[error("CFE: Bad Command Code")]
522    BadCommandCode,
523    /// An external resource failure occurred.
524    #[error("CFE: External resource failure")]
525    ExternalResourceFail,
526    /// The request is already pending.
527    #[error("CFE: Request already pending")]
528    RequestAlreadyPending,
529    /// Validation of the input failed.
530    #[error("CFE: Validation Failure")]
531    ValidationFailure,
532    /// The input value is out of the valid range.
533    #[error("CFE: Input value out of range")]
534    RangeError,
535    /// The request cannot be processed in the current state.
536    #[error("CFE: Cannot process request in current state")]
537    IncorrectState,
538    /// The requested function is not implemented.
539    #[error("CFE: Not Implemented")]
540    NotImplemented,
541    // --- Other Errors ---
542    /// The string contains an interior null character.
543    #[error("Invalid string: contains interior null character")]
544    InvalidString,
545    /// The task pool is full and cannot accept new tasks.
546    #[error("The task pool is full")]
547    TaskPoolFull,
548    /// The task's stack size exceeds the maximum allowed.
549    #[error("The task's stack size exceeds the maximum allowed size")]
550    TaskTooLarge,
551    /// The task's alignment exceeds the maximum allowed.
552    #[error("The task's alignment requirement exceeds the maximum allowed alignment")]
553    TaskAlignmentTooLarge,
554    /// A type conversion error occurred.
555    #[error("Type conversion error")]
556    ConversionError(&'static str),
557    /// An unhandled error code was returned by the C API.
558    #[error("Unhandled error code: {0}")]
559    Unhandled(i32),
560}
561
562// ── From<CFE_Status_t> ─────────────────────────────────────
563
564impl From<ffi::CFE_Status_t> for CfsError {
565    fn from(status: ffi::CFE_Status_t) -> Self {
566        match status {
567            // --- Generic CFE Status ---
568            ffi::CFE_STATUS_WRONG_MSG_LENGTH => CfsError::WrongMsgLength,
569            ffi::CFE_STATUS_UNKNOWN_MSG_ID => CfsError::UnknownMsgId,
570            ffi::CFE_STATUS_BAD_COMMAND_CODE => CfsError::BadCommandCode,
571            ffi::CFE_STATUS_EXTERNAL_RESOURCE_FAIL => CfsError::ExternalResourceFail,
572            ffi::CFE_STATUS_REQUEST_ALREADY_PENDING => CfsError::RequestAlreadyPending,
573            ffi::CFE_STATUS_VALIDATION_FAILURE => CfsError::ValidationFailure,
574            ffi::CFE_STATUS_RANGE_ERROR => CfsError::RangeError,
575            ffi::CFE_STATUS_INCORRECT_STATE => CfsError::IncorrectState,
576            ffi::CFE_STATUS_NOT_IMPLEMENTED => CfsError::NotImplemented,
577
578            // --- CFE EVS (Event Services) ---
579            ffi::CFE_EVS_UNKNOWN_FILTER => EvsError::UnknownFilter.into(),
580            ffi::CFE_EVS_APP_NOT_REGISTERED => EvsError::AppNotRegistered.into(),
581            ffi::CFE_EVS_APP_ILLEGAL_APP_ID => EvsError::AppIllegalAppId.into(),
582            ffi::CFE_EVS_APP_FILTER_OVERLOAD => EvsError::AppFilterOverload.into(),
583            ffi::CFE_EVS_RESET_AREA_POINTER => EvsError::ResetAreaPointer.into(),
584            ffi::CFE_EVS_EVT_NOT_REGISTERED => EvsError::EvtNotRegistered.into(),
585            ffi::CFE_EVS_FILE_WRITE_ERROR => EvsError::FileWriteError.into(),
586            ffi::CFE_EVS_INVALID_PARAMETER => EvsError::InvalidParameter.into(),
587            ffi::CFE_EVS_APP_SQUELCHED => EvsError::AppSquelched.into(),
588            ffi::CFE_EVS_NOT_IMPLEMENTED => EvsError::NotImplemented.into(),
589
590            // --- CFE ES (Executive Services) ---
591            ffi::CFE_ES_ERR_RESOURCEID_NOT_VALID => EsError::ResourceIdNotValid.into(),
592            ffi::CFE_ES_ERR_NAME_NOT_FOUND => EsError::NameNotFound.into(),
593            ffi::CFE_ES_ERR_APP_CREATE => EsError::AppCreate.into(),
594            ffi::CFE_ES_ERR_CHILD_TASK_CREATE => EsError::ChildTaskCreate.into(),
595            ffi::CFE_ES_ERR_SYS_LOG_FULL => EsError::SysLogFull.into(),
596            ffi::CFE_ES_ERR_MEM_BLOCK_SIZE => EsError::MemBlockSize.into(),
597            ffi::CFE_ES_ERR_LOAD_LIB => EsError::LoadLib.into(),
598            ffi::CFE_ES_BAD_ARGUMENT => EsError::BadArgument.into(),
599            ffi::CFE_ES_ERR_CHILD_TASK_REGISTER => EsError::ChildTaskRegister.into(),
600            ffi::CFE_ES_CDS_INSUFFICIENT_MEMORY => EsError::CdsInsufficientMemory.into(),
601            ffi::CFE_ES_CDS_INVALID_NAME => EsError::CdsInvalidName.into(),
602            ffi::CFE_ES_CDS_INVALID_SIZE => EsError::CdsInvalidSize.into(),
603            ffi::CFE_ES_CDS_INVALID => EsError::CdsInvalid.into(),
604            ffi::CFE_ES_CDS_ACCESS_ERROR => EsError::CdsAccessError.into(),
605            ffi::CFE_ES_FILE_IO_ERR => EsError::FileIoErr.into(),
606            ffi::CFE_ES_RST_ACCESS_ERR => EsError::RstAccessErr.into(),
607            ffi::CFE_ES_ERR_APP_REGISTER => EsError::AppRegister.into(),
608            ffi::CFE_ES_ERR_CHILD_TASK_DELETE => EsError::ChildTaskDelete.into(),
609            ffi::CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK => EsError::ChildTaskDeleteMainTask.into(),
610            ffi::CFE_ES_CDS_BLOCK_CRC_ERR => EsError::CdsBlockCrcErr.into(),
611            ffi::CFE_ES_MUT_SEM_DELETE_ERR => EsError::MutSemDeleteErr.into(),
612            ffi::CFE_ES_BIN_SEM_DELETE_ERR => EsError::BinSemDeleteErr.into(),
613            ffi::CFE_ES_COUNT_SEM_DELETE_ERR => EsError::CountSemDeleteErr.into(),
614            ffi::CFE_ES_QUEUE_DELETE_ERR => EsError::QueueDeleteErr.into(),
615            ffi::CFE_ES_FILE_CLOSE_ERR => EsError::FileCloseErr.into(),
616            ffi::CFE_ES_CDS_WRONG_TYPE_ERR => EsError::CdsWrongTypeErr.into(),
617            ffi::CFE_ES_CDS_OWNER_ACTIVE_ERR => EsError::CdsOwnerActiveErr.into(),
618            ffi::CFE_ES_APP_CLEANUP_ERR => EsError::AppCleanupErr.into(),
619            ffi::CFE_ES_TIMER_DELETE_ERR => EsError::TimerDeleteErr.into(),
620            ffi::CFE_ES_BUFFER_NOT_IN_POOL => EsError::BufferNotInPool.into(),
621            ffi::CFE_ES_TASK_DELETE_ERR => EsError::TaskDeleteErr.into(),
622            ffi::CFE_ES_OPERATION_TIMED_OUT => EsError::OperationTimedOut.into(),
623            ffi::CFE_ES_NO_RESOURCE_IDS_AVAILABLE => EsError::NoResourceIdsAvailable.into(),
624            ffi::CFE_ES_POOL_BLOCK_INVALID => EsError::PoolBlockInvalid.into(),
625            ffi::CFE_ES_ERR_DUPLICATE_NAME => EsError::DuplicateName.into(),
626            ffi::CFE_ES_NOT_IMPLEMENTED => EsError::NotImplemented.into(),
627
628            // --- CFE FS (File Services) ---
629            ffi::CFE_FS_BAD_ARGUMENT => FsError::BadArgument.into(),
630            ffi::CFE_FS_INVALID_PATH => FsError::InvalidPath.into(),
631            ffi::CFE_FS_FNAME_TOO_LONG => FsError::FnameTooLong.into(),
632            ffi::CFE_FS_NOT_IMPLEMENTED => FsError::NotImplemented.into(),
633
634            // --- CFE SB (Software Bus) ---
635            ffi::CFE_SB_TIME_OUT => SbError::TimeOut.into(),
636            ffi::CFE_SB_NO_MESSAGE => SbError::NoMessage.into(),
637            ffi::CFE_SB_BAD_ARGUMENT => SbError::BadArgument.into(),
638            ffi::CFE_SB_MAX_PIPES_MET => SbError::MaxPipesMet.into(),
639            ffi::CFE_SB_PIPE_CR_ERR => SbError::PipeCrErr.into(),
640            ffi::CFE_SB_PIPE_RD_ERR => SbError::PipeRdErr.into(),
641            ffi::CFE_SB_MSG_TOO_BIG => SbError::MsgTooBig.into(),
642            ffi::CFE_SB_BUF_ALOC_ERR => SbError::BufAllocErr.into(),
643            ffi::CFE_SB_MAX_MSGS_MET => SbError::MaxMsgsMet.into(),
644            ffi::CFE_SB_MAX_DESTS_MET => SbError::MaxDestsMet.into(),
645            ffi::CFE_SB_INTERNAL_ERR => SbError::InternalErr.into(),
646            ffi::CFE_SB_WRONG_MSG_TYPE => SbError::WrongMsgType.into(),
647            ffi::CFE_SB_BUFFER_INVALID => SbError::BufferInvalid.into(),
648            ffi::CFE_SB_NOT_IMPLEMENTED => SbError::NotImplemented.into(),
649
650            // --- CFE TBL (Table Services) ---
651            ffi::CFE_TBL_ERR_INVALID_HANDLE => TblError::InvalidHandle.into(),
652            ffi::CFE_TBL_ERR_INVALID_NAME => TblError::InvalidName.into(),
653            ffi::CFE_TBL_ERR_INVALID_SIZE => TblError::InvalidSize.into(),
654            ffi::CFE_TBL_ERR_NEVER_LOADED => TblError::NeverLoaded.into(),
655            ffi::CFE_TBL_ERR_REGISTRY_FULL => TblError::RegistryFull.into(),
656            ffi::CFE_TBL_ERR_NO_ACCESS => TblError::NoAccess.into(),
657            ffi::CFE_TBL_ERR_UNREGISTERED => TblError::Unregistered.into(),
658            ffi::CFE_TBL_ERR_HANDLES_FULL => TblError::HandlesFull.into(),
659            ffi::CFE_TBL_ERR_DUPLICATE_DIFF_SIZE => TblError::DuplicateDiffSize.into(),
660            ffi::CFE_TBL_ERR_DUPLICATE_NOT_OWNED => TblError::DuplicateNotOwned.into(),
661            ffi::CFE_TBL_ERR_NO_BUFFER_AVAIL => TblError::NoBufferAvail.into(),
662            ffi::CFE_TBL_ERR_DUMP_ONLY => TblError::DumpOnly.into(),
663            ffi::CFE_TBL_ERR_ILLEGAL_SRC_TYPE => TblError::IllegalSrcType.into(),
664            ffi::CFE_TBL_ERR_LOAD_IN_PROGRESS => TblError::LoadInProgress.into(),
665            ffi::CFE_TBL_ERR_FILE_TOO_LARGE => TblError::FileTooLarge.into(),
666            ffi::CFE_TBL_ERR_BAD_CONTENT_ID => TblError::BadContentId.into(),
667            ffi::CFE_TBL_ERR_BAD_SUBTYPE_ID => TblError::BadSubtypeId.into(),
668            ffi::CFE_TBL_ERR_FILE_SIZE_INCONSISTENT => TblError::FileSizeInconsistent.into(),
669            ffi::CFE_TBL_ERR_NO_STD_HEADER => TblError::NoStdHeader.into(),
670            ffi::CFE_TBL_ERR_NO_TBL_HEADER => TblError::NoTblHeader.into(),
671            ffi::CFE_TBL_ERR_FILENAME_TOO_LONG => TblError::FilenameTooLong.into(),
672            ffi::CFE_TBL_ERR_FILE_FOR_WRONG_TABLE => TblError::FileForWrongTable.into(),
673            ffi::CFE_TBL_ERR_LOAD_INCOMPLETE => TblError::LoadIncomplete.into(),
674            ffi::CFE_TBL_ERR_PARTIAL_LOAD => TblError::PartialLoad.into(),
675            ffi::CFE_TBL_ERR_INVALID_OPTIONS => TblError::InvalidOptions.into(),
676            ffi::CFE_TBL_ERR_BAD_SPACECRAFT_ID => TblError::BadSpacecraftId.into(),
677            ffi::CFE_TBL_ERR_BAD_PROCESSOR_ID => TblError::BadProcessorId.into(),
678            ffi::CFE_TBL_MESSAGE_ERROR => TblError::MessageError.into(),
679            ffi::CFE_TBL_ERR_SHORT_FILE => TblError::ShortFile.into(),
680            ffi::CFE_TBL_ERR_ACCESS => TblError::Access.into(),
681            ffi::CFE_TBL_BAD_ARGUMENT => TblError::BadArgument.into(),
682            ffi::CFE_TBL_NOT_IMPLEMENTED => TblError::NotImplemented.into(),
683
684            // --- CFE TIME (Time Services) ---
685            ffi::CFE_TIME_NOT_IMPLEMENTED => TimeError::NotImplemented.into(),
686            ffi::CFE_TIME_INTERNAL_ONLY => TimeError::InternalOnly.into(),
687            ffi::CFE_TIME_OUT_OF_RANGE => TimeError::OutOfRange.into(),
688            ffi::CFE_TIME_TOO_MANY_SYNCH_CALLBACKS => TimeError::TooManySynchCallbacks.into(),
689            ffi::CFE_TIME_CALLBACK_NOT_REGISTERED => TimeError::CallbackNotRegistered.into(),
690            ffi::CFE_TIME_BAD_ARGUMENT => TimeError::BadArgument.into(),
691
692            // --- OSAL Status Codes ---
693            ffi::OS_ERROR => OsalError::Error.into(),
694            ffi::OS_INVALID_POINTER => OsalError::InvalidPointer.into(),
695            ffi::OS_ERROR_ADDRESS_MISALIGNED => OsalError::AddressMisaligned.into(),
696            ffi::OS_ERROR_TIMEOUT => OsalError::Timeout.into(),
697            ffi::OS_INVALID_INT_NUM => OsalError::InvalidIntNum.into(),
698            ffi::OS_SEM_FAILURE => OsalError::SemFailure.into(),
699            ffi::OS_SEM_TIMEOUT => OsalError::SemTimeout.into(),
700            ffi::OS_QUEUE_EMPTY => OsalError::QueueEmpty.into(),
701            ffi::OS_QUEUE_FULL => OsalError::QueueFull.into(),
702            ffi::OS_QUEUE_TIMEOUT => OsalError::QueueTimeout.into(),
703            ffi::OS_QUEUE_INVALID_SIZE => OsalError::QueueInvalidSize.into(),
704            ffi::OS_QUEUE_ID_ERROR => OsalError::QueueIdError.into(),
705            ffi::OS_ERR_NAME_TOO_LONG => OsalError::NameTooLong.into(),
706            ffi::OS_ERR_NO_FREE_IDS => OsalError::NoFreeIds.into(),
707            ffi::OS_ERR_NAME_TAKEN => OsalError::NameTaken.into(),
708            ffi::OS_ERR_INVALID_ID => OsalError::InvalidId.into(),
709            ffi::OS_ERR_NAME_NOT_FOUND => OsalError::NameNotFound.into(),
710            ffi::OS_ERR_SEM_NOT_FULL => OsalError::SemNotFull.into(),
711            ffi::OS_ERR_INVALID_PRIORITY => OsalError::InvalidPriority.into(),
712            ffi::OS_INVALID_SEM_VALUE => OsalError::InvalidSemValue.into(),
713            ffi::OS_ERR_FILE => OsalError::File.into(),
714            ffi::OS_ERR_NOT_IMPLEMENTED => OsalError::NotImplemented.into(),
715            ffi::OS_TIMER_ERR_INVALID_ARGS => OsalError::TimerInvalidArgs.into(),
716            ffi::OS_TIMER_ERR_TIMER_ID => OsalError::TimerIdError.into(),
717            ffi::OS_TIMER_ERR_UNAVAILABLE => OsalError::TimerUnavailable.into(),
718            ffi::OS_TIMER_ERR_INTERNAL => OsalError::TimerInternal.into(),
719            ffi::OS_ERR_OBJECT_IN_USE => OsalError::ObjectInUse.into(),
720            ffi::OS_ERR_BAD_ADDRESS => OsalError::BadAddress.into(),
721            ffi::OS_ERR_INCORRECT_OBJ_STATE => OsalError::IncorrectObjState.into(),
722            ffi::OS_ERR_INCORRECT_OBJ_TYPE => OsalError::IncorrectObjType.into(),
723            ffi::OS_ERR_STREAM_DISCONNECTED => OsalError::StreamDisconnected.into(),
724            ffi::OS_ERR_OPERATION_NOT_SUPPORTED => OsalError::OperationNotSupported.into(),
725            ffi::OS_ERR_INVALID_SIZE => OsalError::InvalidSize.into(),
726            ffi::OS_ERR_OUTPUT_TOO_LARGE => OsalError::OutputTooLarge.into(),
727            ffi::OS_ERR_INVALID_ARGUMENT => OsalError::InvalidArgument.into(),
728            ffi::OS_FS_ERR_PATH_TOO_LONG => OsalError::FsPathTooLong.into(),
729            ffi::OS_FS_ERR_NAME_TOO_LONG => OsalError::FsNameTooLong.into(),
730            ffi::OS_FS_ERR_DRIVE_NOT_CREATED => OsalError::FsDriveNotCreated.into(),
731            ffi::OS_FS_ERR_DEVICE_NOT_FREE => OsalError::FsDeviceNotFree.into(),
732            ffi::OS_FS_ERR_PATH_INVALID => OsalError::FsPathInvalid.into(),
733
734            other => CfsError::Unhandled(other),
735        }
736    }
737}
738
739// ── Helper functions ────────────────────────────────────────
740
741impl CfsError {
742    /// Retrieves the symbolic name for an OSAL status code.
743    pub fn name(error: i32) -> Result<CString<{ ffi::OS_ERROR_NAME_LENGTH as usize }>> {
744        const SIZE: usize = ffi::OS_ERROR_NAME_LENGTH as usize;
745        let mut name_buf = [0 as libc::c_char; SIZE];
746        check(unsafe { ffi::OS_GetErrorName(error, &mut name_buf) })?;
747
748        let c_str = unsafe { core::ffi::CStr::from_ptr(name_buf.as_ptr()) };
749        let mut s = CString::new();
750        s.extend_from_bytes(c_str.to_bytes())
751            .map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
752        Ok(s)
753    }
754}
755
756/// Retrieves the symbolic name for a CFE status code.
757pub fn get_cfe_status_name(
758    status: i32,
759) -> Result<CString<{ ffi::CFE_STATUS_STRING_LENGTH as usize }>> {
760    const SIZE: usize = ffi::CFE_STATUS_STRING_LENGTH as usize;
761    let mut name_buf = [0 as libc::c_char; SIZE];
762    unsafe { ffi::CFE_ES_StatusToString(status, &mut name_buf) };
763
764    let c_str = unsafe { core::ffi::CStr::from_ptr(name_buf.as_ptr()) };
765    let mut s = CString::new();
766    s.extend_from_bytes(c_str.to_bytes())
767        .map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
768    Ok(s)
769}
770
771/// Converts an OSAL status code to its decimal or hex string
772/// representation.
773pub fn osal_status_to_string(
774    status: i32,
775) -> Result<CString<{ ffi::OS_STATUS_STRING_LENGTH as usize }>> {
776    const SIZE: usize = ffi::OS_STATUS_STRING_LENGTH as usize;
777    let mut name_buf = [0 as libc::c_char; SIZE];
778    unsafe { ffi::OS_StatusToString(status, &mut name_buf) };
779
780    let c_str = unsafe { core::ffi::CStr::from_ptr(name_buf.as_ptr()) };
781    let mut s = CString::new();
782    s.extend_from_bytes(c_str.to_bytes())
783        .map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
784    Ok(s)
785}