1use core::fmt::Debug;
19
20use embassy_time::Instant;
21
22use crate::acl::Accessor;
23use crate::dm::{ClusterId, EndptId, EventId, Node};
24use crate::error::{Error, ErrorCode};
25use crate::im::{
26 EventData, EventDataTag, EventDataTimestamp, EventFilter, EventNumber, EventPath,
27 EventPriority, EventResp, EventRespTag,
28};
29use crate::persist::{KvBlobStore, KvBlobStoreAccess, Persist, EVENT_EPOCH_KEY};
30use crate::tlv::{
31 FromTLV, TLVArray, TLVBuilderParent, TLVElement, TLVSequence, TLVSequenceIter, TLVTag,
32 TLVWrite, TagType, ToTLV,
33};
34use crate::utils::cell::RefCell;
35use crate::utils::init::{init, Init};
36use crate::utils::storage::WriteBuf;
37use crate::utils::sync::blocking::Mutex;
38
39pub const DEFAULT_MAX_EVENTS_BUF_SIZE: usize = 256;
42
43pub const NO_EVENTS_BUF_SIZE: usize = 0;
45
46pub type NoEvents = Events<NO_EVENTS_BUF_SIZE>;
48
49const EVENT_NUMBER_EPOCH_SIZE: EventNumber = 10000;
51
52pub struct Events<const N: usize = DEFAULT_MAX_EVENTS_BUF_SIZE> {
64 inner: Mutex<RefCell<EventsInner<N>>>,
65}
66
67impl<const N: usize> Events<N> {
68 #[inline(always)]
69 pub const fn new() -> Self {
70 Self {
71 inner: Mutex::new(RefCell::new(EventsInner::new())),
72 }
73 }
74
75 pub fn init() -> impl Init<Self> {
76 init!(Self {
77 inner <- Mutex::init(RefCell::init(EventsInner::init())),
78 })
79 }
80
81 pub fn reset(&mut self) {
82 self.inner.get_mut().borrow_mut().reset();
83 }
84
85 pub(crate) fn inner_mut(&mut self) -> &mut EventsInner<N> {
91 self.inner.get_mut().get_mut()
92 }
93
94 pub(crate) fn fetch<F, R>(&self, f: F) -> R
95 where
96 F: FnOnce(EventsIter<'_, N>) -> R,
97 {
98 self.inner.lock(|state| {
99 let state = state.borrow();
100
101 f(state.iter())
102 })
103 }
104
105 pub(crate) fn watermark(&self) -> EventNumber {
106 self.inner
107 .lock(|state| state.borrow().next_event_number.wrapping_sub(1))
108 }
109
110 pub fn push<S, F>(
125 &self,
126 endpoint_id: EndptId,
127 cluster_id: ClusterId,
128 event_id: EventId,
129 priority: EventPriority,
130 kv: S,
131 f: F,
132 ) -> Result<EventNumber, Error>
133 where
134 S: KvBlobStoreAccess,
135 F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
136 {
137 let mut persist = Persist::new(kv);
138
139 let event_number = self.inner.lock(|state| {
140 let mut state = state.borrow_mut();
141
142 let event_number = state.next_event_number(&mut persist)?;
143
144 let timestamp = EventDataTimestamp::SystemTimestamp(Instant::now().as_millis());
150
151 state.push(
152 endpoint_id,
153 cluster_id,
154 event_id,
155 event_number,
156 priority,
157 timestamp,
158 f,
159 )?;
160
161 Ok::<_, Error>(event_number)
162 })?;
163
164 persist.run()?;
165
166 Ok(event_number)
167 }
168}
169
170impl<const N: usize> Default for Events<N> {
171 fn default() -> Self {
172 Self::new()
173 }
174}
175
176#[derive(Debug)]
193#[cfg_attr(feature = "defmt", derive(defmt::Format))]
194pub(crate) struct EventsInner<const N: usize> {
195 buf_debug: EventsBuf<N>,
197 buf_info: EventsBuf<N>,
198 buf_critical: EventsBuf<N>,
199 next_event_number: EventNumber,
202}
203
204impl<const N: usize> EventsInner<N> {
205 const fn new() -> Self {
206 Self {
207 buf_debug: EventsBuf::new(),
208 buf_info: EventsBuf::new(),
209 buf_critical: EventsBuf::new(),
210 next_event_number: 1,
211 }
212 }
213
214 fn init() -> impl Init<Self> {
215 init!(Self {
216 buf_debug <- EventsBuf::init(),
217 buf_info <- EventsBuf::init(),
218 buf_critical <- EventsBuf::init(),
219 next_event_number: 1,
220 })
221 }
222
223 fn reset(&mut self) {
224 self.buf_debug.reset();
225 self.buf_info.reset();
226 self.buf_critical.reset();
227 self.next_event_number = 1;
228 }
229
230 pub(crate) fn reset_persist(
232 &mut self,
233 kv: &mut dyn KvBlobStore,
234 buf: &mut [u8],
235 ) -> Result<(), Error> {
236 self.reset();
237
238 kv.remove(EVENT_EPOCH_KEY, buf)?;
239
240 info!("Removed events counter from storage");
241
242 Ok(())
243 }
244
245 pub(crate) fn load_persist(
247 &mut self,
248 kv: &mut dyn KvBlobStore,
249 buf: &mut [u8],
250 ) -> Result<(), Error> {
251 self.reset();
252
253 if let Some(data) = kv.load(EVENT_EPOCH_KEY, buf)? {
254 self.load(data)?;
255
256 info!("Loaded events counter from storage");
257 }
258
259 Ok(())
260 }
261
262 fn load(&mut self, data: &[u8]) -> Result<(), Error> {
264 self.next_event_number = TLVElement::new(data).u64()?;
265
266 Ok(())
267 }
268
269 #[allow(clippy::too_many_arguments)]
270 fn push<F>(
271 &mut self,
272 endpoint_id: EndptId,
273 cluster_id: ClusterId,
274 event_id: EventId,
275 event_number: EventNumber,
276 priority: EventPriority,
277 timestamp: EventDataTimestamp,
278 f: F,
279 ) -> Result<(), Error>
280 where
281 F: FnOnce(EventTLVWrite<'_>) -> Result<(), Error>,
282 {
283 let mut event_writer = EventWriter::new(self);
284
285 let pos = event_writer.get_tail();
286
287 let result = (|| {
288 EventData {
289 path: EventPath {
290 endpoint: Some(endpoint_id),
291 cluster: Some(cluster_id),
292 event: Some(event_id),
293 ..Default::default()
294 },
295 event_number,
296 priority,
297 timestamp,
298 data: TLVElement::new(&[]),
299 }
300 .write_preamble(&EVENT_TAG, event_writer.tw())?;
301
302 f(event_writer.tw())?;
303
304 event_writer.tw().end_container()
305 })();
306
307 if result.is_err() {
308 event_writer.rewind_to(pos);
309 }
310
311 result
312 }
313
314 fn next_event_number<S>(&mut self, persist: &mut Persist<S>) -> Result<EventNumber, Error>
315 where
316 S: KvBlobStoreAccess,
317 {
318 let event_number = self.next_event_number;
319
320 if event_number == 1 || event_number.is_multiple_of(EVENT_NUMBER_EPOCH_SIZE) {
321 persist.store_tlv(
324 EVENT_EPOCH_KEY,
325 if event_number == 1 {
326 EVENT_NUMBER_EPOCH_SIZE
327 } else {
328 event_number.wrapping_add(EVENT_NUMBER_EPOCH_SIZE).max(1)
329 },
330 )?;
331 }
332
333 self.next_event_number = event_number.wrapping_add(1).max(1);
334
335 Ok(event_number)
336 }
337
338 fn iter(&self) -> EventsIter<'_, N> {
339 EventsIter {
340 events: self,
341 buf_ref: EventPriority::Critical,
342 buf_iter: self.buf_critical.iter(),
343 }
344 }
345
346 fn buf(&self, priority: EventPriority) -> &EventsBuf<N> {
348 match priority {
349 EventPriority::Debug => &self.buf_debug,
350 EventPriority::Info => &self.buf_info,
351 EventPriority::Critical => &self.buf_critical,
352 }
353 }
354
355 fn buf_mut(&mut self, priority: EventPriority) -> &mut EventsBuf<N> {
357 match priority {
358 EventPriority::Debug => &mut self.buf_debug,
359 EventPriority::Info => &mut self.buf_info,
360 EventPriority::Critical => &mut self.buf_critical,
361 }
362 }
363
364 fn buf_and_next_mut(
366 &mut self,
367 priority: EventPriority,
368 ) -> (&EventsBuf<N>, Option<&mut EventsBuf<N>>) {
369 match priority {
370 EventPriority::Debug => (&self.buf_debug, Some(&mut self.buf_info)),
371 EventPriority::Info => (&self.buf_info, Some(&mut self.buf_critical)),
372 EventPriority::Critical => (&self.buf_critical, None),
373 }
374 }
375}
376
377pub struct EventsIter<'a, const N: usize> {
379 events: &'a EventsInner<N>,
380 buf_ref: EventPriority,
381 buf_iter: TLVSequenceIter<'a>,
382}
383
384impl<'a, const N: usize> Iterator for EventsIter<'a, N> {
385 type Item = EventData<'a>;
386
387 fn next(&mut self) -> Option<Self::Item> {
388 if let Some(res) = self.buf_iter.next() {
389 let event = unwrap!(
390 res,
391 "Should not have iter errors as we only put well-formed TLVs in the buffer"
392 );
393 let event = unwrap!(
394 EventData::from_tlv(&event),
395 "Should not have parsing errors as we only put well-formed TLVs in the buffer"
396 );
397
398 return Some(event);
399 }
400
401 if let Some(next_buf_ref) = self.buf_ref.prev() {
402 self.buf_iter = self.events.buf(next_buf_ref).iter();
403 self.buf_ref = next_buf_ref;
404
405 self.next()
406 } else {
407 None
408 }
409 }
410}
411
412struct EventWriter<'a, const N: usize> {
414 events: &'a mut EventsInner<N>,
415 bytes_written: usize,
416}
417
418impl<'a, const N: usize> EventWriter<'a, N> {
419 const OPER_BUF: EventPriority = EventPriority::Debug;
422
423 #[inline(always)]
425 const fn new(events: &'a mut EventsInner<N>) -> Self {
426 Self {
427 events,
428 bytes_written: 0,
429 }
430 }
431
432 #[inline(always)]
435 fn tw(&mut self) -> EventTLVWrite<'_> {
436 EventTLVWrite(self)
437 }
438
439 fn write(&mut self, byte: u8) -> Result<(), Error> {
441 if N == 0 {
442 return Ok(());
444 }
445
446 if self.bytes_written == N {
447 return Err(Error::new(ErrorCode::ResourceExhausted));
449 }
450
451 while self.events.buf_mut(Self::OPER_BUF).append(byte).is_err() {
452 self.evict(Self::OPER_BUF);
456 }
457
458 self.bytes_written += 1;
459
460 Ok(())
461 }
462
463 fn rewind_to(&mut self, bytes_written: usize) {
465 assert!(self.bytes_written >= bytes_written);
466
467 self.events
468 .buf_mut(Self::OPER_BUF)
469 .rewind_by(self.bytes_written - bytes_written);
470 self.bytes_written = bytes_written;
471 }
472
473 fn evict(&mut self, buf_ref: EventPriority) {
476 let event_len = self.events.buf(buf_ref).first_event_len();
477
478 if let Some(next_buf_ref) = buf_ref.next() {
479 let event_prio = self.events.buf(buf_ref).first_event_prio();
480
481 if next_buf_ref as u8 <= event_prio {
482 self.promote(buf_ref, next_buf_ref, event_len);
484 }
485 }
486
487 self.events.buf_mut(buf_ref).evict_first_event();
489 }
490
491 fn promote(&mut self, src_buf: EventPriority, dst_buf: EventPriority, event_len: usize) {
495 while self.events.buf(dst_buf).capacity() < event_len {
497 self.evict(dst_buf);
498 }
499
500 let (src, dst) = self.events.buf_and_next_mut(src_buf);
501
502 let dst = unwrap!(
503 dst,
504 "Dst buffer should always exist as this is checked in evict()"
505 );
506
507 unwrap!(
508 dst.append_slice(src.slice(event_len)),
509 "Should not overflow as eviction should have cleared space"
510 );
511 }
512}
513
514trait DynEventWriter {
517 fn write(&mut self, byte: u8) -> Result<(), Error>;
518
519 fn get_tail(&self) -> usize;
520
521 fn rewind_to(&mut self, pos: usize);
522}
523
524impl<'a, const N: usize> DynEventWriter for EventWriter<'a, N> {
525 fn write(&mut self, byte: u8) -> Result<(), Error> {
526 EventWriter::write(self, byte)
527 }
528
529 fn get_tail(&self) -> usize {
530 self.bytes_written
531 }
532
533 fn rewind_to(&mut self, pos: usize) {
534 EventWriter::rewind_to(self, pos)
535 }
536}
537
538pub struct EventTLVWrite<'a>(&'a mut dyn DynEventWriter);
541
542impl core::fmt::Debug for EventTLVWrite<'_> {
543 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
544 f.debug_tuple("EventTLVWrite").finish()
545 }
546}
547
548#[cfg(feature = "defmt")]
549impl defmt::Format for EventTLVWrite<'_> {
550 fn format(&self, fmt: defmt::Formatter) {
551 defmt::write!(fmt, "EventTLVWrite")
552 }
553}
554
555impl TLVWrite for EventTLVWrite<'_> {
556 type Position = usize;
557
558 fn write(&mut self, byte: u8) -> Result<(), Error> {
559 self.0.write(byte)
560 }
561
562 fn get_tail(&self) -> Self::Position {
563 self.0.get_tail()
564 }
565
566 fn rewind_to(&mut self, pos: Self::Position) {
567 self.0.rewind_to(pos)
568 }
569}
570
571impl TLVBuilderParent for EventTLVWrite<'_> {
572 type Write = Self;
573
574 fn writer(&mut self) -> &mut Self::Write {
575 self
576 }
577}
578
579const EVENT_TAG: TLVTag = TLVTag::Context(EventRespTag::Data as _);
580
581pub const EVENT_DATA_TAG: TLVTag = TLVTag::Context(EventDataTag::Data as _);
583
584#[derive(Debug, Clone)]
597#[cfg_attr(feature = "defmt", derive(defmt::Format))]
598struct EventsBuf<const N: usize> {
599 data: [u8; N],
600 head: usize,
601}
602
603impl<const N: usize> EventsBuf<N> {
604 const fn new() -> Self {
605 Self {
606 data: [0; N],
607 head: 0,
608 }
609 }
610
611 fn init() -> impl Init<Self> {
612 init!(Self {
613 data <- crate::utils::init::zeroed(),
614 head: 0,
615 })
616 }
617
618 fn reset(&mut self) {
619 self.head = 0;
620 }
621
622 fn rewind_by(&mut self, bytes_written: usize) {
623 assert!(self.head >= bytes_written);
624
625 self.head -= bytes_written;
626 }
627
628 fn slice(&self, len: usize) -> &[u8] {
629 assert!(self.head >= len);
630 &self.data[..len]
631 }
632
633 fn append(&mut self, byte: u8) -> Result<(), OverflowError> {
634 if self.capacity() == 0 {
635 return Err(OverflowError);
636 }
637
638 self.data[self.head] = byte;
639 self.head += 1;
640 Ok(())
641 }
642
643 fn append_slice(&mut self, data: &[u8]) -> Result<(), OverflowError> {
644 if self.capacity() < data.len() {
645 return Err(OverflowError);
646 }
647
648 self.data[self.head..self.head + data.len()].copy_from_slice(data);
649 self.head += data.len();
650
651 Ok(())
652 }
653
654 fn capacity(&self) -> usize {
655 self.data.len() - self.head
656 }
657
658 fn first_event_len(&self) -> usize {
662 assert!(self.head > 0);
663 unwrap!(TLVSequence(&self.data[..self.head]).container_len())
664 }
665
666 fn first_event_prio(&self) -> u8 {
670 unwrap!(unwrap!(
671 unwrap!(TLVElement::new(&self.data[..self.head]).structure())
672 .find_ctx(EventDataTag::Priority as _)
673 )
674 .u8())
675 }
676
677 fn evict_first_event(&mut self) {
678 let tlv_len = self.first_event_len();
679
680 self.data.copy_within(tlv_len..self.head, 0);
681 self.head -= tlv_len;
682 }
683
684 fn iter(&self) -> TLVSequenceIter<'_> {
685 TLVSequence(&self.data[0..self.head]).iter()
686 }
687}
688
689#[derive(Debug)]
690#[cfg_attr(feature = "defmt", derive(defmt::Format))]
691struct OverflowError;
692
693pub struct EventReader {
694 max_seen_event_number: u64,
695 next_max_seen_event_number: u64,
696 fabric_filtered: bool,
701}
702
703impl EventReader {
704 pub const fn new(
705 max_seen_event_number: u64,
706 next_max_seen_event_number: u64,
707 fabric_filtered: bool,
708 ) -> Self {
709 Self {
710 max_seen_event_number,
711 next_max_seen_event_number,
712 fabric_filtered,
713 }
714 }
715
716 pub fn process_read(
717 &mut self,
718 event: EventData<'_>,
719 paths: &TLVArray<'_, EventPath>,
720 event_filters: &Option<TLVArray<'_, EventFilter>>,
721 node: &Node<'_>,
722 accessor: &Accessor<'_>,
723 tw: &mut WriteBuf<'_>,
724 ) -> Result<bool, Error> {
725 let event_number = event.event_number;
726 if !(event_number > self.max_seen_event_number
727 && event_number <= self.next_max_seen_event_number)
728 {
729 return Ok(false);
731 }
732
733 let tail = tw.get_tail();
734
735 let result = self.do_process_read(event, paths, event_filters, node, accessor, &mut *tw);
736
737 if result.is_err() {
738 tw.rewind_to(tail);
742 } else {
743 self.max_seen_event_number = event_number;
748 }
749
750 result
751 }
752
753 fn do_process_read(
754 &mut self,
755 event: EventData<'_>,
756 paths: &TLVArray<'_, EventPath>,
757 event_filters: &Option<TLVArray<'_, EventFilter>>,
758 node: &Node<'_>,
759 accessor: &Accessor<'_>,
760 tw: &mut WriteBuf<'_>,
761 ) -> Result<bool, Error> {
762 if self.fabric_filtered && !Self::matches_fabric(&event, accessor) {
763 return Ok(false);
764 }
765
766 if Self::matches_paths(&event, paths, node, accessor)?
767 && Self::matches_filters(&event, event_filters)?
768 && Self::matches_access(&event, node, accessor)?
769 {
770 EventResp::Data(event).to_tlv(&TagType::Anonymous, &mut *tw)?;
771
772 Ok(true)
773 } else {
774 Ok(false)
775 }
776 }
777
778 fn matches_fabric(event: &EventData<'_>, accessor: &Accessor<'_>) -> bool {
787 let Ok(payload) = event.data.structure() else {
789 return true;
791 };
792
793 let Ok(elem) = payload.find_ctx(crate::im::encoding::FABRIC_INDEX_TAG) else {
794 return true;
796 };
797
798 match elem.non_empty().and_then(|e| e.u8().ok()) {
799 Some(fab_idx) => fab_idx == accessor.fab_idx,
800 None => true,
802 }
803 }
804
805 fn matches_paths(
806 event: &EventData<'_>,
807 paths: &TLVArray<'_, EventPath>,
808 node: &Node<'_>,
809 accessor: &Accessor<'_>,
810 ) -> Result<bool, Error> {
811 for path in paths {
812 let path = path?;
813
814 if Self::matches_path(event, path, node, accessor) {
815 return Ok(true);
816 }
817 }
818
819 Ok(false)
820 }
821
822 fn matches_path(
823 event: &EventData<'_>,
824 path: EventPath,
825 node: &Node<'_>,
826 accessor: &Accessor<'_>,
827 ) -> bool {
828 if node.validate_event_path(&path, accessor).is_err() {
829 return false;
830 }
831
832 let epath = &event.path;
833
834 epath
835 .node
836 .is_none_or(|node| path.node.is_none_or(|expected_node| expected_node == node))
837 && epath.endpoint.is_none_or(|endpoint| {
838 path.endpoint
839 .is_none_or(|expected_endpoint| expected_endpoint == endpoint)
840 })
841 && epath.cluster.is_none_or(|cluster| {
842 path.cluster
843 .is_none_or(|expected_cluster| expected_cluster == cluster)
844 })
845 && epath.event.is_none_or(|event| {
846 path.event
847 .is_none_or(|expected_event| expected_event == event)
848 })
849 }
850
851 fn matches_filters(
852 event: &EventData<'_>,
853 event_filters: &Option<TLVArray<'_, EventFilter>>,
854 ) -> Result<bool, Error> {
855 if let Some(filters) = &event_filters {
856 for filter in filters {
859 if let Some(event_min) = filter?.event_min {
860 if event.event_number < event_min {
861 return Ok(false);
862 }
863 }
864 }
865 }
866
867 Ok(true)
868 }
869
870 fn matches_access(
871 event: &EventData<'_>,
872 node: &Node<'_>,
873 accessor: &Accessor<'_>,
874 ) -> Result<bool, Error> {
875 Ok(node.validate_event_path(&event.path, accessor).is_ok())
876 }
877}
878
879#[cfg(test)]
880mod tests {
881 use crate::tlv::ToTLV;
882
883 use super::*;
884
885 #[test]
886 fn one_entry() {
887 let crit1 = TestEvent::new(1, EventPriority::Critical);
888 let mut q: EventsInner<32> = EventsInner::new();
889
890 crit1.push_into(&mut q).unwrap();
891
892 assert_eq!(TestEvent::vec_from(&q.buf_debug).unwrap(), &[crit1]);
893 }
894
895 #[test]
896 fn critical_is_promoted() {
897 let crit1 = TestEvent::new(1, EventPriority::Critical);
898 let crit2 = TestEvent::new(2, EventPriority::Info);
899 let crit3 = TestEvent::new(3, EventPriority::Info);
900 let mut q: EventsInner<32> = EventsInner::new();
901
902 crit1.push_into(&mut q).unwrap();
903 crit2.push_into(&mut q).unwrap();
904 crit3.push_into(&mut q).unwrap();
905
906 assert_eq!(TestEvent::vec_from(&q.buf_debug).unwrap(), &[crit3]);
907 assert_eq!(TestEvent::vec_from(&q.buf_info).unwrap(), &[crit2]);
908 assert_eq!(TestEvent::vec_from(&q.buf_critical).unwrap(), &[crit1]);
909 }
910
911 #[test]
912 fn debug_is_dropped() {
913 let crit1 = TestEvent::new(1, EventPriority::Critical);
914 let dbg2 = TestEvent::new(2, EventPriority::Debug);
915 let crit3: TestEvent = TestEvent::new(3, EventPriority::Critical);
916 let mut q: EventsInner<32> = EventsInner::new();
917
918 crit1.push_into(&mut q).unwrap();
919 dbg2.push_into(&mut q).unwrap();
920 crit3.push_into(&mut q).unwrap();
921
922 assert_eq!(TestEvent::vec_from(&q.buf_debug).unwrap(), &[crit3]);
924 assert_eq!(TestEvent::vec_from(&q.buf_info).unwrap(), &[crit1]);
927 assert_eq!(TestEvent::vec_from(&q.buf_critical).unwrap(), &[]);
929 }
930
931 #[test]
932 fn event_larger_than_buffer() {
933 let crit1 = TestEvent::new(1, EventPriority::Critical);
934 let mut q: EventsInner<8> = EventsInner::new();
935
936 assert_eq!(
937 crit1.push_into(&mut q).expect_err("").code(),
938 ErrorCode::ResourceExhausted
939 );
940 }
941
942 #[derive(PartialEq, Clone, Debug)]
945 struct TestEvent {
946 endpoint: EndptId,
947 cluster: ClusterId,
948 event: EventId,
949 event_number: EventNumber,
950 priority: EventPriority,
951 timestamp: EventDataTimestamp,
952 data: u64,
953 }
954
955 impl TestEvent {
956 const fn new(event_number: EventNumber, priority: EventPriority) -> Self {
957 Self {
958 endpoint: 42,
959 cluster: 1,
960 event: 0xB33F,
961 event_number,
962 priority,
963 timestamp: EventDataTimestamp::EpochTimestamp(10_000 + event_number),
964 data: 1337,
965 }
966 }
967
968 fn vec_from<const N: usize>(
969 buf: &EventsBuf<N>,
970 ) -> Result<heapless::Vec<TestEvent, N>, Error> {
971 let mut out = heapless::Vec::new();
972 for tr in buf.iter() {
973 let e = EventData::from_tlv(&tr?)?;
974 out.push(TestEvent {
975 endpoint: e.path.endpoint.unwrap(),
976 cluster: e.path.cluster.unwrap(),
977 event: e.path.event.unwrap(),
978 event_number: e.event_number,
979 priority: e.priority,
980 timestamp: e.timestamp,
981 data: e.data.u64()?,
982 })
983 .unwrap();
984 }
985
986 Ok(out)
987 }
988
989 fn push_into<const N: usize>(&self, q: &mut EventsInner<N>) -> Result<(), Error> {
990 q.push(
991 self.endpoint,
992 self.cluster,
993 self.event,
994 self.event_number,
995 self.priority,
996 self.timestamp.clone(),
997 |tw| self.data.to_tlv(&EVENT_DATA_TAG, tw),
998 )
999 }
1000 }
1001}