diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index d0ea2f2..eded68e 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -411,7 +411,7 @@ impl EcssEnumeration for EventU32 { 32 } - fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { self.base.write_to_bytes(self.raw(), buf, self.byte_width()) } } @@ -420,7 +420,7 @@ impl EcssEnumeration for EventU32 { impl EcssEnumeration for EventU32TypedSev { delegate!(to self.event { fn pfc(&self) -> u8; - fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>; + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>; }); } @@ -542,11 +542,12 @@ impl EventU16TypedSev { impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8); impl EcssEnumeration for EventU16 { + #[inline] fn pfc(&self) -> u8 { 16 } - fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { self.base.write_to_bytes(self.raw(), buf, self.byte_width()) } } @@ -555,7 +556,7 @@ impl EcssEnumeration for EventU16 { impl EcssEnumeration for EventU16TypedSev { delegate!(to self.event { fn pfc(&self) -> u8; - fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>; + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>; }); } @@ -574,6 +575,34 @@ try_from_impls!(SeverityLow, Severity::LOW, u16, EventU16TypedSev); try_from_impls!(SeverityMedium, Severity::MEDIUM, u16, EventU16TypedSev); try_from_impls!(SeverityHigh, Severity::HIGH, u16, EventU16TypedSev); +impl PartialEq for EventU32TypedSev { + #[inline] + fn eq(&self, other: &EventU32) -> bool { + self.raw() == other.raw() + } +} + +impl PartialEq> for EventU32 { + #[inline] + fn eq(&self, other: &EventU32TypedSev) -> bool { + self.raw() == other.raw() + } +} + +impl PartialEq for EventU16TypedSev { + #[inline] + fn eq(&self, other: &EventU16) -> bool { + self.raw() == other.raw() + } +} + +impl PartialEq> for EventU16 { + #[inline] + fn eq(&self, other: &EventU16TypedSev) -> bool { + self.raw() == other.raw() + } +} + #[cfg(test)] mod tests { use super::EventU32TypedSev; @@ -713,7 +742,7 @@ mod tests { #[test] fn write_to_buf() { let mut buf: [u8; 4] = [0; 4]; - assert!(HIGH_SEV_EVENT.write_to_bytes(&mut buf).is_ok()); + assert!(HIGH_SEV_EVENT.write_to_be_bytes(&mut buf).is_ok()); let val_from_raw = u32::from_be_bytes(buf); assert_eq!(val_from_raw, 0xFFFFFFFF); } @@ -721,7 +750,7 @@ mod tests { #[test] fn write_to_buf_small() { let mut buf: [u8; 2] = [0; 2]; - assert!(HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf).is_ok()); + assert!(HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf).is_ok()); let val_from_raw = u16::from_be_bytes(buf); assert_eq!(val_from_raw, 0xFFFF); } @@ -729,7 +758,7 @@ mod tests { #[test] fn write_to_buf_insufficient_buf() { let mut buf: [u8; 3] = [0; 3]; - let err = HIGH_SEV_EVENT.write_to_bytes(&mut buf); + let err = HIGH_SEV_EVENT.write_to_be_bytes(&mut buf); assert!(err.is_err()); let err = err.unwrap_err(); if let ByteConversionError::ToSliceTooSmall(missmatch) = err { @@ -741,7 +770,7 @@ mod tests { #[test] fn write_to_buf_small_insufficient_buf() { let mut buf: [u8; 1] = [0; 1]; - let err = HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf); + let err = HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf); assert!(err.is_err()); let err = err.unwrap_err(); if let ByteConversionError::ToSliceTooSmall(missmatch) = err { diff --git a/fsrc-core/src/pus/event.rs b/fsrc-core/src/pus/event.rs index f7b7e36..a4867e6 100644 --- a/fsrc-core/src/pus/event.rs +++ b/fsrc-core/src/pus/event.rs @@ -152,7 +152,7 @@ impl EventReporterBase { time_stamp, ); let mut current_idx = 0; - event_id.write_to_bytes(&mut buf[0..event_id.byte_width()])?; + event_id.write_to_be_bytes(&mut buf[0..event_id.byte_width()])?; current_idx += event_id.byte_width(); if let Some(aux_data) = aux_data { buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); diff --git a/fsrc-core/src/pus/verification.rs b/fsrc-core/src/pus/verification.rs index 0908b01..da56f69 100644 --- a/fsrc-core/src/pus/verification.rs +++ b/fsrc-core/src/pus/verification.rs @@ -536,7 +536,7 @@ impl VerificationReporterBasic { idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check was done beforehand - step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) + step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); } let mut sp_header = SpHeader::tm(self.apid(), 0, 0).unwrap(); @@ -571,13 +571,13 @@ impl VerificationReporterBasic { idx += RequestId::SIZE_AS_BYTES; if let Some(step) = step { // Size check done beforehand - step.write_to_bytes(&mut buf[idx..idx + step.byte_width() as usize]) + step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize]) .unwrap(); idx += step.byte_width() as usize; } params .failure_code - .write_to_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?; + .write_to_be_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?; idx += params.failure_code.byte_width() as usize; if let Some(failure_data) = params.failure_data { buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); @@ -1344,7 +1344,7 @@ mod tests { let fail_code = EcssEnumU8::new(10); let fail_data = EcssEnumU32::new(12); let mut fail_data_raw = [0; 4]; - fail_data.write_to_bytes(&mut fail_data_raw).unwrap(); + fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap(); let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, Some(fail_data_raw.as_slice())); b.vr.acceptance_failure(tok, &mut sender, fail_params) .expect("Sending acceptance success failed"); diff --git a/fsrc-core/src/util.rs b/fsrc-core/src/util.rs index 6622eb9..3967fee 100644 --- a/fsrc-core/src/util.rs +++ b/fsrc-core/src/util.rs @@ -32,13 +32,16 @@ use core::fmt::Debug; use core::mem::size_of; use paste::paste; pub use spacepackets::ecss::ToBeBytes; -use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8}; +use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8, EcssEnumeration}; use spacepackets::ByteConversionError; use spacepackets::SizeMissmatch; +/// Generic trait which is used for objects which can be converted into a raw network (big) endian +/// byte format. pub trait WritableAsBeBytes { fn raw_len(&self) -> usize; - fn write_be(&self, buf: &mut [u8]) -> Result; + /// Writes the object to a raw buffer in network endianness (big) + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result; } macro_rules! param_to_be_bytes_impl { @@ -49,7 +52,7 @@ macro_rules! param_to_be_bytes_impl { size_of::<::ByteArray>() } - fn write_be(&self, buf: &mut [u8]) -> Result { + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { let raw_len = self.raw_len(); if buf.len() < raw_len { return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { @@ -137,7 +140,7 @@ macro_rules! primitive_newtypes { primitive_newtypes_with_eq!(u8, u16, u32, u64, i8, i16, i32, i64,); primitive_newtypes!(f32, f64,); -macro_rules! scalar_to_be_bytes_impl { +macro_rules! scalar_byte_conversions_impl { ($($ty: ty,)+) => { $( paste! { @@ -147,12 +150,26 @@ macro_rules! scalar_to_be_bytes_impl { self.0.to_be_bytes() } } + + impl TryFrom<&[u8]> for [<$ty:upper>] { + type Error = ByteConversionError; + + fn try_from(v: &[u8]) -> Result { + if v.len() < size_of::<$ty>() { + return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { + expected: size_of::<$ty>(), + found: v.len() + })); + } + Ok([<$ty:upper>]($ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()))) + } + } } )+ } } -macro_rules! pair_to_be_bytes_impl { +macro_rules! pair_byte_conversions_impl { ($($ty: ty,)+) => { $( paste! { @@ -167,6 +184,23 @@ macro_rules! pair_to_be_bytes_impl { array } } + + impl TryFrom<&[u8]> for [<$ty:upper Pair>] { + type Error = ByteConversionError; + + fn try_from(v: &[u8]) -> Result { + if v.len() < 2 * size_of::<$ty>() { + return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { + expected: 2 * size_of::<$ty>(), + found: v.len() + })); + } + Ok([<$ty:upper Pair>]( + $ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()), + $ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap()) + )) + } + } } )+ } @@ -182,20 +216,37 @@ macro_rules! triplet_to_be_bytes_impl { let mut array = [0; size_of::<$ty>() * 3]; array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes()); array[ - size_of::<$ty>()..2* size_of::<$ty>() + size_of::<$ty>()..2 * size_of::<$ty>() ].copy_from_slice(&self.1.to_be_bytes()); array[ - 2 * size_of::<$ty>()..3* size_of::<$ty>() + 2 * size_of::<$ty>()..3 * size_of::<$ty>() ].copy_from_slice(&self.2.to_be_bytes()); array } } + impl TryFrom<&[u8]> for [<$ty:upper Triplet>] { + type Error = ByteConversionError; + + fn try_from(v: &[u8]) -> Result { + if v.len() < 3 * size_of::<$ty>() { + return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { + expected: 3 * size_of::<$ty>(), + found: v.len() + })); + } + Ok([<$ty:upper Triplet>]( + $ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()), + $ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap()), + $ty::from_be_bytes(v[2 * size_of::<$ty>()..3 * size_of::<$ty>()].try_into().unwrap()) + )) + } + } } )+ } } -scalar_to_be_bytes_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,); +scalar_byte_conversions_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,); impl ToBeBytes for U8Pair { type ByteArray = [u8; 2]; @@ -243,7 +294,7 @@ impl ToBeBytes for I8Triplet { } } -pair_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); +pair_byte_conversions_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); triplet_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); /// Generic enumeration for additonal parameters only consisting of primitive data types. @@ -305,35 +356,36 @@ impl WritableAsBeBytes for ParamsRaw { } } - fn write_be(&self, buf: &mut [u8]) -> Result { + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { match self { - ParamsRaw::U8(v) => v.write_be(buf), - ParamsRaw::U8Pair(v) => v.write_be(buf), - ParamsRaw::U8Triplet(v) => v.write_be(buf), - ParamsRaw::I8(v) => v.write_be(buf), - ParamsRaw::I8Pair(v) => v.write_be(buf), - ParamsRaw::I8Triplet(v) => v.write_be(buf), - ParamsRaw::U16(v) => v.write_be(buf), - ParamsRaw::U16Pair(v) => v.write_be(buf), - ParamsRaw::U16Triplet(v) => v.write_be(buf), - ParamsRaw::I16(v) => v.write_be(buf), - ParamsRaw::I16Pair(v) => v.write_be(buf), - ParamsRaw::I16Triplet(v) => v.write_be(buf), - ParamsRaw::U32(v) => v.write_be(buf), - ParamsRaw::U32Pair(v) => v.write_be(buf), - ParamsRaw::U32Triplet(v) => v.write_be(buf), - ParamsRaw::I32(v) => v.write_be(buf), - ParamsRaw::I32Pair(v) => v.write_be(buf), - ParamsRaw::I32Triplet(v) => v.write_be(buf), - ParamsRaw::F32(v) => v.write_be(buf), - ParamsRaw::F32Pair(v) => v.write_be(buf), - ParamsRaw::F32Triplet(v) => v.write_be(buf), - ParamsRaw::U64(v) => v.write_be(buf), - ParamsRaw::I64(v) => v.write_be(buf), - ParamsRaw::F64(v) => v.write_be(buf), + ParamsRaw::U8(v) => v.write_to_be_bytes(buf), + ParamsRaw::U8Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::U8Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::I8(v) => v.write_to_be_bytes(buf), + ParamsRaw::I8Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::I8Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::U16(v) => v.write_to_be_bytes(buf), + ParamsRaw::U16Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::U16Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::I16(v) => v.write_to_be_bytes(buf), + ParamsRaw::I16Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::I16Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::U32(v) => v.write_to_be_bytes(buf), + ParamsRaw::U32Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::U32Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::I32(v) => v.write_to_be_bytes(buf), + ParamsRaw::I32Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::I32Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::F32(v) => v.write_to_be_bytes(buf), + ParamsRaw::F32Pair(v) => v.write_to_be_bytes(buf), + ParamsRaw::F32Triplet(v) => v.write_to_be_bytes(buf), + ParamsRaw::U64(v) => v.write_to_be_bytes(buf), + ParamsRaw::I64(v) => v.write_to_be_bytes(buf), + ParamsRaw::F64(v) => v.write_to_be_bytes(buf), } } } + macro_rules! params_raw_from_newtype { ($($newtype: ident,)+) => { $( @@ -360,6 +412,45 @@ pub enum EcssEnumParams { U64(EcssEnumU64), } +macro_rules! writable_as_be_bytes_ecss_enum_impl { + ($EnumIdent: ident) => { + impl WritableAsBeBytes for $EnumIdent { + fn raw_len(&self) -> usize { + self.byte_width() + } + + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { + EcssEnumeration::write_to_be_bytes(self, buf).map(|_| self.byte_width()) + } + } + }; +} + +writable_as_be_bytes_ecss_enum_impl!(EcssEnumU8); +writable_as_be_bytes_ecss_enum_impl!(EcssEnumU16); +writable_as_be_bytes_ecss_enum_impl!(EcssEnumU32); +writable_as_be_bytes_ecss_enum_impl!(EcssEnumU64); + +impl WritableAsBeBytes for EcssEnumParams { + fn raw_len(&self) -> usize { + match self { + EcssEnumParams::U8(e) => e.byte_width(), + EcssEnumParams::U16(e) => e.byte_width(), + EcssEnumParams::U32(e) => e.byte_width(), + EcssEnumParams::U64(e) => e.byte_width(), + } + } + + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { + match self { + EcssEnumParams::U8(e) => WritableAsBeBytes::write_to_be_bytes(e, buf), + EcssEnumParams::U16(e) => WritableAsBeBytes::write_to_be_bytes(e, buf), + EcssEnumParams::U32(e) => WritableAsBeBytes::write_to_be_bytes(e, buf), + EcssEnumParams::U64(e) => WritableAsBeBytes::write_to_be_bytes(e, buf), + } + } +} + /// Generic enumeration for parameters which do not rely on heap allocations. #[derive(Debug, Copy, Clone, PartialEq)] pub enum ParamsHeapless { diff --git a/fsrc-core/tests/pus_events.rs b/fsrc-core/tests/pus_events.rs index 5d4f1c8..9d402e7 100644 --- a/fsrc-core/tests/pus_events.rs +++ b/fsrc-core/tests/pus_events.rs @@ -2,7 +2,9 @@ use fsrc_core::event_man::{EventManager, MpscEventReceiver, MpscEventU32SendProv use fsrc_core::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo}; use fsrc_core::pus::event_man::{DefaultPusMgmtBackendProvider, EventReporter, PusEventTmManager}; use fsrc_core::pus::{EcssTmError, EcssTmSender}; -use fsrc_core::util::{Params, ParamsHeapless, ParamsRaw}; +use fsrc_core::util::U32Pair; +use fsrc_core::util::{Params, ParamsHeapless, WritableAsBeBytes}; +use spacepackets::ecss::PusPacket; use spacepackets::tm::PusTm; use std::sync::mpsc::{channel, SendError, TryRecvError}; use std::thread; @@ -43,55 +45,41 @@ fn test_threaded_usage() { let jh0 = thread::spawn(move || { let mut sender = EventTmSender { sender: event_tx }; let mut event_cnt = 0; - let _params_array: [u8; 256] = [0; 256]; + let mut params_array: [u8; 128] = [0; 128]; loop { let res = event_man.try_event_handling(); assert!(res.is_ok()); match pus_event_man_rx.try_recv() { Ok((event, aux_data)) => { - // TODO: Convert auxiliary data into raw byte format - if let Some(aux_data) = aux_data { + let mut gen_event = |aux_data| { + pus_event_man.generate_pus_event_tm_generic( + &mut sender, + &EMPTY_STAMP, + event, + aux_data, + ) + }; + let res = if let Some(aux_data) = aux_data { match aux_data { Params::Heapless(heapless) => match heapless { - ParamsHeapless::Raw(raw) => match raw { - ParamsRaw::U8(_) => {} - ParamsRaw::U8Pair(_) => {} - ParamsRaw::U8Triplet(_) => {} - ParamsRaw::I8(_) => {} - ParamsRaw::I8Pair(_) => {} - ParamsRaw::I8Triplet(_) => {} - ParamsRaw::U16(_) => {} - ParamsRaw::U16Pair(_) => {} - ParamsRaw::U16Triplet(_) => {} - ParamsRaw::I16(_) => {} - ParamsRaw::I16Pair(_) => {} - ParamsRaw::I16Triplet(_) => {} - ParamsRaw::U32(_) => {} - ParamsRaw::U32Pair(_) => {} - ParamsRaw::U32Triplet(_) => {} - ParamsRaw::I32(_) => {} - ParamsRaw::I32Pair(_) => {} - ParamsRaw::I32Triplet(_) => {} - ParamsRaw::F32(_) => {} - ParamsRaw::F32Pair(_) => {} - ParamsRaw::F32Triplet(_) => {} - ParamsRaw::U64(_) => {} - ParamsRaw::I64(_) => {} - ParamsRaw::F64(_) => {} - }, - ParamsHeapless::EcssEnum(_) => {} - ParamsHeapless::Store(_) => {} + ParamsHeapless::Raw(raw) => { + raw.write_to_be_bytes(&mut params_array) + .expect("Writing raw parameter failed"); + gen_event(Some(¶ms_array[0..raw.raw_len()])) + } + ParamsHeapless::EcssEnum(e) => { + e.write_to_be_bytes(&mut params_array) + .expect("Writing ECSS enum failed"); + gen_event(Some(¶ms_array[0..e.raw_len()])) + } + ParamsHeapless::Store(_) => gen_event(None), }, - Params::Vec(_) => {} - Params::String(_) => {} + Params::Vec(vec) => gen_event(Some(vec.as_slice())), + Params::String(str) => gen_event(Some(str.as_bytes())), } - } - let res = pus_event_man.generate_pus_event_tm_generic( - &mut sender, - &EMPTY_STAMP, - event, - None, - ); + } else { + gen_event(None) + }; event_cnt += 1; assert!(res.is_ok()); assert!(res.unwrap()); @@ -116,8 +104,18 @@ fn test_threaded_usage() { loop { match event_rx.try_recv() { // Event TM received successfully - Ok(event) => { - println!("{:x?}", event); + Ok(event_tm) => { + let tm = + PusTm::from_bytes(event_tm.as_slice(), 7).expect("Deserializing TM failed"); + assert_eq!(tm.0.service(), 5); + assert_eq!(tm.0.subservice(), 1); + let src_data = tm.0.source_data(); + assert!(src_data.is_some()); + let src_data = src_data.unwrap(); + assert_eq!(src_data.len(), 4); + let event = + EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); + assert_eq!(event, INFO_EVENT); break; } Err(e) => { @@ -136,8 +134,22 @@ fn test_threaded_usage() { loop { match event_rx.try_recv() { // Event TM received successfully - Ok(event) => { - println!("{:x?}", event); + Ok(event_tm) => { + let tm = + PusTm::from_bytes(event_tm.as_slice(), 7).expect("Deserializing TM failed"); + assert_eq!(tm.0.service(), 5); + assert_eq!(tm.0.subservice(), 2); + let src_data = tm.0.source_data(); + assert!(src_data.is_some()); + let src_data = src_data.unwrap(); + assert_eq!(src_data.len(), 12); + let event = + EventU32::from(u32::from_be_bytes(src_data[0..4].try_into().unwrap())); + assert_eq!(event, LOW_SEV_EVENT); + let u32_pair: U32Pair = + src_data[4..].try_into().expect("Creating U32Pair failed"); + assert_eq!(u32_pair.0, 2); + assert_eq!(u32_pair.1, 3); break; } Err(e) => { diff --git a/spacepackets b/spacepackets index 38b789c..4c1101f 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 38b789ca6d061239e6cecc76f0843d6ba8b9bd01 +Subproject commit 4c1101f65f20419606932c4ee40fb2768e8cc736