1use crate::cfe::time::SysTime;
9use crate::error::{CfsError, OsalError, Result};
10use crate::ffi;
11use crate::status::check;
12use core::mem::MaybeUninit;
13
14#[repr(transparent)]
16#[derive(Clone, Copy, Default)]
17pub struct CmdHeader(pub(crate) ffi::CFE_MSG_CommandHeader_t);
18
19impl core::fmt::Debug for CmdHeader {
20 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21 f.debug_struct("CmdHeader").finish()
22 }
23}
24
25#[repr(transparent)]
27#[derive(Clone, Copy, Default)]
28pub struct TlmHeader(pub(crate) ffi::CFE_MSG_TelemetryHeader_t);
29
30impl core::fmt::Debug for TlmHeader {
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 f.debug_struct("TlmHeader").finish()
33 }
34}
35
36#[derive(Debug, Clone, Copy)]
38#[repr(transparent)]
39pub struct MsgId(pub(crate) ffi::CFE_SB_MsgId_t);
40
41impl MsgId {
42 pub fn value(&self) -> u32 {
44 self.0.Value
45 }
46}
47
48impl PartialEq for MsgId {
49 fn eq(&self, other: &Self) -> bool {
50 self.0.Value == other.0.Value
51 }
52}
53impl Eq for MsgId {}
54
55impl MsgId {
56 pub fn is_valid(&self) -> bool {
61 self.0.Value != 0 && self.0.Value <= ffi::CFE_PLATFORM_SB_HIGHEST_VALID_MSGID
63 }
64
65 pub fn cmd(topic_id: u16, instance_num: u16) -> Self {
67 Self(ffi::CFE_SB_MsgId_t {
68 Value: unsafe { ffi::CFE_SB_CmdTopicIdToMsgId(topic_id, instance_num) },
69 })
70 }
71
72 pub fn tlm(topic_id: u16, instance_num: u16) -> Self {
74 Self(ffi::CFE_SB_MsgId_t {
75 Value: unsafe { ffi::CFE_SB_TlmTopicIdToMsgId(topic_id, instance_num) },
76 })
77 }
78
79 pub fn global_cmd(topic_id: u16) -> Self {
81 Self(ffi::CFE_SB_MsgId_t {
82 Value: unsafe { ffi::CFE_SB_GlobalCmdTopicIdToMsgId(topic_id) },
83 })
84 }
85
86 pub fn global_tlm(topic_id: u16) -> Self {
88 Self(ffi::CFE_SB_MsgId_t {
89 Value: unsafe { ffi::CFE_SB_GlobalTlmTopicIdToMsgId(topic_id) },
90 })
91 }
92
93 pub fn local_cmd(topic_id: u16) -> Self {
95 Self(ffi::CFE_SB_MsgId_t {
96 Value: unsafe { ffi::CFE_SB_LocalCmdTopicIdToMsgId(topic_id) },
97 })
98 }
99
100 pub fn local_tlm(topic_id: u16) -> Self {
102 Self(ffi::CFE_SB_MsgId_t {
103 Value: unsafe { ffi::CFE_SB_LocalTlmTopicIdToMsgId(topic_id) },
104 })
105 }
106
107 pub fn get_type(&self) -> Result<MsgType> {
109 let mut msg_type = MaybeUninit::uninit();
110 check(unsafe { ffi::CFE_MSG_GetTypeFromMsgId(self.0, msg_type.as_mut_ptr()) })?;
111 Ok(unsafe { msg_type.assume_init() }.into())
112 }
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117#[repr(u32)]
118pub enum MsgType {
119 Invalid = ffi::CFE_MSG_Type_CFE_MSG_Type_Invalid,
121 Cmd = ffi::CFE_MSG_Type_CFE_MSG_Type_Cmd,
123 Tlm = ffi::CFE_MSG_Type_CFE_MSG_Type_Tlm,
125}
126
127impl From<ffi::CFE_MSG_Type_t> for MsgType {
128 fn from(val: ffi::CFE_MSG_Type_t) -> Self {
129 match val {
130 ffi::CFE_MSG_Type_CFE_MSG_Type_Cmd => MsgType::Cmd,
131 ffi::CFE_MSG_Type_CFE_MSG_Type_Tlm => MsgType::Tlm,
132 _ => MsgType::Invalid,
133 }
134 }
135}
136
137#[derive(Debug, Copy, Clone)]
142pub struct MessageRef<'a> {
143 slice: &'a [u8],
144}
145
146impl<'a> MessageRef<'a> {
147 pub fn new(slice: &'a [u8]) -> Self {
149 Self { slice }
150 }
151
152 pub fn as_slice(&self) -> &'a [u8] {
154 self.slice
155 }
156
157 pub fn header_version(&self) -> Result<u16> {
159 let mut version = 0;
160 check(unsafe {
161 ffi::CFE_MSG_GetHeaderVersion(
162 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
163 &mut version,
164 )
165 })?;
166 Ok(version)
167 }
168
169 pub fn apid(&self) -> Result<u16> {
171 let mut apid = 0;
172 check(unsafe {
173 ffi::CFE_MSG_GetApId(
174 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
175 &mut apid,
176 )
177 })?;
178 Ok(apid)
179 }
180
181 pub fn size(&self) -> Result<usize> {
183 let mut size = 0;
184 let status = unsafe {
185 ffi::CFE_MSG_GetSize(
186 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
187 &mut size,
188 )
189 };
190 check(status)?;
191 Ok(size)
192 }
193
194 pub fn msg_id(&self) -> Result<MsgId> {
196 let mut msg_id = MaybeUninit::uninit();
197 let status = unsafe {
198 ffi::CFE_MSG_GetMsgId(
199 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
200 msg_id.as_mut_ptr(),
201 )
202 };
203 check(status)?;
204 Ok(MsgId(unsafe { msg_id.assume_init() }))
205 }
206
207 pub fn fcn_code(&self) -> Result<u16> {
211 let mut fcn_code = 0;
212 let status = unsafe {
213 ffi::CFE_MSG_GetFcnCode(
214 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
215 &mut fcn_code,
216 )
217 };
218 check(status)?;
219 Ok(fcn_code)
220 }
221
222 pub fn time(&self) -> Result<SysTime> {
226 let mut time = MaybeUninit::uninit();
227 let status = unsafe {
228 ffi::CFE_MSG_GetMsgTime(
229 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
230 time.as_mut_ptr(),
231 )
232 };
233 check(status)?;
234 Ok(SysTime(unsafe { time.assume_init() }))
235 }
236
237 pub fn sequence_count(&self) -> Result<u16> {
239 let mut count = 0;
240 let status = unsafe {
241 ffi::CFE_MSG_GetSequenceCount(
242 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
243 &mut count,
244 )
245 };
246 check(status)?;
247 Ok(count)
248 }
249
250 pub fn validate_checksum(&self) -> Result<bool> {
255 let mut is_valid = false;
256 let status = unsafe {
257 ffi::CFE_MSG_ValidateChecksum(
258 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
259 &mut is_valid,
260 )
261 };
262 check(status)?;
263 Ok(is_valid)
264 }
265
266 pub fn get_type(&self) -> Result<MsgType> {
268 let mut msg_type = MaybeUninit::uninit();
269 check(unsafe {
270 ffi::CFE_MSG_GetType(
271 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
272 msg_type.as_mut_ptr(),
273 )
274 })?;
275 Ok(unsafe { msg_type.assume_init() }.into())
276 }
277
278 pub fn has_secondary_header(&self) -> Result<bool> {
280 let mut has_secondary = false;
281 check(unsafe {
282 ffi::CFE_MSG_GetHasSecondaryHeader(
283 self.slice.as_ptr() as *const ffi::CFE_MSG_Message_t,
284 &mut has_secondary,
285 )
286 })?;
287 Ok(has_secondary)
288 }
289
290 pub unsafe fn user_data(&self) -> *mut libc::c_void {
298 ffi::CFE_SB_GetUserData(self.slice.as_ptr() as *mut ffi::CFE_MSG_Message_t)
299 }
300
301 pub fn user_data_length(&self) -> usize {
303 unsafe { ffi::CFE_SB_GetUserDataLength(self.slice.as_ptr() as *const _) }
304 }
305
306 pub fn segmentation_flag(&self) -> Result<ffi::CFE_MSG_SegmentationFlag_t> {
308 let mut flag = MaybeUninit::uninit();
309 check(unsafe {
310 ffi::CFE_MSG_GetSegmentationFlag(
311 self.as_slice().as_ptr() as *const _,
312 flag.as_mut_ptr(),
313 )
314 })?;
315 Ok(unsafe { flag.assume_init() })
316 }
317
318 pub fn eds_version(&self) -> Result<u16> {
320 let mut version = MaybeUninit::uninit();
321 check(unsafe {
322 ffi::CFE_MSG_GetEDSVersion(self.as_slice().as_ptr() as *const _, version.as_mut_ptr())
323 })?;
324 Ok(unsafe { version.assume_init() })
325 }
326
327 pub fn endian(&self) -> Result<ffi::CFE_MSG_Endian_t> {
329 let mut endian = MaybeUninit::uninit();
330 check(unsafe {
331 ffi::CFE_MSG_GetEndian(self.as_slice().as_ptr() as *const _, endian.as_mut_ptr())
332 })?;
333 Ok(unsafe { endian.assume_init() })
334 }
335
336 pub fn playback_flag(&self) -> Result<ffi::CFE_MSG_PlaybackFlag_t> {
338 let mut flag = MaybeUninit::uninit();
339 check(unsafe {
340 ffi::CFE_MSG_GetPlaybackFlag(self.as_slice().as_ptr() as *const _, flag.as_mut_ptr())
341 })?;
342 Ok(unsafe { flag.assume_init() })
343 }
344
345 pub fn subsystem(&self) -> Result<u16> {
347 let mut subsystem = MaybeUninit::uninit();
348 check(unsafe {
349 ffi::CFE_MSG_GetSubsystem(self.as_slice().as_ptr() as *const _, subsystem.as_mut_ptr())
350 })?;
351 Ok(unsafe { subsystem.assume_init() })
352 }
353
354 pub fn system(&self) -> Result<u16> {
356 let mut system = MaybeUninit::uninit();
357 check(unsafe {
358 ffi::CFE_MSG_GetSystem(self.as_slice().as_ptr() as *const _, system.as_mut_ptr())
359 })?;
360 Ok(unsafe { system.assume_init() })
361 }
362}
363
364#[derive(Debug)]
369pub struct MessageMut<'a> {
370 pub(crate) slice: &'a mut [u8],
371}
372
373impl<'a> MessageMut<'a> {
374 pub fn as_slice(&self) -> &[u8] {
376 self.slice
377 }
378
379 pub fn as_mut_slice(&mut self) -> &mut [u8] {
381 self.slice
382 }
383
384 pub fn send(self, is_origination: bool) -> Result<()> {
388 let status = unsafe {
389 ffi::CFE_SB_TransmitBuffer(self.slice.as_mut_ptr() as *mut _, is_origination)
390 };
391
392 if status == ffi::CFE_SUCCESS {
393 Ok(())
394 } else {
395 Err(CfsError::from(status))
396 }
397 }
398
399 pub fn init(&mut self, msg_id: MsgId, size: usize) -> Result<()> {
404 if size > self.slice.len() {
405 return Err(CfsError::Osal(OsalError::InvalidSize));
406 }
407 let status = unsafe {
408 ffi::CFE_MSG_Init(
409 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
410 msg_id.0,
411 size,
412 )
413 };
414 check(status)?;
415 Ok(())
416 }
417
418 pub fn set_size(&mut self, size: usize) -> Result<()> {
420 if size > self.slice.len() {
421 return Err(CfsError::Osal(OsalError::InvalidSize));
422 }
423 let status = unsafe {
424 ffi::CFE_MSG_SetSize(self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t, size)
425 };
426 check(status)?;
427 Ok(())
428 }
429
430 pub fn set_msg_id(&mut self, msg_id: MsgId) -> Result<()> {
432 let status = unsafe {
433 ffi::CFE_MSG_SetMsgId(
434 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
435 msg_id.0,
436 )
437 };
438 check(status)?;
439 Ok(())
440 }
441
442 pub fn set_header_version(&mut self, version: u16) -> Result<()> {
444 check(unsafe {
445 ffi::CFE_MSG_SetHeaderVersion(
446 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
447 version,
448 )
449 })?;
450 Ok(())
451 }
452
453 pub fn set_apid(&mut self, apid: u16) -> Result<()> {
455 check(unsafe {
456 ffi::CFE_MSG_SetApId(self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t, apid)
457 })?;
458 Ok(())
459 }
460
461 pub fn set_fcn_code(&mut self, fcn_code: u16) -> Result<()> {
465 let status = unsafe {
466 ffi::CFE_MSG_SetFcnCode(
467 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
468 fcn_code,
469 )
470 };
471 check(status)?;
472 Ok(())
473 }
474
475 pub fn set_time(&mut self, new_time: SysTime) -> Result<()> {
479 let status = unsafe {
480 ffi::CFE_MSG_SetMsgTime(
481 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
482 new_time.0,
483 )
484 };
485 check(status)?;
486 Ok(())
487 }
488
489 pub fn set_sequence_count(&mut self, count: u16) -> Result<()> {
491 let status = unsafe {
492 ffi::CFE_MSG_SetSequenceCount(
493 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
494 count,
495 )
496 };
497 check(status)?;
498 Ok(())
499 }
500
501 pub fn generate_checksum(&mut self) -> Result<()> {
505 let status = unsafe {
506 ffi::CFE_MSG_GenerateChecksum(self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t)
507 };
508 check(status)?;
509 Ok(())
510 }
511
512 pub fn set_type(&mut self, msg_type: MsgType) -> Result<()> {
514 check(unsafe {
515 ffi::CFE_MSG_SetType(
516 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
517 msg_type as ffi::CFE_MSG_Type_t,
518 )
519 })?;
520 Ok(())
521 }
522
523 pub fn set_has_secondary_header(&mut self, has_secondary: bool) -> Result<()> {
525 check(unsafe {
526 ffi::CFE_MSG_SetHasSecondaryHeader(
527 self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t,
528 has_secondary,
529 )
530 })?;
531 Ok(())
532 }
533
534 pub unsafe fn user_data(&mut self) -> *mut libc::c_void {
542 ffi::CFE_SB_GetUserData(self.slice.as_mut_ptr() as *mut ffi::CFE_MSG_Message_t)
543 }
544
545 pub fn payload<P: Sized>(&mut self) -> Result<&mut P> {
556 if core::mem::size_of::<P>() > self.user_data_length() {
557 return Err(CfsError::WrongMsgLength);
558 }
559 unsafe {
564 let payload_ptr = self.user_data() as *mut P;
565 Ok(&mut *payload_ptr)
566 }
567 }
568
569 pub fn user_data_length(&self) -> usize {
571 unsafe { ffi::CFE_SB_GetUserDataLength(self.slice.as_ptr() as *const _) }
572 }
573
574 pub fn set_user_data_length(&mut self, length: usize) {
576 unsafe { ffi::CFE_SB_SetUserDataLength(self.slice.as_mut_ptr() as *mut _, length) }
577 }
578
579 pub fn timestamp(&mut self) {
581 unsafe { ffi::CFE_SB_TimeStampMsg(self.slice.as_mut_ptr() as *mut _) }
582 }
583
584 pub fn set_segmentation_flag(&mut self, flag: ffi::CFE_MSG_SegmentationFlag_t) -> Result<()> {
586 check(unsafe {
587 ffi::CFE_MSG_SetSegmentationFlag(self.slice.as_mut_ptr() as *mut _, flag)
588 })?;
589 Ok(())
590 }
591
592 pub fn set_eds_version(&mut self, version: u16) -> Result<()> {
594 check(unsafe { ffi::CFE_MSG_SetEDSVersion(self.slice.as_mut_ptr() as *mut _, version) })?;
595 Ok(())
596 }
597
598 pub fn set_endian(&mut self, endian: ffi::CFE_MSG_Endian_t) -> Result<()> {
600 check(unsafe { ffi::CFE_MSG_SetEndian(self.slice.as_mut_ptr() as *mut _, endian) })?;
601 Ok(())
602 }
603
604 pub fn set_playback_flag(&mut self, flag: ffi::CFE_MSG_PlaybackFlag_t) -> Result<()> {
606 check(unsafe { ffi::CFE_MSG_SetPlaybackFlag(self.slice.as_mut_ptr() as *mut _, flag) })?;
607 Ok(())
608 }
609
610 pub fn set_subsystem(&mut self, subsystem: u16) -> Result<()> {
612 check(unsafe { ffi::CFE_MSG_SetSubsystem(self.slice.as_mut_ptr() as *mut _, subsystem) })?;
613 Ok(())
614 }
615
616 pub fn set_system(&mut self, system: u16) -> Result<()> {
618 check(unsafe { ffi::CFE_MSG_SetSystem(self.slice.as_mut_ptr() as *mut _, system) })?;
619 Ok(())
620 }
621}
622
623pub fn message_string_set(dest: &mut [i8], src: &str) -> Result<usize> {
632 let bytes_copied = unsafe {
633 ffi::CFE_SB_MessageStringSet(
634 dest.as_mut_ptr() as *mut libc::c_char,
635 src.as_ptr() as *const libc::c_char,
636 dest.len(),
637 src.len(),
638 )
639 };
640 if bytes_copied < 0 {
641 Err(CfsError::from(bytes_copied))
642 } else {
643 Ok(bytes_copied as usize)
644 }
645}
646
647pub fn message_string_get<'a>(
657 dest: &'a mut [u8],
658 src: &[u8],
659 default_src: Option<&str>,
660) -> Result<&'a str> {
661 let default_ptr = default_src.map_or(core::ptr::null(), |s| s.as_ptr() as *const libc::c_char);
662 let bytes_copied = unsafe {
663 ffi::CFE_SB_MessageStringGet(
664 dest.as_mut_ptr() as *mut libc::c_char,
665 src.as_ptr() as *const libc::c_char,
666 default_ptr as *const libc::c_char,
667 dest.len(),
668 src.len(),
669 )
670 };
671 if bytes_copied < 0 {
672 return Err(CfsError::from(bytes_copied));
673 }
674 core::str::from_utf8(&dest[..bytes_copied as usize]).map_err(|_| CfsError::InvalidString)
675}
676
677pub fn get_next_sequence_count(current_count: u16) -> u16 {
679 unsafe { ffi::CFE_MSG_GetNextSequenceCount(current_count) }
680}