1#[cfg(feature = "alloc")]
47use crate::pool::StoreAddr;
48#[cfg(feature = "alloc")]
49use alloc::string::{String, ToString};
50#[cfg(feature = "alloc")]
51use alloc::vec::Vec;
52use core::fmt::Debug;
53use core::mem::size_of;
54use paste::paste;
55use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8};
56use spacepackets::util::UnsignedEnum;
57use spacepackets::ByteConversionError;
58
59#[cfg(feature = "alloc")]
60pub use alloc_mod::*;
61pub use spacepackets::util::ToBeBytes;
62
63pub trait WritableToBeBytes {
66 fn raw_len(&self) -> usize;
67 fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
69}
70
71macro_rules! param_to_be_bytes_impl {
72 ($Newtype: ident) => {
73 impl WritableToBeBytes for $Newtype {
74 #[inline]
75 fn raw_len(&self) -> usize {
76 size_of::<<Self as ToBeBytes>::ByteArray>()
77 }
78
79 fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
80 let raw_len = self.raw_len();
81 if buf.len() < raw_len {
82 return Err(ByteConversionError::ToSliceTooSmall {
83 found: buf.len(),
84 expected: raw_len,
85 });
86 }
87 buf[0..raw_len].copy_from_slice(&self.to_be_bytes());
88 Ok(raw_len)
89 }
90 }
91 };
92}
93
94macro_rules! primitive_newtypes_with_eq {
95 ($($ty: ty,)+) => {
96 $(
97 paste! {
98 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
99 pub struct [<$ty:upper>](pub $ty);
100 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
101 pub struct [<$ty:upper Pair>](pub $ty, pub $ty);
102 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
103 pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
104
105 param_to_be_bytes_impl!([<$ty:upper>]);
106 param_to_be_bytes_impl!([<$ty:upper Pair>]);
107 param_to_be_bytes_impl!([<$ty:upper Triplet>]);
108
109 impl From<$ty> for [<$ty:upper>] {
110 fn from(v: $ty) -> Self {
111 Self(v)
112 }
113 }
114 impl From<($ty, $ty)> for [<$ty:upper Pair>] {
115 fn from(v: ($ty, $ty)) -> Self {
116 Self(v.0, v.1)
117 }
118 }
119 impl From<($ty, $ty, $ty)> for [<$ty:upper Triplet>] {
120 fn from(v: ($ty, $ty, $ty)) -> Self {
121 Self(v.0, v.1, v.2)
122 }
123 }
124 }
125 )+
126 }
127}
128
129macro_rules! primitive_newtypes {
130 ($($ty: ty,)+) => {
131 $(
132 paste! {
133 #[derive(Debug, Copy, Clone, PartialEq)]
134 pub struct [<$ty:upper>](pub $ty);
135 #[derive(Debug, Copy, Clone, PartialEq)]
136 pub struct [<$ty:upper Pair>](pub $ty, pub $ty);
137 #[derive(Debug, Copy, Clone, PartialEq)]
138 pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
139
140 param_to_be_bytes_impl!([<$ty:upper>]);
141 param_to_be_bytes_impl!([<$ty:upper Pair>]);
142 param_to_be_bytes_impl!([<$ty:upper Triplet>]);
143
144 impl From<$ty> for [<$ty:upper>] {
145 fn from(v: $ty) -> Self {
146 Self(v)
147 }
148 }
149 impl From<($ty, $ty)> for [<$ty:upper Pair>] {
150 fn from(v: ($ty, $ty)) -> Self {
151 Self(v.0, v.1)
152 }
153 }
154 impl From<($ty, $ty, $ty)> for [<$ty:upper Triplet>] {
155 fn from(v: ($ty, $ty, $ty)) -> Self {
156 Self(v.0, v.1, v.2)
157 }
158 }
159 }
160 )+
161 }
162}
163
164primitive_newtypes_with_eq!(u8, u16, u32, u64, i8, i16, i32, i64,);
165primitive_newtypes!(f32, f64,);
166
167macro_rules! scalar_byte_conversions_impl {
168 ($($ty: ty,)+) => {
169 $(
170 paste! {
171 impl ToBeBytes for [<$ty:upper>] {
172 type ByteArray = [u8; size_of::<$ty>()];
173
174 fn written_len(&self) -> usize {
175 size_of::<Self::ByteArray>()
176 }
177
178 fn to_be_bytes(&self) -> Self::ByteArray {
179 self.0.to_be_bytes()
180 }
181 }
182
183 impl TryFrom<&[u8]> for [<$ty:upper>] {
184 type Error = ByteConversionError;
185
186 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
187 if v.len() < size_of::<$ty>() {
188 return Err(ByteConversionError::FromSliceTooSmall{
189 expected: size_of::<$ty>(),
190 found: v.len()
191 });
192 }
193 Ok([<$ty:upper>]($ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap())))
194 }
195 }
196 }
197 )+
198 }
199}
200
201macro_rules! pair_byte_conversions_impl {
202 ($($ty: ty,)+) => {
203 $(
204 paste! {
205 impl ToBeBytes for [<$ty:upper Pair>] {
206 type ByteArray = [u8; size_of::<$ty>() * 2];
207
208 fn written_len(&self) -> usize {
209 size_of::<Self::ByteArray>()
210 }
211
212 fn to_be_bytes(&self) -> Self::ByteArray {
213 let mut array = [0; size_of::<$ty>() * 2];
214 array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
215 array[
216 size_of::<$ty>()..2 * size_of::<$ty>()
217 ].copy_from_slice(&self.1.to_be_bytes());
218 array
219 }
220 }
221
222 impl TryFrom<&[u8]> for [<$ty:upper Pair>] {
223 type Error = ByteConversionError;
224
225 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
226 if v.len() < 2 * size_of::<$ty>() {
227 return Err(ByteConversionError::FromSliceTooSmall{
228 expected: 2 * size_of::<$ty>(),
229 found: v.len()
230 });
231 }
232 Ok([<$ty:upper Pair>](
233 $ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()),
234 $ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap())
235 ))
236 }
237 }
238 }
239 )+
240 }
241}
242
243macro_rules! triplet_to_be_bytes_impl {
244 ($($ty: ty,)+) => {
245 $(
246 paste! {
247 impl ToBeBytes for [<$ty:upper Triplet>] {
248 type ByteArray = [u8; size_of::<$ty>() * 3];
249
250 fn written_len(&self) -> usize {
251 size_of::<Self::ByteArray>()
252 }
253
254 fn to_be_bytes(&self) -> Self::ByteArray {
255 let mut array = [0; size_of::<$ty>() * 3];
256 array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
257 array[
258 size_of::<$ty>()..2 * size_of::<$ty>()
259 ].copy_from_slice(&self.1.to_be_bytes());
260 array[
261 2 * size_of::<$ty>()..3 * size_of::<$ty>()
262 ].copy_from_slice(&self.2.to_be_bytes());
263 array
264 }
265 }
266 impl TryFrom<&[u8]> for [<$ty:upper Triplet>] {
267 type Error = ByteConversionError;
268
269 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
270 if v.len() < 3 * size_of::<$ty>() {
271 return Err(ByteConversionError::FromSliceTooSmall{
272 expected: 3 * size_of::<$ty>(),
273 found: v.len()
274 });
275 }
276 Ok([<$ty:upper Triplet>](
277 $ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()),
278 $ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap()),
279 $ty::from_be_bytes(v[2 * size_of::<$ty>()..3 * size_of::<$ty>()].try_into().unwrap())
280 ))
281 }
282 }
283 }
284 )+
285 }
286}
287
288scalar_byte_conversions_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,);
289
290impl ToBeBytes for U8Pair {
291 type ByteArray = [u8; 2];
292
293 fn written_len(&self) -> usize {
294 size_of::<Self::ByteArray>()
295 }
296
297 fn to_be_bytes(&self) -> Self::ByteArray {
298 let mut array = [0; 2];
299 array[0] = self.0;
300 array[1] = self.1;
301 array
302 }
303}
304
305impl ToBeBytes for I8Pair {
306 type ByteArray = [u8; 2];
307
308 fn written_len(&self) -> usize {
309 size_of::<Self::ByteArray>()
310 }
311
312 fn to_be_bytes(&self) -> Self::ByteArray {
313 let mut array = [0; 2];
314 array[0] = self.0 as u8;
315 array[1] = self.1 as u8;
316 array
317 }
318}
319
320impl ToBeBytes for U8Triplet {
321 type ByteArray = [u8; 3];
322
323 fn written_len(&self) -> usize {
324 size_of::<Self::ByteArray>()
325 }
326
327 fn to_be_bytes(&self) -> Self::ByteArray {
328 let mut array = [0; 3];
329 array[0] = self.0;
330 array[1] = self.1;
331 array[2] = self.2;
332 array
333 }
334}
335
336impl ToBeBytes for I8Triplet {
337 type ByteArray = [u8; 3];
338
339 fn written_len(&self) -> usize {
340 size_of::<Self::ByteArray>()
341 }
342
343 fn to_be_bytes(&self) -> Self::ByteArray {
344 let mut array = [0; 3];
345 array[0] = self.0 as u8;
346 array[1] = self.1 as u8;
347 array[2] = self.2 as u8;
348 array
349 }
350}
351
352pair_byte_conversions_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
353triplet_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
354
355#[derive(Debug, Copy, Clone, PartialEq)]
360pub enum ParamsRaw {
361 U8(U8),
362 U8Pair(U8Pair),
363 U8Triplet(U8Triplet),
364 I8(I8),
365 I8Pair(I8Pair),
366 I8Triplet(I8Triplet),
367 U16(U16),
368 U16Pair(U16Pair),
369 U16Triplet(U16Triplet),
370 I16(I16),
371 I16Pair(I16Pair),
372 I16Triplet(I16Triplet),
373 U32(U32),
374 U32Pair(U32Pair),
375 U32Triplet(U32Triplet),
376 I32(I32),
377 I32Pair(I32Pair),
378 I32Triplet(I32Triplet),
379 F32(F32),
380 F32Pair(F32Pair),
381 F32Triplet(F32Triplet),
382 U64(U64),
383 I64(I64),
384 F64(F64),
385}
386
387impl WritableToBeBytes for ParamsRaw {
388 fn raw_len(&self) -> usize {
389 match self {
390 ParamsRaw::U8(v) => v.raw_len(),
391 ParamsRaw::U8Pair(v) => v.raw_len(),
392 ParamsRaw::U8Triplet(v) => v.raw_len(),
393 ParamsRaw::I8(v) => v.raw_len(),
394 ParamsRaw::I8Pair(v) => v.raw_len(),
395 ParamsRaw::I8Triplet(v) => v.raw_len(),
396 ParamsRaw::U16(v) => v.raw_len(),
397 ParamsRaw::U16Pair(v) => v.raw_len(),
398 ParamsRaw::U16Triplet(v) => v.raw_len(),
399 ParamsRaw::I16(v) => v.raw_len(),
400 ParamsRaw::I16Pair(v) => v.raw_len(),
401 ParamsRaw::I16Triplet(v) => v.raw_len(),
402 ParamsRaw::U32(v) => v.raw_len(),
403 ParamsRaw::U32Pair(v) => v.raw_len(),
404 ParamsRaw::U32Triplet(v) => v.raw_len(),
405 ParamsRaw::I32(v) => v.raw_len(),
406 ParamsRaw::I32Pair(v) => v.raw_len(),
407 ParamsRaw::I32Triplet(v) => v.raw_len(),
408 ParamsRaw::F32(v) => v.raw_len(),
409 ParamsRaw::F32Pair(v) => v.raw_len(),
410 ParamsRaw::F32Triplet(v) => v.raw_len(),
411 ParamsRaw::U64(v) => v.raw_len(),
412 ParamsRaw::I64(v) => v.raw_len(),
413 ParamsRaw::F64(v) => v.raw_len(),
414 }
415 }
416
417 fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
418 match self {
419 ParamsRaw::U8(v) => v.write_to_be_bytes(buf),
420 ParamsRaw::U8Pair(v) => v.write_to_be_bytes(buf),
421 ParamsRaw::U8Triplet(v) => v.write_to_be_bytes(buf),
422 ParamsRaw::I8(v) => v.write_to_be_bytes(buf),
423 ParamsRaw::I8Pair(v) => v.write_to_be_bytes(buf),
424 ParamsRaw::I8Triplet(v) => v.write_to_be_bytes(buf),
425 ParamsRaw::U16(v) => v.write_to_be_bytes(buf),
426 ParamsRaw::U16Pair(v) => v.write_to_be_bytes(buf),
427 ParamsRaw::U16Triplet(v) => v.write_to_be_bytes(buf),
428 ParamsRaw::I16(v) => v.write_to_be_bytes(buf),
429 ParamsRaw::I16Pair(v) => v.write_to_be_bytes(buf),
430 ParamsRaw::I16Triplet(v) => v.write_to_be_bytes(buf),
431 ParamsRaw::U32(v) => v.write_to_be_bytes(buf),
432 ParamsRaw::U32Pair(v) => v.write_to_be_bytes(buf),
433 ParamsRaw::U32Triplet(v) => v.write_to_be_bytes(buf),
434 ParamsRaw::I32(v) => v.write_to_be_bytes(buf),
435 ParamsRaw::I32Pair(v) => v.write_to_be_bytes(buf),
436 ParamsRaw::I32Triplet(v) => v.write_to_be_bytes(buf),
437 ParamsRaw::F32(v) => v.write_to_be_bytes(buf),
438 ParamsRaw::F32Pair(v) => v.write_to_be_bytes(buf),
439 ParamsRaw::F32Triplet(v) => v.write_to_be_bytes(buf),
440 ParamsRaw::U64(v) => v.write_to_be_bytes(buf),
441 ParamsRaw::I64(v) => v.write_to_be_bytes(buf),
442 ParamsRaw::F64(v) => v.write_to_be_bytes(buf),
443 }
444 }
445}
446
447macro_rules! params_raw_from_newtype {
448 ($($newtype: ident,)+) => {
449 $(
450 impl From<$newtype> for ParamsRaw {
451 fn from(v: $newtype) -> Self {
452 Self::$newtype(v)
453 }
454 }
455 )+
456 }
457}
458
459params_raw_from_newtype!(
460 U8, U8Pair, U8Triplet, U16, U16Pair, U16Triplet, U32, U32Pair, U32Triplet, I8, I8Pair,
461 I8Triplet, I16, I16Pair, I16Triplet, I32, I32Pair, I32Triplet, F32, F32Pair, F32Triplet, U64,
462 I64, F64,
463);
464
465#[derive(Debug, Copy, Clone, PartialEq, Eq)]
466pub enum EcssEnumParams {
467 U8(EcssEnumU8),
468 U16(EcssEnumU16),
469 U32(EcssEnumU32),
470 U64(EcssEnumU64),
471}
472
473macro_rules! writable_as_be_bytes_ecss_enum_impl {
474 ($EnumIdent: ident) => {
475 impl WritableToBeBytes for $EnumIdent {
476 fn raw_len(&self) -> usize {
477 self.size()
478 }
479
480 fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
481 <Self as UnsignedEnum>::write_to_be_bytes(self, buf).map(|_| self.raw_len())
482 }
483 }
484 };
485}
486
487writable_as_be_bytes_ecss_enum_impl!(EcssEnumU8);
488writable_as_be_bytes_ecss_enum_impl!(EcssEnumU16);
489writable_as_be_bytes_ecss_enum_impl!(EcssEnumU32);
490writable_as_be_bytes_ecss_enum_impl!(EcssEnumU64);
491
492impl WritableToBeBytes for EcssEnumParams {
493 fn raw_len(&self) -> usize {
494 match self {
495 EcssEnumParams::U8(e) => e.raw_len(),
496 EcssEnumParams::U16(e) => e.raw_len(),
497 EcssEnumParams::U32(e) => e.raw_len(),
498 EcssEnumParams::U64(e) => e.raw_len(),
499 }
500 }
501
502 fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
503 match self {
504 EcssEnumParams::U8(e) => WritableToBeBytes::write_to_be_bytes(e, buf),
505 EcssEnumParams::U16(e) => WritableToBeBytes::write_to_be_bytes(e, buf),
506 EcssEnumParams::U32(e) => WritableToBeBytes::write_to_be_bytes(e, buf),
507 EcssEnumParams::U64(e) => WritableToBeBytes::write_to_be_bytes(e, buf),
508 }
509 }
510}
511
512#[derive(Debug, Copy, Clone, PartialEq)]
514pub enum ParamsHeapless {
515 Raw(ParamsRaw),
516 EcssEnum(EcssEnumParams),
517}
518
519macro_rules! from_conversions_for_raw {
520 ($(($raw_ty: ty, $TargetPath: path),)+) => {
521 $(
522 impl From<$raw_ty> for ParamsRaw {
523 fn from(val: $raw_ty) -> Self {
524 $TargetPath(val.into())
525 }
526 }
527
528 impl From<$raw_ty> for ParamsHeapless {
529 fn from(val: $raw_ty) -> Self {
530 ParamsHeapless::Raw(val.into())
531 }
532 }
533 )+
534 };
535}
536
537from_conversions_for_raw!(
538 (u8, Self::U8),
539 ((u8, u8), Self::U8Pair),
540 ((u8, u8, u8), Self::U8Triplet),
541 (i8, Self::I8),
542 ((i8, i8), Self::I8Pair),
543 ((i8, i8, i8), Self::I8Triplet),
544 (u16, Self::U16),
545 ((u16, u16), Self::U16Pair),
546 ((u16, u16, u16), Self::U16Triplet),
547 (i16, Self::I16),
548 ((i16, i16), Self::I16Pair),
549 ((i16, i16, i16), Self::I16Triplet),
550 (u32, Self::U32),
551 ((u32, u32), Self::U32Pair),
552 ((u32, u32, u32), Self::U32Triplet),
553 (i32, Self::I32),
554 ((i32, i32), Self::I32Pair),
555 ((i32, i32, i32), Self::I32Triplet),
556 (f32, Self::F32),
557 ((f32, f32), Self::F32Pair),
558 ((f32, f32, f32), Self::F32Triplet),
559 (u64, Self::U64),
560 (f64, Self::F64),
561);
562
563#[cfg(feature = "alloc")]
564mod alloc_mod {
565 use super::*;
566 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
569 #[derive(Debug, Clone)]
570 pub enum Params {
571 Heapless(ParamsHeapless),
572 Store(StoreAddr),
573 Vec(Vec<u8>),
574 String(String),
575 }
576
577 impl From<StoreAddr> for Params {
578 fn from(x: StoreAddr) -> Self {
579 Self::Store(x)
580 }
581 }
582
583 impl From<ParamsHeapless> for Params {
584 fn from(x: ParamsHeapless) -> Self {
585 Self::Heapless(x)
586 }
587 }
588
589 impl From<Vec<u8>> for Params {
590 fn from(val: Vec<u8>) -> Self {
591 Self::Vec(val)
592 }
593 }
594
595 impl From<&[u8]> for Params {
597 fn from(val: &[u8]) -> Self {
598 Self::Vec(val.to_vec())
599 }
600 }
601
602 impl From<String> for Params {
603 fn from(val: String) -> Self {
604 Self::String(val)
605 }
606 }
607
608 impl From<&str> for Params {
610 fn from(val: &str) -> Self {
611 Self::String(val.to_string())
612 }
613 }
614}
615
616#[cfg(test)]
617mod tests {
618 use super::*;
619
620 #[test]
621 fn test_basic_u32_pair() {
622 let u32_pair = U32Pair(4, 8);
623 assert_eq!(u32_pair.0, 4);
624 assert_eq!(u32_pair.1, 8);
625 let raw = u32_pair.to_be_bytes();
626 let mut u32_conv_back = u32::from_be_bytes(raw[0..4].try_into().unwrap());
627 assert_eq!(u32_conv_back, 4);
628 u32_conv_back = u32::from_be_bytes(raw[4..8].try_into().unwrap());
629 assert_eq!(u32_conv_back, 8);
630 }
631
632 #[test]
633 fn basic_signed_test_pair() {
634 let i8_pair = I8Pair(-3, -16);
635 assert_eq!(i8_pair.0, -3);
636 assert_eq!(i8_pair.1, -16);
637 let raw = i8_pair.to_be_bytes();
638 let mut i8_conv_back = i8::from_be_bytes(raw[0..1].try_into().unwrap());
639 assert_eq!(i8_conv_back, -3);
640 i8_conv_back = i8::from_be_bytes(raw[1..2].try_into().unwrap());
641 assert_eq!(i8_conv_back, -16);
642 }
643
644 #[test]
645 fn basic_signed_test_triplet() {
646 let i8_triplet = I8Triplet(-3, -16, -126);
647 assert_eq!(i8_triplet.0, -3);
648 assert_eq!(i8_triplet.1, -16);
649 assert_eq!(i8_triplet.2, -126);
650 let raw = i8_triplet.to_be_bytes();
651 let mut i8_conv_back = i8::from_be_bytes(raw[0..1].try_into().unwrap());
652 assert_eq!(i8_conv_back, -3);
653 i8_conv_back = i8::from_be_bytes(raw[1..2].try_into().unwrap());
654 assert_eq!(i8_conv_back, -16);
655 i8_conv_back = i8::from_be_bytes(raw[2..3].try_into().unwrap());
656 assert_eq!(i8_conv_back, -126);
657 }
658
659 #[test]
660 fn conversion_test_string() {
661 let param: Params = "Test String".into();
662 if let Params::String(str) = param {
663 assert_eq!(str, String::from("Test String"));
664 } else {
665 panic!("Params type is not String")
666 }
667 }
668
669 #[test]
670 fn conversion_from_slice() {
671 let test_slice: [u8; 5] = [0; 5];
672 let vec_param: Params = test_slice.as_slice().into();
673 if let Params::Vec(vec) = vec_param {
674 assert_eq!(vec, test_slice.to_vec());
675 } else {
676 panic!("Params type is not a vector")
677 }
678 }
679}