1use core::fmt::Debug;
31use core::hash::Hash;
32use core::marker::PhantomData;
33use delegate::delegate;
34use spacepackets::ecss::EcssEnumeration;
35use spacepackets::util::{ToBeBytes, UnsignedEnum};
36use spacepackets::ByteConversionError;
37
38pub type LargestEventRaw = u32;
40pub type LargestGroupIdRaw = u16;
42
43#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
44pub enum Severity {
45    INFO = 0,
46    LOW = 1,
47    MEDIUM = 2,
48    HIGH = 3,
49}
50
51pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone {
52    const SEVERITY: Severity;
53}
54
55#[derive(Debug, PartialEq, Eq, Copy, Clone)]
57pub struct SeverityInfo {}
58impl HasSeverity for SeverityInfo {
59    const SEVERITY: Severity = Severity::INFO;
60}
61
62#[derive(Debug, PartialEq, Eq, Copy, Clone)]
64pub struct SeverityLow {}
65impl HasSeverity for SeverityLow {
66    const SEVERITY: Severity = Severity::LOW;
67}
68
69#[derive(Debug, PartialEq, Eq, Copy, Clone)]
71pub struct SeverityMedium {}
72impl HasSeverity for SeverityMedium {
73    const SEVERITY: Severity = Severity::MEDIUM;
74}
75
76#[derive(Debug, PartialEq, Eq, Copy, Clone)]
78pub struct SeverityHigh {}
79impl HasSeverity for SeverityHigh {
80    const SEVERITY: Severity = Severity::HIGH;
81}
82
83pub trait GenericEvent: EcssEnumeration {
84    type Raw;
85    type GroupId;
86    type UniqueId;
87
88    fn raw(&self) -> Self::Raw;
89    fn severity(&self) -> Severity;
90    fn group_id(&self) -> Self::GroupId;
91    fn unique_id(&self) -> Self::UniqueId;
92
93    fn raw_as_largest_type(&self) -> LargestEventRaw;
94    fn group_id_as_largest_type(&self) -> LargestGroupIdRaw;
95}
96
97impl TryFrom<u8> for Severity {
98    type Error = ();
99
100    fn try_from(value: u8) -> Result<Self, Self::Error> {
101        match value {
102            x if x == Severity::INFO as u8 => Ok(Severity::INFO),
103            x if x == Severity::LOW as u8 => Ok(Severity::LOW),
104            x if x == Severity::MEDIUM as u8 => Ok(Severity::MEDIUM),
105            x if x == Severity::HIGH as u8 => Ok(Severity::HIGH),
106            _ => Err(()),
107        }
108    }
109}
110
111#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
112struct EventBase<RAW, GID, UID> {
113    severity: Severity,
114    group_id: GID,
115    unique_id: UID,
116    phantom: PhantomData<RAW>,
117}
118
119impl<RAW: ToBeBytes, GID, UID> EventBase<RAW, GID, UID> {
120    fn write_to_bytes(
121        &self,
122        raw: RAW,
123        buf: &mut [u8],
124        width: usize,
125    ) -> Result<usize, ByteConversionError> {
126        if buf.len() < width {
127            return Err(ByteConversionError::ToSliceTooSmall {
128                found: buf.len(),
129                expected: width,
130            });
131        }
132        buf.copy_from_slice(raw.to_be_bytes().as_ref());
133        Ok(raw.written_len())
134    }
135}
136
137impl EventBase<u32, u16, u16> {
138    #[inline]
139    fn raw(&self) -> u32 {
140        ((self.severity as u32) << 30) | ((self.group_id as u32) << 16) | self.unique_id as u32
141    }
142}
143
144impl EventBase<u16, u8, u8> {
145    #[inline]
146    fn raw(&self) -> u16 {
147        ((self.severity as u16) << 14) | ((self.group_id as u16) << 8) | self.unique_id as u16
148    }
149}
150
151impl<RAW, GID, UID> EventBase<RAW, GID, UID> {
152    #[inline]
153    pub fn severity(&self) -> Severity {
154        self.severity
155    }
156}
157
158impl<RAW, GID> EventBase<RAW, GID, u16> {
159    #[inline]
160    pub fn unique_id(&self) -> u16 {
161        self.unique_id
162    }
163}
164
165impl<RAW, GID> EventBase<RAW, GID, u8> {
166    #[inline]
167    pub fn unique_id(&self) -> u8 {
168        self.unique_id
169    }
170}
171
172impl<RAW, UID> EventBase<RAW, u16, UID> {
173    #[inline]
174    pub fn group_id(&self) -> u16 {
175        self.group_id
176    }
177}
178
179impl<RAW, UID> EventBase<RAW, u8, UID> {
180    #[inline]
181    pub fn group_id(&self) -> u8 {
182        self.group_id
183    }
184}
185
186macro_rules! event_provider_impl {
187    () => {
188        #[inline]
189        fn raw(&self) -> Self::Raw {
190            self.base.raw()
191        }
192
193        #[inline]
196        fn severity(&self) -> Severity {
197            self.base.severity()
198        }
199
200        #[inline]
201        fn group_id(&self) -> Self::GroupId {
202            self.base.group_id()
203        }
204
205        #[inline]
206        fn unique_id(&self) -> Self::UniqueId {
207            self.base.unique_id()
208        }
209    };
210}
211
212macro_rules! impl_event_provider {
213    ($BaseIdent: ident, $TypedIdent: ident, $raw: ty, $gid: ty, $uid: ty) => {
214        impl GenericEvent for $BaseIdent {
215            type Raw = $raw;
216            type GroupId = $gid;
217            type UniqueId = $uid;
218
219            event_provider_impl!();
220
221            fn raw_as_largest_type(&self) -> LargestEventRaw {
222                self.raw().into()
223            }
224
225            fn group_id_as_largest_type(&self) -> LargestGroupIdRaw {
226                self.group_id().into()
227            }
228        }
229
230        impl<SEVERITY: HasSeverity> GenericEvent for $TypedIdent<SEVERITY> {
231            type Raw = $raw;
232            type GroupId = $gid;
233            type UniqueId = $uid;
234
235            delegate!(to self.event {
236                fn raw(&self) -> Self::Raw;
237                fn severity(&self) -> Severity;
238                fn group_id(&self) -> Self::GroupId;
239                fn unique_id(&self) -> Self::UniqueId;
240                fn raw_as_largest_type(&self) -> LargestEventRaw;
241                fn group_id_as_largest_type(&self) -> LargestGroupIdRaw;
242            });
243        }
244    }
245}
246
247macro_rules! try_from_impls {
248    ($SevIdent: ident, $severity: path, $raw: ty, $TypedSevIdent: ident) => {
249        impl TryFrom<$raw> for $TypedSevIdent<$SevIdent> {
250            type Error = Severity;
251
252            fn try_from(raw: $raw) -> Result<Self, Self::Error> {
253                Self::try_from_generic($severity, raw)
254            }
255        }
256    };
257}
258
259macro_rules! const_from_fn {
260    ($from_fn_name: ident, $TypedIdent: ident, $SevIdent: ident) => {
261        pub const fn $from_fn_name(event: $TypedIdent<$SevIdent>) -> Self {
262            Self {
263                base: event.event.base,
264            }
265        }
266    };
267}
268
269#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
270pub struct EventU32 {
271    base: EventBase<u32, u16, u16>,
272}
273
274#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
275pub struct EventU32TypedSev<SEVERITY> {
276    event: EventU32,
277    phantom: PhantomData<SEVERITY>,
278}
279
280impl<SEVERITY: HasSeverity> From<EventU32TypedSev<SEVERITY>> for EventU32 {
281    fn from(e: EventU32TypedSev<SEVERITY>) -> Self {
282        Self { base: e.event.base }
283    }
284}
285
286impl<Severity: HasSeverity> AsRef<EventU32> for EventU32TypedSev<Severity> {
287    fn as_ref(&self) -> &EventU32 {
288        &self.event
289    }
290}
291
292impl<Severity: HasSeverity> AsMut<EventU32> for EventU32TypedSev<Severity> {
293    fn as_mut(&mut self) -> &mut EventU32 {
294        &mut self.event
295    }
296}
297
298impl_event_provider!(EventU32, EventU32TypedSev, u32, u16, u16);
299
300impl EventU32 {
301    pub fn new(
313        severity: Severity,
314        group_id: <Self as GenericEvent>::GroupId,
315        unique_id: <Self as GenericEvent>::UniqueId,
316    ) -> Option<Self> {
317        if group_id > (2u16.pow(14) - 1) {
318            return None;
319        }
320        Some(Self {
321            base: EventBase {
322                severity,
323                group_id,
324                unique_id,
325                phantom: PhantomData,
326            },
327        })
328    }
329    pub const fn const_new(
330        severity: Severity,
331        group_id: <Self as GenericEvent>::GroupId,
332        unique_id: <Self as GenericEvent>::UniqueId,
333    ) -> Self {
334        if group_id > (2u16.pow(14) - 1) {
335            panic!("Group ID too large");
336        }
337        Self {
338            base: EventBase {
339                severity,
340                group_id,
341                unique_id,
342                phantom: PhantomData,
343            },
344        }
345    }
346
347    const_from_fn!(const_from_info, EventU32TypedSev, SeverityInfo);
348    const_from_fn!(const_from_low, EventU32TypedSev, SeverityLow);
349    const_from_fn!(const_from_medium, EventU32TypedSev, SeverityMedium);
350    const_from_fn!(const_from_high, EventU32TypedSev, SeverityHigh);
351}
352
353impl<SEVERITY: HasSeverity> EventU32TypedSev<SEVERITY> {
354    pub fn new(
357        group_id: <Self as GenericEvent>::GroupId,
358        unique_id: <Self as GenericEvent>::UniqueId,
359    ) -> Option<Self> {
360        let event = EventU32::new(SEVERITY::SEVERITY, group_id, unique_id)?;
361        Some(Self {
362            event,
363            phantom: PhantomData,
364        })
365    }
366
367    pub const fn const_new(
369        group_id: <Self as GenericEvent>::GroupId,
370        unique_id: <Self as GenericEvent>::UniqueId,
371    ) -> Self {
372        let event = EventU32::const_new(SEVERITY::SEVERITY, group_id, unique_id);
373        Self {
374            event,
375            phantom: PhantomData,
376        }
377    }
378
379    fn try_from_generic(expected: Severity, raw: u32) -> Result<Self, Severity> {
380        let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
381        if severity != expected {
382            return Err(severity);
383        }
384        Ok(Self::const_new(
385            ((raw >> 16) & 0x3FFF) as u16,
386            (raw & 0xFFFF) as u16,
387        ))
388    }
389}
390
391impl From<u32> for EventU32 {
392    fn from(raw: u32) -> Self {
393        let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
395        let group_id = ((raw >> 16) & 0x3FFF) as u16;
396        let unique_id = (raw & 0xFFFF) as u16;
397        Self::const_new(severity, group_id, unique_id)
399    }
400}
401
402try_from_impls!(SeverityInfo, Severity::INFO, u32, EventU32TypedSev);
403try_from_impls!(SeverityLow, Severity::LOW, u32, EventU32TypedSev);
404try_from_impls!(SeverityMedium, Severity::MEDIUM, u32, EventU32TypedSev);
405try_from_impls!(SeverityHigh, Severity::HIGH, u32, EventU32TypedSev);
406
407impl UnsignedEnum for EventU32 {
408    fn size(&self) -> usize {
409        core::mem::size_of::<u32>()
410    }
411
412    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
413        self.base.write_to_bytes(self.raw(), buf, self.size())
414    }
415}
416
417impl EcssEnumeration for EventU32 {
418    fn pfc(&self) -> u8 {
419        u32::BITS as u8
420    }
421}
422
423impl<SEVERITY: HasSeverity> UnsignedEnum for EventU32TypedSev<SEVERITY> {
425    delegate!(to self.event {
426        fn size(&self) -> usize;
427        fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
428    });
429}
430
431impl<SEVERITY: HasSeverity> EcssEnumeration for EventU32TypedSev<SEVERITY> {
433    delegate!(to self.event {
434        fn pfc(&self) -> u8;
435    });
436}
437
438#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
439pub struct EventU16 {
440    base: EventBase<u16, u8, u8>,
441}
442
443#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
444pub struct EventU16TypedSev<SEVERITY> {
445    event: EventU16,
446    phantom: PhantomData<SEVERITY>,
447}
448
449impl<Severity: HasSeverity> AsRef<EventU16> for EventU16TypedSev<Severity> {
450    fn as_ref(&self) -> &EventU16 {
451        &self.event
452    }
453}
454
455impl<Severity: HasSeverity> AsMut<EventU16> for EventU16TypedSev<Severity> {
456    fn as_mut(&mut self) -> &mut EventU16 {
457        &mut self.event
458    }
459}
460
461impl EventU16 {
462    pub fn new(
474        severity: Severity,
475        group_id: <Self as GenericEvent>::GroupId,
476        unique_id: <Self as GenericEvent>::UniqueId,
477    ) -> Option<Self> {
478        if group_id > (2u8.pow(6) - 1) {
479            return None;
480        }
481        Some(Self {
482            base: EventBase {
483                severity,
484                group_id,
485                unique_id,
486                phantom: Default::default(),
487            },
488        })
489    }
490
491    pub const fn const_new(
493        severity: Severity,
494        group_id: <Self as GenericEvent>::GroupId,
495        unique_id: <Self as GenericEvent>::UniqueId,
496    ) -> Self {
497        if group_id > (2u8.pow(6) - 1) {
498            panic!("Group ID too large");
499        }
500        Self {
501            base: EventBase {
502                severity,
503                group_id,
504                unique_id,
505                phantom: PhantomData,
506            },
507        }
508    }
509    const_from_fn!(const_from_info, EventU16TypedSev, SeverityInfo);
510    const_from_fn!(const_from_low, EventU16TypedSev, SeverityLow);
511    const_from_fn!(const_from_medium, EventU16TypedSev, SeverityMedium);
512    const_from_fn!(const_from_high, EventU16TypedSev, SeverityHigh);
513}
514
515impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
516    pub fn new(
519        group_id: <Self as GenericEvent>::GroupId,
520        unique_id: <Self as GenericEvent>::UniqueId,
521    ) -> Option<Self> {
522        let event = EventU16::new(SEVERITY::SEVERITY, group_id, unique_id)?;
523        Some(Self {
524            event,
525            phantom: PhantomData,
526        })
527    }
528
529    pub const fn const_new(
531        group_id: <Self as GenericEvent>::GroupId,
532        unique_id: <Self as GenericEvent>::UniqueId,
533    ) -> Self {
534        let event = EventU16::const_new(SEVERITY::SEVERITY, group_id, unique_id);
535        Self {
536            event,
537            phantom: PhantomData,
538        }
539    }
540
541    fn try_from_generic(expected: Severity, raw: u16) -> Result<Self, Severity> {
542        let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
543        if severity != expected {
544            return Err(severity);
545        }
546        Ok(Self::const_new(
547            ((raw >> 8) & 0x3F) as u8,
548            (raw & 0xFF) as u8,
549        ))
550    }
551}
552
553impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
554
555impl UnsignedEnum for EventU16 {
556    fn size(&self) -> usize {
557        core::mem::size_of::<u16>()
558    }
559
560    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
561        self.base.write_to_bytes(self.raw(), buf, self.size())
562    }
563}
564impl EcssEnumeration for EventU16 {
565    #[inline]
566    fn pfc(&self) -> u8 {
567        u16::BITS as u8
568    }
569}
570
571impl<SEVERITY: HasSeverity> UnsignedEnum for EventU16TypedSev<SEVERITY> {
573    delegate!(to self.event {
574        fn size(&self) -> usize;
575        fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
576    });
577}
578
579impl<SEVERITY: HasSeverity> EcssEnumeration for EventU16TypedSev<SEVERITY> {
581    delegate!(to self.event {
582        fn pfc(&self) -> u8;
583    });
584}
585
586impl From<u16> for EventU16 {
587    fn from(raw: <Self as GenericEvent>::Raw) -> Self {
588        let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
589        let group_id = ((raw >> 8) & 0x3F) as u8;
590        let unique_id = (raw & 0xFF) as u8;
591        Self::const_new(severity, group_id, unique_id)
593    }
594}
595
596try_from_impls!(SeverityInfo, Severity::INFO, u16, EventU16TypedSev);
597try_from_impls!(SeverityLow, Severity::LOW, u16, EventU16TypedSev);
598try_from_impls!(SeverityMedium, Severity::MEDIUM, u16, EventU16TypedSev);
599try_from_impls!(SeverityHigh, Severity::HIGH, u16, EventU16TypedSev);
600
601impl<Severity: HasSeverity> PartialEq<EventU32> for EventU32TypedSev<Severity> {
602    #[inline]
603    fn eq(&self, other: &EventU32) -> bool {
604        self.raw() == other.raw()
605    }
606}
607
608impl<Severity: HasSeverity> PartialEq<EventU32TypedSev<Severity>> for EventU32 {
609    #[inline]
610    fn eq(&self, other: &EventU32TypedSev<Severity>) -> bool {
611        self.raw() == other.raw()
612    }
613}
614
615impl<Severity: HasSeverity> PartialEq<EventU16> for EventU16TypedSev<Severity> {
616    #[inline]
617    fn eq(&self, other: &EventU16) -> bool {
618        self.raw() == other.raw()
619    }
620}
621
622impl<Severity: HasSeverity> PartialEq<EventU16TypedSev<Severity>> for EventU16 {
623    #[inline]
624    fn eq(&self, other: &EventU16TypedSev<Severity>) -> bool {
625        self.raw() == other.raw()
626    }
627}
628
629#[cfg(test)]
630mod tests {
631    use super::EventU32TypedSev;
632    use super::*;
633    use spacepackets::ByteConversionError;
634    use std::mem::size_of;
635
636    fn assert_size<T>(_: T, val: usize) {
637        assert_eq!(size_of::<T>(), val);
638    }
639
640    const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0);
641    const INFO_EVENT_SMALL: EventU16TypedSev<SeverityInfo> = EventU16TypedSev::const_new(0, 0);
642    const HIGH_SEV_EVENT: EventU32TypedSev<SeverityHigh> =
643        EventU32TypedSev::const_new(0x3FFF, 0xFFFF);
644    const HIGH_SEV_EVENT_SMALL: EventU16TypedSev<SeverityHigh> =
645        EventU16TypedSev::const_new(0x3F, 0xff);
646
647    const INFO_REDUCED: EventU32 = EventU32::const_from_info(INFO_EVENT);
649
650    #[test]
651    fn test_normal_from_raw_conversion() {
652        let conv_from_raw = EventU32TypedSev::<SeverityInfo>::try_from(INFO_EVENT.raw())
653            .expect("Creating typed EventU32 failed");
654        assert_eq!(conv_from_raw, INFO_EVENT);
655    }
656
657    #[test]
658    fn test_small_from_raw_conversion() {
659        let conv_from_raw = EventU16TypedSev::<SeverityInfo>::try_from(INFO_EVENT_SMALL.raw())
660            .expect("Creating typed EventU16 failed");
661        assert_eq!(conv_from_raw, INFO_EVENT_SMALL);
662    }
663
664    #[test]
665    fn verify_normal_size() {
666        assert_size(INFO_EVENT.raw(), 4)
667    }
668
669    #[test]
670    fn verify_small_size() {
671        assert_size(INFO_EVENT_SMALL.raw(), 2)
672    }
673
674    #[test]
675    fn test_normal_event_getters() {
676        assert_eq!(INFO_EVENT.severity(), Severity::INFO);
677        assert_eq!(INFO_EVENT.unique_id(), 0);
678        assert_eq!(INFO_EVENT.group_id(), 0);
679        let raw_event = INFO_EVENT.raw();
680        assert_eq!(raw_event, 0x00000000);
681    }
682
683    #[test]
684    fn test_small_event_getters() {
685        assert_eq!(INFO_EVENT_SMALL.severity(), Severity::INFO);
686        assert_eq!(INFO_EVENT_SMALL.unique_id(), 0);
687        assert_eq!(INFO_EVENT_SMALL.group_id(), 0);
688        let raw_event = INFO_EVENT_SMALL.raw();
689        assert_eq!(raw_event, 0x00000000);
690    }
691
692    #[test]
693    fn all_ones_event_regular() {
694        assert_eq!(HIGH_SEV_EVENT.severity(), Severity::HIGH);
695        assert_eq!(HIGH_SEV_EVENT.group_id(), 0x3FFF);
696        assert_eq!(HIGH_SEV_EVENT.unique_id(), 0xFFFF);
697        let raw_event = HIGH_SEV_EVENT.raw();
698        assert_eq!(raw_event, 0xFFFFFFFF);
699    }
700
701    #[test]
702    fn all_ones_event_small() {
703        assert_eq!(HIGH_SEV_EVENT_SMALL.severity(), Severity::HIGH);
704        assert_eq!(HIGH_SEV_EVENT_SMALL.group_id(), 0x3F);
705        assert_eq!(HIGH_SEV_EVENT_SMALL.unique_id(), 0xFF);
706        let raw_event = HIGH_SEV_EVENT_SMALL.raw();
707        assert_eq!(raw_event, 0xFFFF);
708    }
709
710    #[test]
711    fn invalid_group_id_normal() {
712        assert!(EventU32TypedSev::<SeverityMedium>::new(2_u16.pow(14), 0).is_none());
713    }
714
715    #[test]
716    fn invalid_group_id_small() {
717        assert!(EventU16TypedSev::<SeverityMedium>::new(2_u8.pow(6), 0).is_none());
718    }
719
720    #[test]
721    fn regular_new() {
722        assert_eq!(
723            EventU32TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"),
724            INFO_EVENT
725        );
726    }
727
728    #[test]
729    fn small_new() {
730        assert_eq!(
731            EventU16TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"),
732            INFO_EVENT_SMALL
733        );
734    }
735
736    #[test]
737    fn as_largest_type() {
738        let event_raw = HIGH_SEV_EVENT.raw_as_largest_type();
739        assert_size(event_raw, 4);
740        assert_eq!(event_raw, 0xFFFFFFFF);
741    }
742
743    #[test]
744    fn as_largest_type_for_small_event() {
745        let event_raw = HIGH_SEV_EVENT_SMALL.raw_as_largest_type();
746        assert_size(event_raw, 4);
747        assert_eq!(event_raw, 0xFFFF);
748    }
749
750    #[test]
751    fn as_largest_group_id() {
752        let group_id = HIGH_SEV_EVENT.group_id_as_largest_type();
753        assert_size(group_id, 2);
754        assert_eq!(group_id, 0x3FFF);
755    }
756
757    #[test]
758    fn as_largest_group_id_small_event() {
759        let group_id = HIGH_SEV_EVENT_SMALL.group_id_as_largest_type();
760        assert_size(group_id, 2);
761        assert_eq!(group_id, 0x3F);
762    }
763
764    #[test]
765    fn write_to_buf() {
766        let mut buf: [u8; 4] = [0; 4];
767        assert!(HIGH_SEV_EVENT.write_to_be_bytes(&mut buf).is_ok());
768        let val_from_raw = u32::from_be_bytes(buf);
769        assert_eq!(val_from_raw, 0xFFFFFFFF);
770    }
771
772    #[test]
773    fn write_to_buf_small() {
774        let mut buf: [u8; 2] = [0; 2];
775        assert!(HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf).is_ok());
776        let val_from_raw = u16::from_be_bytes(buf);
777        assert_eq!(val_from_raw, 0xFFFF);
778    }
779
780    #[test]
781    fn write_to_buf_insufficient_buf() {
782        let mut buf: [u8; 3] = [0; 3];
783        let err = HIGH_SEV_EVENT.write_to_be_bytes(&mut buf);
784        assert!(err.is_err());
785        let err = err.unwrap_err();
786        if let ByteConversionError::ToSliceTooSmall { found, expected } = err {
787            assert_eq!(expected, 4);
788            assert_eq!(found, 3);
789        }
790    }
791
792    #[test]
793    fn write_to_buf_small_insufficient_buf() {
794        let mut buf: [u8; 1] = [0; 1];
795        let err = HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf);
796        assert!(err.is_err());
797        let err = err.unwrap_err();
798        if let ByteConversionError::ToSliceTooSmall { found, expected } = err {
799            assert_eq!(expected, 2);
800            assert_eq!(found, 1);
801        }
802    }
803
804    #[test]
805    fn severity_from_invalid_raw_val() {
806        let invalid = 0xFF;
807        assert!(Severity::try_from(invalid).is_err());
808        let invalid = Severity::HIGH as u8 + 1;
809        assert!(Severity::try_from(invalid).is_err());
810    }
811
812    #[test]
813    fn reduction() {
814        let event = EventU32TypedSev::<SeverityInfo>::const_new(1, 1);
815        let raw = event.raw();
816        let reduced: EventU32 = event.into();
817        assert_eq!(reduced.group_id(), 1);
818        assert_eq!(reduced.unique_id(), 1);
819        assert_eq!(raw, reduced.raw());
820    }
821
822    #[test]
823    fn const_reducation() {
824        assert_eq!(INFO_REDUCED.raw(), INFO_EVENT.raw());
825    }
826}