1#[cfg(not(feature = "std"))]
4extern crate alloc;
5
6use alloc::alloc::{alloc_zeroed, handle_alloc_error};
7use alloc::boxed::Box;
8use alloc::vec::Vec;
9use core::alloc::Layout;
10
11use bincode::{Decode, Encode};
12use core::fmt;
13
14use core::fmt::Display;
15use core::iter::{Chain, Rev};
16use core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
17use cu29_traits::{CopperListTuple, ErasedCuStampedData, ErasedCuStampedDataSet};
18use serde_derive::{Deserialize, Serialize};
19
20const MAX_TASKS: usize = 512;
21
22#[derive(Debug, Encode, Decode, PartialEq, Clone, Copy)]
25pub struct CopperLiskMask {
26 #[allow(dead_code)]
27 mask: [u128; MAX_TASKS / 128 + 1],
28}
29
30#[derive(Debug, Encode, Decode, Serialize, Deserialize, PartialEq, Copy, Clone)]
32pub enum CopperListState {
33 Free,
34 Initialized,
35 Processing,
36 DoneProcessing,
37 QueuedForSerialization,
38 BeingSerialized,
39}
40
41impl Display for CopperListState {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 CopperListState::Free => write!(f, "Free"),
45 CopperListState::Initialized => write!(f, "Initialized"),
46 CopperListState::Processing => write!(f, "Processing"),
47 CopperListState::DoneProcessing => write!(f, "DoneProcessing"),
48 CopperListState::QueuedForSerialization => write!(f, "QueuedForSerialization"),
49 CopperListState::BeingSerialized => write!(f, "BeingSerialized"),
50 }
51 }
52}
53
54#[derive(Debug, Encode, Decode, Serialize, Deserialize)]
57pub struct CopperList<P: CopperListTuple> {
58 pub id: u64,
59 #[bincode(skip, default = "deserialized_state")]
61 #[serde(skip, default = "deserialized_state")]
62 state: CopperListState,
63 pub msgs: P, }
65
66fn deserialized_state() -> CopperListState {
67 CopperListState::BeingSerialized
68}
69
70impl<P: CopperListTuple> Default for CopperList<P> {
71 fn default() -> Self {
72 CopperList {
73 id: 0,
74 state: CopperListState::Free,
75 msgs: P::default(),
76 }
77 }
78}
79
80impl<P: CopperListTuple> CopperList<P> {
81 pub fn new(id: u64, msgs: P) -> Self {
83 CopperList {
84 id,
85 state: CopperListState::Initialized,
86 msgs,
87 }
88 }
89
90 pub fn change_state(&mut self, new_state: CopperListState) {
91 self.state = new_state; }
93
94 pub fn get_state(&self) -> CopperListState {
95 self.state
96 }
97
98 #[doc(hidden)]
102 pub fn reset_for_runtime_use(&mut self, id: u64)
103 where
104 P: CuListZeroedInit,
105 {
106 self.id = id;
107 self.state = CopperListState::Initialized;
108 self.msgs.init_zeroed();
109 }
110}
111
112impl<P: CopperListTuple> ErasedCuStampedDataSet for CopperList<P> {
113 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
114 self.msgs.cumsgs()
115 }
116}
117
118pub struct CuListsManager<P: CopperListTuple, const N: usize> {
122 data: Box<[CopperList<P>; N]>,
123 length: usize,
124 insertion_index: usize,
125 current_cl_id: u64,
126}
127
128impl<P: CopperListTuple + fmt::Debug, const N: usize> fmt::Debug for CuListsManager<P, N> {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.debug_struct("CuListsManager")
131 .field("data", &self.data)
132 .field("length", &self.length)
133 .field("insertion_index", &self.insertion_index)
134 .finish()
136 }
137}
138
139pub type Iter<'a, T> = Chain<Rev<SliceIter<'a, T>>, Rev<SliceIter<'a, T>>>;
140pub type IterMut<'a, T> = Chain<Rev<SliceIterMut<'a, T>>, Rev<SliceIterMut<'a, T>>>;
141pub type AscIter<'a, T> = Chain<SliceIter<'a, T>, SliceIter<'a, T>>;
142pub type AscIterMut<'a, T> = Chain<SliceIterMut<'a, T>, SliceIterMut<'a, T>>;
143
144pub trait CuListZeroedInit: CopperListTuple {
147 fn init_zeroed(&mut self);
150}
151
152impl<P: CopperListTuple + CuListZeroedInit, const N: usize> Default for CuListsManager<P, N> {
153 fn default() -> Self {
154 Self::new()
155 }
156}
157
158impl<P: CopperListTuple, const N: usize> CuListsManager<P, N> {
159 pub fn new() -> Self
160 where
161 P: CuListZeroedInit,
162 {
163 let data = unsafe {
165 let layout = Layout::new::<[CopperList<P>; N]>();
166 let ptr = alloc_zeroed(layout) as *mut [CopperList<P>; N];
167 if ptr.is_null() {
168 handle_alloc_error(layout);
169 }
170 Box::from_raw(ptr)
171 };
172 let mut manager = CuListsManager {
173 data,
174 length: 0,
175 insertion_index: 0,
176 current_cl_id: 0,
177 };
178
179 for cl in manager.data.iter_mut() {
180 cl.msgs.init_zeroed();
181 }
182
183 manager
184 }
185
186 #[inline]
189 pub fn len(&self) -> usize {
190 self.length
191 }
192
193 #[inline]
196 pub fn is_empty(&self) -> bool {
197 self.length == 0
198 }
199
200 #[inline]
203 pub fn is_full(&self) -> bool {
204 N == self.len()
205 }
206
207 #[inline]
210 pub fn clear(&mut self) {
211 self.insertion_index = 0;
212 self.length = 0;
213 }
214
215 #[inline]
216 pub fn create(&mut self) -> Option<&mut CopperList<P>>
217 where
218 P: CuListZeroedInit,
219 {
220 if self.is_full() {
221 return None;
222 }
223 let next_id = self.current_cl_id;
224 let result = &mut self.data[self.insertion_index];
225 self.insertion_index = (self.insertion_index + 1) % N;
226 self.length += 1;
227
228 result.reset_for_runtime_use(next_id);
230 self.current_cl_id += 1;
231
232 Some(result)
233 }
234
235 #[inline]
237 pub fn next_cl_id(&self) -> u64 {
238 self.current_cl_id
239 }
240
241 pub(crate) fn set_next_replay_id(&mut self, id: u64) {
242 debug_assert_eq!(self.length, 0);
243 self.current_cl_id = id;
244 }
245
246 #[inline]
250 pub fn last_cl_id(&self) -> u64 {
251 self.current_cl_id.saturating_sub(1)
252 }
253
254 #[inline]
256 pub fn peek(&self) -> Option<&CopperList<P>> {
257 if self.length == 0 {
258 return None;
259 }
260 let index = if self.insertion_index == 0 {
261 N - 1
262 } else {
263 self.insertion_index - 1
264 };
265 Some(&self.data[index])
266 }
267
268 #[inline]
269 #[allow(dead_code)]
270 fn drop_last(&mut self) {
271 if self.length == 0 {
272 return;
273 }
274 if self.insertion_index == 0 {
275 self.insertion_index = N - 1;
276 } else {
277 self.insertion_index -= 1;
278 }
279 self.length -= 1;
280 }
281
282 #[inline]
283 pub fn pop(&mut self) -> Option<&mut CopperList<P>> {
284 if self.length == 0 {
285 return None;
286 }
287 if self.insertion_index == 0 {
288 self.insertion_index = N - 1;
289 } else {
290 self.insertion_index -= 1;
291 }
292 self.length -= 1;
293 Some(&mut self.data[self.insertion_index])
294 }
295
296 #[inline]
301 pub fn iter(&self) -> Iter<'_, CopperList<P>> {
302 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
303 a.iter().rev().chain(b.iter().rev())
304 }
305
306 #[inline]
311 pub fn iter_mut(&mut self) -> IterMut<'_, CopperList<P>> {
312 let (a, b) = self.data[0..self.length].split_at_mut(self.insertion_index);
313 a.iter_mut().rev().chain(b.iter_mut().rev())
314 }
315
316 #[inline]
321 pub fn asc_iter(&self) -> AscIter<'_, CopperList<P>> {
322 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
323 b.iter().chain(a.iter())
324 }
325
326 #[inline]
331 pub fn asc_iter_mut(&mut self) -> AscIterMut<'_, CopperList<P>> {
332 let (a, b) = self.data[0..self.length].split_at_mut(self.insertion_index);
333 b.iter_mut().chain(a.iter_mut())
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340 use cu29_traits::{ErasedCuStampedData, ErasedCuStampedDataSet, MatchingTasks};
341 use serde::{Deserialize, Serialize, Serializer};
342
343 #[derive(Debug, Encode, Decode, PartialEq, Clone, Copy, Serialize, Deserialize, Default)]
344 struct CuStampedDataSet(i32);
345
346 impl ErasedCuStampedDataSet for CuStampedDataSet {
347 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
348 Vec::new()
349 }
350 }
351
352 impl MatchingTasks for CuStampedDataSet {
353 fn get_all_task_ids() -> &'static [&'static str] {
354 &[]
355 }
356 }
357
358 impl CuListZeroedInit for CuStampedDataSet {
359 fn init_zeroed(&mut self) {}
360 }
361
362 #[test]
363 fn serialization_omits_runtime_state() {
364 let expected =
365 bincode::encode_to_vec((42u64, CuStampedDataSet(123)), bincode::config::standard())
366 .unwrap();
367 for state in [
368 CopperListState::Free,
369 CopperListState::Initialized,
370 CopperListState::Processing,
371 CopperListState::DoneProcessing,
372 CopperListState::QueuedForSerialization,
373 CopperListState::BeingSerialized,
374 ] {
375 let mut list = CopperList::new(42, CuStampedDataSet(123));
376 list.change_state(state);
377 let bytes = bincode::encode_to_vec(&list, bincode::config::standard()).unwrap();
378 assert_eq!(bytes, expected);
379 let old_bytes =
380 bincode::encode_to_vec((list.id, state, &list.msgs), bincode::config::standard())
381 .unwrap();
382 assert_eq!(old_bytes.len(), bytes.len() + 1);
383 let (decoded, used): (CopperList<CuStampedDataSet>, usize) =
384 bincode::decode_from_slice(&bytes, bincode::config::standard()).unwrap();
385 assert_eq!(decoded.id, list.id);
386 assert_eq!(decoded.msgs, list.msgs);
387 assert_eq!(decoded.get_state(), CopperListState::BeingSerialized);
388 assert_eq!(used, bytes.len());
389 let (borrowed, used): (CopperList<CuStampedDataSet>, usize) =
390 bincode::borrow_decode_from_slice(&bytes, bincode::config::standard()).unwrap();
391 assert_eq!(borrowed.get_state(), CopperListState::BeingSerialized);
392 assert_eq!(borrowed.msgs, list.msgs);
393 assert_eq!(used, bytes.len());
394 assert_eq!(list.get_state(), state);
395 #[cfg(feature = "std")]
396 {
397 let json = serde_json::to_value(&list).unwrap();
398 assert_eq!(json, serde_json::json!({"id": 42, "msgs": 123}));
399 let decoded: CopperList<CuStampedDataSet> = serde_json::from_value(json).unwrap();
400 assert_eq!(decoded.get_state(), CopperListState::BeingSerialized);
401 assert_eq!(decoded.msgs, list.msgs);
402 }
403 }
404 }
405
406 #[test]
407 fn empty_queue() {
408 let q = CuListsManager::<CuStampedDataSet, 5>::new();
409
410 assert!(q.is_empty());
411 assert!(q.iter().next().is_none());
412 assert!(q.asc_iter().next().is_none());
413 assert!(q.peek().is_none());
414 }
415
416 #[test]
417 fn partially_full_queue() {
418 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
419 q.create().unwrap().msgs.0 = 1;
420 q.create().unwrap().msgs.0 = 2;
421 q.create().unwrap().msgs.0 = 3;
422
423 assert!(!q.is_empty());
424 assert_eq!(q.len(), 3);
425
426 let res: Vec<i32> = q.iter().map(|x| x.msgs.0).collect();
427 assert_eq!(res, [3, 2, 1]);
428 }
429
430 #[test]
431 fn full_queue() {
432 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
433 q.create().unwrap().msgs.0 = 1;
434 q.create().unwrap().msgs.0 = 2;
435 q.create().unwrap().msgs.0 = 3;
436 q.create().unwrap().msgs.0 = 4;
437 q.create().unwrap().msgs.0 = 5;
438 assert_eq!(q.len(), 5);
439
440 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
441 assert_eq!(res, [5, 4, 3, 2, 1]);
442 }
443
444 #[test]
445 fn over_full_queue() {
446 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
447 q.create().unwrap().msgs.0 = 1;
448 q.create().unwrap().msgs.0 = 2;
449 q.create().unwrap().msgs.0 = 3;
450 q.create().unwrap().msgs.0 = 4;
451 q.create().unwrap().msgs.0 = 5;
452 assert!(q.create().is_none());
453 assert_eq!(q.len(), 5);
454
455 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
456 assert_eq!(res, [5, 4, 3, 2, 1]);
457 }
458
459 #[test]
460 fn clear() {
461 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
462 q.create().unwrap().msgs.0 = 1;
463 q.create().unwrap().msgs.0 = 2;
464 q.create().unwrap().msgs.0 = 3;
465 q.create().unwrap().msgs.0 = 4;
466 q.create().unwrap().msgs.0 = 5;
467 assert!(q.create().is_none());
468 assert_eq!(q.len(), 5);
469
470 q.clear();
471
472 assert_eq!(q.len(), 0);
473 assert!(q.iter().next().is_none());
474
475 q.create().unwrap().msgs.0 = 1;
476 q.create().unwrap().msgs.0 = 2;
477 q.create().unwrap().msgs.0 = 3;
478
479 assert_eq!(q.len(), 3);
480
481 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
482 assert_eq!(res, [3, 2, 1]);
483 }
484
485 #[test]
486 fn create_fresh_slot_starts_initialized_with_zeroed_payload() {
487 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
488
489 let cl = q.create().unwrap();
490 assert_eq!(cl.id, 0);
491 assert_eq!(cl.get_state(), CopperListState::Initialized);
492 assert_eq!(cl.msgs.0, 0);
493 assert_eq!(q.next_cl_id(), 1);
494 assert_eq!(q.last_cl_id(), 0);
495 }
496
497 #[test]
498 fn create_reused_slot_reinitializes_state_but_preserves_payload_storage() {
499 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
500
501 {
502 let cl = q.create().unwrap();
503 cl.msgs.0 = 41;
504 cl.change_state(CopperListState::Processing);
505 }
506
507 let popped = q.pop().unwrap();
508 assert_eq!(popped.id, 0);
509 assert_eq!(popped.get_state(), CopperListState::Processing);
510 assert_eq!(popped.msgs.0, 41);
511
512 let reused = q.create().unwrap();
513 assert_eq!(reused.id, 1);
514 assert_eq!(reused.get_state(), CopperListState::Initialized);
515 assert_eq!(reused.msgs.0, 41);
516 assert_eq!(q.next_cl_id(), 2);
517 assert_eq!(q.last_cl_id(), 1);
518 }
519
520 #[test]
521 fn mutable_iterator() {
522 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
523 q.create().unwrap().msgs.0 = 1;
524 q.create().unwrap().msgs.0 = 2;
525 q.create().unwrap().msgs.0 = 3;
526 q.create().unwrap().msgs.0 = 4;
527 q.create().unwrap().msgs.0 = 5;
528
529 for x in q.iter_mut() {
530 x.msgs.0 *= 2;
531 }
532
533 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
534 assert_eq!(res, [10, 8, 6, 4, 2]);
535 }
536
537 #[test]
538 fn mutable_iterator_non_wrapped_only_visits_active_slots() {
539 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
540 q.create().unwrap().msgs.0 = 1;
541 q.create().unwrap().msgs.0 = 2;
542 q.create().unwrap().msgs.0 = 3;
543
544 let mut visited = Vec::new();
545 for cl in q.iter_mut() {
546 visited.push(cl.id);
547 cl.msgs.0 *= 10;
548 }
549
550 assert_eq!(visited, vec![2, 1, 0]);
551 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
552 assert_eq!(res, [30, 20, 10]);
553 }
554
555 #[test]
556 fn test_drop_last() {
557 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
558 q.create().unwrap().msgs.0 = 1;
559 q.create().unwrap().msgs.0 = 2;
560 q.create().unwrap().msgs.0 = 3;
561 q.create().unwrap().msgs.0 = 4;
562 q.create().unwrap().msgs.0 = 5;
563 assert_eq!(q.len(), 5);
564
565 q.drop_last();
566 assert_eq!(q.len(), 4);
567
568 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
569 assert_eq!(res, [4, 3, 2, 1]);
570 }
571
572 #[test]
573 fn drop_last_on_empty_queue_is_a_noop() {
574 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
575
576 q.drop_last();
577
578 assert!(q.is_empty());
579 assert!(q.peek().is_none());
580 assert!(q.pop().is_none());
581 }
582
583 #[test]
584 fn drop_last_on_non_wrapped_queue_removes_most_recent_slot() {
585 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
586 q.create().unwrap().msgs.0 = 1;
587 q.create().unwrap().msgs.0 = 2;
588 q.create().unwrap().msgs.0 = 3;
589
590 q.drop_last();
591
592 assert_eq!(q.len(), 2);
593 assert_eq!(q.peek().unwrap().msgs.0, 2);
594 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
595 assert_eq!(res, [2, 1]);
596 }
597
598 #[test]
599 fn test_pop() {
600 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
601 q.create().unwrap().msgs.0 = 1;
602 q.create().unwrap().msgs.0 = 2;
603 q.create().unwrap().msgs.0 = 3;
604 q.create().unwrap().msgs.0 = 4;
605 q.create().unwrap().msgs.0 = 5;
606 assert_eq!(q.len(), 5);
607
608 let last = q.pop().unwrap();
609 assert_eq!(last.msgs.0, 5);
610 assert_eq!(q.len(), 4);
611
612 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
613 assert_eq!(res, [4, 3, 2, 1]);
614 }
615
616 #[test]
617 fn pop_on_empty_queue_returns_none() {
618 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
619
620 assert!(q.pop().is_none());
621 assert!(q.is_empty());
622 }
623
624 #[test]
625 fn test_peek() {
626 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
627 q.create().unwrap().msgs.0 = 1;
628 q.create().unwrap().msgs.0 = 2;
629 q.create().unwrap().msgs.0 = 3;
630 q.create().unwrap().msgs.0 = 4;
631 q.create().unwrap().msgs.0 = 5;
632 assert_eq!(q.len(), 5);
633
634 let last = q.peek().unwrap();
635 assert_eq!(last.msgs.0, 5);
636 assert_eq!(q.len(), 5);
637
638 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
639 assert_eq!(res, [5, 4, 3, 2, 1]);
640 }
641
642 #[test]
643 fn peek_on_empty_queue_returns_none() {
644 let q = CuListsManager::<CuStampedDataSet, 5>::new();
645
646 assert!(q.peek().is_none());
647 }
648
649 #[test]
650 fn next_and_last_cl_id_track_assigned_ids() {
651 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
652
653 assert_eq!(q.next_cl_id(), 0);
655 assert_eq!(q.last_cl_id(), 0);
656
657 let cl0 = q.create().unwrap();
658 assert_eq!(cl0.id, 0);
659 assert_eq!(q.next_cl_id(), 1);
660 assert_eq!(q.last_cl_id(), 0);
661
662 let cl1 = q.create().unwrap();
663 assert_eq!(cl1.id, 1);
664 assert_eq!(q.next_cl_id(), 2);
665 assert_eq!(q.last_cl_id(), 1);
666
667 let _ = q.pop().unwrap();
668 let cl2 = q.create().unwrap();
669 assert_eq!(cl2.id, 2);
670 assert_eq!(q.next_cl_id(), 3);
671 assert_eq!(q.last_cl_id(), 2);
672 }
673
674 #[test]
675 fn asc_iter_non_wrapped_returns_oldest_to_newest_without_free_slots() {
676 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
677 q.create().unwrap().msgs.0 = 10;
678 q.create().unwrap().msgs.0 = 20;
679 q.create().unwrap().msgs.0 = 30;
680
681 let res: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
682 assert_eq!(res, [10, 20, 30]);
683 }
684
685 #[test]
686 fn asc_iter_mut_non_wrapped_only_visits_active_slots_in_oldest_first_order() {
687 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
688 q.create().unwrap().msgs.0 = 10;
689 q.create().unwrap().msgs.0 = 20;
690 q.create().unwrap().msgs.0 = 30;
691
692 let mut visited = Vec::new();
693 for (offset, cl) in q.asc_iter_mut().enumerate() {
694 visited.push(cl.id);
695 cl.msgs.0 += offset as i32;
696 }
697
698 assert_eq!(visited, vec![0, 1, 2]);
699 let res: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
700 assert_eq!(res, [10, 21, 32]);
701 }
702
703 #[test]
704 fn asc_iter_wrapped_layout_tracks_reused_slots_in_ascending_order() {
705 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
706 for value in 1..=5 {
707 q.create().unwrap().msgs.0 = value;
708 }
709 assert_eq!(q.pop().unwrap().msgs.0, 5);
710 assert_eq!(q.pop().unwrap().msgs.0, 4);
711 q.create().unwrap().msgs.0 = 6;
712 q.create().unwrap().msgs.0 = 7;
713
714 let desc: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
715 assert_eq!(desc, [7, 6, 3, 2, 1]);
716
717 let asc: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
718 assert_eq!(asc, [1, 2, 3, 6, 7]);
719 }
720
721 #[test]
722 fn asc_iter_mut_wrapped_layout_updates_oldest_to_newest_order() {
723 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
724 for value in 1..=5 {
725 q.create().unwrap().msgs.0 = value;
726 }
727 let _ = q.pop().unwrap();
728 let _ = q.pop().unwrap();
729 q.create().unwrap().msgs.0 = 6;
730 q.create().unwrap().msgs.0 = 7;
731
732 let mut visited = Vec::new();
733 for (offset, cl) in q.asc_iter_mut().enumerate() {
734 visited.push(cl.id);
735 cl.msgs.0 += offset as i32;
736 }
737
738 assert_eq!(visited, vec![0, 1, 2, 5, 6]);
739 let asc: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
740 assert_eq!(asc, [1, 3, 5, 9, 11]);
741 }
742
743 #[derive(Decode, Encode, Debug, PartialEq, Clone, Copy)]
744 struct TestStruct {
745 content: [u8; 10_000_000],
746 }
747
748 impl Default for TestStruct {
749 fn default() -> Self {
750 TestStruct {
751 content: [0; 10_000_000],
752 }
753 }
754 }
755
756 impl ErasedCuStampedDataSet for TestStruct {
757 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
758 Vec::new()
759 }
760 }
761
762 impl Serialize for TestStruct {
763 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
764 where
765 S: Serializer,
766 {
767 serializer.serialize_i8(0)
768 }
769 }
770
771 impl MatchingTasks for TestStruct {
772 fn get_all_task_ids() -> &'static [&'static str] {
773 &[]
774 }
775 }
776
777 impl CuListZeroedInit for TestStruct {
778 fn init_zeroed(&mut self) {}
779 }
780
781 #[test]
782 fn be_sure_we_wont_stackoverflow_at_init() {
783 let _ = CuListsManager::<TestStruct, 3>::new();
784 }
785}