1use crate::{EntityAlloc, IEntityAllocID, PtrID, alloc::IEntityAllocatable};
2use std::{
3 cell::Cell,
4 error::Error,
5 fmt::{Debug, Display},
6 iter::Rev,
7};
8
9pub struct EntityListHead<E: IEntityAllocatable>(pub Option<PtrID<E>>, pub Option<PtrID<E>>);
10
11impl<E: IEntityAllocatable> Clone for EntityListHead<E> {
12 #[inline]
13 fn clone(&self) -> Self {
14 Self(self.0, self.1)
15 }
16}
17impl<E: IEntityAllocatable> Copy for EntityListHead<E> {}
18impl<E: IEntityAllocatable> EntityListHead<E> {
19 #[inline]
20 pub fn none() -> Self {
21 Self(None, None)
22 }
23
24 #[inline]
25 pub fn get_prev_id(&self) -> Option<PtrID<E>> {
26 self.0
27 }
28 #[inline]
29 pub fn get_next_id(&self) -> Option<PtrID<E>> {
30 self.1
31 }
32
33 #[inline]
34 pub fn prev_id(self, prev: Option<PtrID<E>>) -> Self {
35 Self(prev, self.1)
36 }
37 #[inline]
38 pub fn next_id(self, next: Option<PtrID<E>>) -> Self {
39 Self(self.0, next)
40 }
41}
42
43pub enum EntityListError<E: IEntityAllocatable> {
44 EmptyList,
45 ListBroken,
46 NodeIsSentinel,
47 RepeatedNode,
48 SelfNotAttached(PtrID<E>),
49 ItemFalselyAttached(PtrID<E>),
50 ItemFalselyDetached(PtrID<E>),
51}
52impl<E: IEntityAllocatable> Debug for EntityListError<E> {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 use EntityListError::*;
55 match self {
56 EmptyList => write!(f, "EmptyList"),
57 ListBroken => write!(f, "ListBroken"),
58 NodeIsSentinel => write!(f, "NodeIsSentinel"),
59 RepeatedNode => write!(f, "RepeatedNode"),
60 SelfNotAttached(id) => {
61 write!(f, "SelfNotAttached({id:?})")
62 }
63 ItemFalselyAttached(id) => {
64 write!(f, "ItemFalselyAttached({id:?})")
65 }
66 ItemFalselyDetached(id) => {
67 write!(f, "ItemFalselyDetached({id:?})")
68 }
69 }
70 }
71}
72impl<E: IEntityAllocatable> Clone for EntityListError<E> {
73 fn clone(&self) -> Self {
74 match self {
75 EntityListError::EmptyList => EntityListError::EmptyList,
76 EntityListError::ListBroken => EntityListError::ListBroken,
77 EntityListError::NodeIsSentinel => EntityListError::NodeIsSentinel,
78 EntityListError::RepeatedNode => EntityListError::RepeatedNode,
79 EntityListError::SelfNotAttached(id) => EntityListError::SelfNotAttached(*id),
80 EntityListError::ItemFalselyAttached(id) => EntityListError::ItemFalselyAttached(*id),
81 EntityListError::ItemFalselyDetached(id) => EntityListError::ItemFalselyDetached(*id),
82 }
83 }
84}
85impl<E: IEntityAllocatable> Copy for EntityListError<E> {}
86impl<E: IEntityAllocatable> Display for EntityListError<E> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(f, "{self:?}")
89 }
90}
91impl<E: IEntityAllocatable> Error for EntityListError<E> {}
92
93pub type PtrListRes<E, T = ()> = Result<T, EntityListError<E>>;
94
95pub trait IEntityListNode: Sized + IEntityAllocatable {
96 fn load_head(&self) -> EntityListHead<Self>;
97 fn store_head(&self, head: EntityListHead<Self>);
98 fn is_sentinel(&self) -> bool;
99 fn new_sentinel() -> Self;
100 fn on_push_next(
101 curr: PtrID<Self>,
102 next: PtrID<Self>,
103 alloc: &EntityAlloc<Self>,
104 ) -> PtrListRes<Self>;
105 fn on_push_prev(
106 curr: PtrID<Self>,
107 prev: PtrID<Self>,
108 alloc: &EntityAlloc<Self>,
109 ) -> PtrListRes<Self>;
110 fn on_unplug(curr: PtrID<Self>, alloc: &EntityAlloc<Self>) -> PtrListRes<Self>;
111
112 #[inline]
113 fn get_prev_id(&self) -> Option<PtrID<Self>> {
114 self.load_head().get_prev_id()
115 }
116 #[inline]
117 fn get_next_id(&self) -> Option<PtrID<Self>> {
118 self.load_head().get_next_id()
119 }
120
121 #[inline]
122 fn set_prev_id(&self, prev: Option<PtrID<Self>>) {
123 let head = self.load_head();
124 self.store_head(head.prev_id(prev));
125 }
126 #[inline]
127 fn set_next_id(&self, next: Option<PtrID<Self>>) {
128 let head = self.load_head();
129 self.store_head(head.next_id(next));
130 }
131
132 #[inline]
133 fn is_attached(&self) -> bool {
134 let EntityListHead(prev, next) = self.load_head();
135 assert!(
136 self.is_sentinel() || prev.is_some() == next.is_some(),
137 "ptrlist node is corrupted"
138 );
139 prev.is_some() || next.is_some()
140 }
141
142 fn comes_before(
143 curr: PtrID<Self>,
144 other: PtrID<Self>,
145 alloc: &EntityAlloc<Self>,
146 ) -> PtrListRes<Self> {
147 let mut node = curr;
148 while let Some(next) = node.deref(alloc).get_next_id() {
149 if next == other {
150 return Ok(());
151 }
152 node = next;
153 }
154 Err(EntityListError::ListBroken)
155 }
156}
157
158pub struct EntityListRange<E: IEntityListNode> {
163 pub start: PtrID<E>,
164 pub end: Option<PtrID<E>>,
165}
166
167impl<E: IEntityListNode> EntityListRange<E> {
168 #[inline]
169 pub fn is_empty(&self) -> bool {
170 Some(self.start) == self.end
171 }
172
173 pub fn iter<'alloc>(&self, alloc: &'alloc EntityAlloc<E>) -> EntityListReadIter<'alloc, E> {
174 EntityListReadIter {
175 alloc,
176 curr: Some(self.start),
177 end: self.end,
178 }
179 }
180}
181
182pub struct EntityList<E: IEntityListNode> {
183 pub head: PtrID<E>,
184 pub tail: PtrID<E>,
185 pub len: Cell<usize>,
186}
187
188impl<E: IEntityListNode> EntityList<E> {
189 pub fn new(alloc: &EntityAlloc<E>) -> Self {
190 let head = alloc.allocate(E::new_sentinel());
191 let tail = alloc.allocate(E::new_sentinel());
192 head.deref(alloc).set_next_id(Some(tail));
193 tail.deref(alloc).set_prev_id(Some(head));
194 Self {
195 head,
196 tail,
197 len: Cell::new(0),
198 }
199 }
200
201 #[inline]
202 pub fn len(&self) -> usize {
203 self.len.get()
204 }
205 #[inline]
206 pub fn is_empty(&self) -> bool {
207 self.len.get() == 0
208 }
209
210 pub fn get_front_id(&self, alloc: &EntityAlloc<E>) -> Option<PtrID<E>> {
211 let head = self.head.deref(alloc);
212 let next = head.get_next_id()?;
213 if next == self.tail { None } else { Some(next) }
214 }
215 pub fn get_back_id(&self, alloc: &EntityAlloc<E>) -> Option<PtrID<E>> {
216 let tail = self.tail.deref(alloc);
217 let prev = tail.get_prev_id()?;
218 if prev == self.head { None } else { Some(prev) }
219 }
220
221 pub fn node_add_next(
222 &self,
223 node: PtrID<E>,
224 new_node: PtrID<E>,
225 alloc: &EntityAlloc<E>,
226 ) -> PtrListRes<E> {
227 if node == new_node {
228 return Err(EntityListError::RepeatedNode);
229 }
230 E::on_push_next(node, new_node, alloc)?;
231 assert!(node.deref(alloc).is_attached());
232 assert!(!new_node.deref(alloc).is_attached());
233 let node_obj = node.deref(alloc);
234 let orig_next = node_obj.get_next_id();
235 new_node
236 .deref(alloc)
237 .store_head(EntityListHead(Some(node), orig_next));
238 node_obj.set_next_id(Some(new_node));
239 if let Some(orig_next) = orig_next {
240 orig_next.deref(alloc).set_prev_id(Some(new_node));
241 }
242 self.len.set(self.len.get() + 1);
243 Ok(())
244 }
245 pub fn node_add_prev(
246 &self,
247 node: PtrID<E>,
248 new_node: PtrID<E>,
249 alloc: &EntityAlloc<E>,
250 ) -> PtrListRes<E> {
251 if node == new_node {
252 return Err(EntityListError::RepeatedNode);
253 }
254 E::on_push_prev(node, new_node, alloc)?;
255 assert!(node.deref(alloc).is_attached());
256 assert!(!new_node.deref(alloc).is_attached());
257 let node_obj = node.deref(alloc);
258 let orig_prev = node_obj.get_prev_id();
259 new_node
260 .deref(alloc)
261 .store_head(EntityListHead(orig_prev, Some(node)));
262 node_obj.set_prev_id(Some(new_node));
263 if let Some(orig_prev) = orig_prev {
264 orig_prev.deref(alloc).set_next_id(Some(new_node));
265 }
266 self.len.set(self.len.get() + 1);
267 Ok(())
268 }
269 pub fn node_unplug(&self, node: PtrID<E>, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
270 if node == self.head || node == self.tail {
271 return Err(EntityListError::NodeIsSentinel);
272 }
273 E::on_unplug(node, alloc)?;
274 assert!(node.deref(alloc).is_attached());
275 let node_obj = node.deref(alloc);
276 let prev = node_obj.get_prev_id().ok_or(EntityListError::ListBroken)?;
277 let next = node_obj.get_next_id().ok_or(EntityListError::ListBroken)?;
278 prev.deref(alloc).set_next_id(Some(next));
279 next.deref(alloc).set_prev_id(Some(prev));
280 node_obj.store_head(EntityListHead(None, None));
281 self.len.set(self.len.get() - 1);
282 Ok(())
283 }
284
285 #[inline]
286 pub fn push_back_id(&self, new_node: PtrID<E>, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
287 self.node_add_prev(self.tail, new_node, alloc)
288 }
289 #[inline]
290 pub fn push_front_id(&self, new_node: PtrID<E>, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
291 self.node_add_next(self.head, new_node, alloc)
292 }
293 #[inline]
294 pub fn push_back_val(&self, val: E, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
295 self.push_back_id(alloc.allocate(val), alloc)
296 }
297 #[inline]
298 pub fn push_front_val(&self, val: E, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
299 self.push_front_id(alloc.allocate(val), alloc)
300 }
301
302 pub fn pop_back(&self, alloc: &EntityAlloc<E>) -> PtrListRes<E, PtrID<E>> {
303 let back_id = self.get_back_id(alloc).ok_or(EntityListError::EmptyList)?;
304 self.node_unplug(back_id, alloc)?;
305 Ok(back_id)
306 }
307 pub fn pop_front(&self, alloc: &EntityAlloc<E>) -> PtrListRes<E, PtrID<E>> {
308 let front_id = self.get_front_id(alloc).ok_or(EntityListError::EmptyList)?;
309 self.node_unplug(front_id, alloc)?;
310 Ok(front_id)
311 }
312
313 pub fn foreach(&self, alloc: &EntityAlloc<E>, mut f: impl FnMut(PtrID<E>, &E)) {
314 let mut node_opt = self.get_front_id(alloc);
315 while let Some(node) = node_opt {
316 let node_obj = node.deref(alloc);
317 f(node, node_obj);
318 node_opt = node_obj.get_next_id();
319 if node_opt == Some(self.tail) {
320 break;
321 }
322 }
323 }
324 pub fn forall_with_sentinel(
325 &self,
326 alloc: &EntityAlloc<E>,
327 mut f: impl FnMut(PtrID<E>, &E) -> bool,
328 ) -> bool {
329 let mut node_opt = Some(self.head);
330 while let Some(node) = node_opt {
331 let node_obj = node.deref(alloc);
332 if !f(node, node_obj) {
333 return false;
334 }
335 node_opt = node_obj.get_next_id();
336 }
337 true
338 }
339
340 pub fn get_range(&self, alloc: &EntityAlloc<E>) -> EntityListRange<E> {
341 let Some(start) = self.head.deref(alloc).get_next_id() else {
342 panic!("EntityList corrupted: head has no next");
343 };
344 EntityListRange {
345 start,
346 end: Some(self.tail),
347 }
348 }
349 pub fn get_range_with_sentinels(&self) -> EntityListRange<E> {
351 EntityListRange {
352 start: self.head,
353 end: None,
354 }
355 }
356
357 pub fn iter<'alloc>(
358 &'alloc self,
359 alloc: &'alloc EntityAlloc<E>,
360 ) -> EntityListReadIter<'alloc, E> {
361 EntityListReadIter {
362 alloc,
363 curr: self.head.deref(alloc).get_next_id(),
364 end: Some(self.tail),
365 }
366 }
367 pub fn iter_with_sentinels<'alloc>(
368 &'alloc self,
369 alloc: &'alloc EntityAlloc<E>,
370 ) -> EntityListReadIter<'alloc, E> {
371 EntityListReadIter {
372 alloc,
373 curr: Some(self.head),
374 end: None,
375 }
376 }
377}
378
379pub struct EntityListReadIter<'alloc, E: IEntityListNode> {
380 alloc: &'alloc EntityAlloc<E>,
381 curr: Option<PtrID<E>>,
382 end: Option<PtrID<E>>,
383}
384impl<'alloc, E: IEntityListNode> Iterator for EntityListReadIter<'alloc, E> {
385 type Item = (PtrID<E>, &'alloc E);
386
387 fn next(&mut self) -> Option<Self::Item> {
388 let curr_id = self.curr?;
389 if Some(curr_id) == self.end {
390 return None;
391 }
392 let curr_obj = curr_id.deref(self.alloc);
393 self.curr = curr_obj.get_next_id();
394 Some((curr_id, curr_obj))
395 }
396}
397
398pub trait IEntityRingListNode: Sized + IEntityAllocatable {
400 fn load_head(&self) -> EntityListHead<Self>;
401 fn store_head(&self, head: EntityListHead<Self>);
402 fn is_sentinel(&self) -> bool;
403 fn new_sentinel() -> Self;
404
405 fn ring_list_node_dispose(&self, alloc: &EntityAlloc<Self>) {
406 self.detach(alloc)
407 .expect("Failed to detach node during disposal");
408 }
409 fn on_self_unplug(&self, self_id: PtrID<Self>, alloc: &EntityAlloc<Self>);
410
411 #[inline]
412 fn get_prev_id(&self) -> Option<PtrID<Self>> {
413 self.load_head().get_prev_id()
414 }
415 #[inline]
416 fn get_next_id(&self) -> Option<PtrID<Self>> {
417 self.load_head().get_next_id()
418 }
419 #[inline]
420 fn set_prev_id(&self, prev: Option<PtrID<Self>>) {
421 let head = self.load_head();
422 self.store_head(head.prev_id(prev));
423 }
424 #[inline]
425 fn set_next_id(&self, next: Option<PtrID<Self>>) {
426 let head = self.load_head();
427 self.store_head(head.next_id(next));
428 }
429
430 #[inline]
431 fn is_attached(&self) -> bool {
432 let EntityListHead(prev, next) = self.load_head();
433 assert!(
434 prev.is_some() == next.is_some(),
435 "ptrlist node is corrupted"
436 );
437 prev.is_some() || next.is_some()
438 }
439 fn detach(&self, alloc: &EntityAlloc<Self>) -> PtrListRes<Self> {
440 if self.is_sentinel() {
441 return Err(EntityListError::NodeIsSentinel);
442 }
443 let EntityListHead(Some(prev), Some(next)) = self.load_head() else {
444 return Ok(());
446 };
447 prev.deref(alloc).set_next_id(Some(next));
448 next.deref(alloc).set_prev_id(Some(prev));
449 self.store_head(EntityListHead(None, None));
450 Ok(())
451 }
452}
453
454impl<E: IEntityRingListNode> PtrID<E> {
455 pub fn detach(self, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
456 let obj = self.deref(alloc);
457 if obj.is_sentinel() {
458 return Err(EntityListError::NodeIsSentinel);
459 }
460 let EntityListHead(Some(prev), Some(next)) = obj.load_head() else {
461 return Ok(());
463 };
464 prev.deref(alloc).set_next_id(Some(next));
465 next.deref(alloc).set_prev_id(Some(prev));
466 obj.store_head(EntityListHead(None, None));
467 Ok(())
468 }
469}
470
471pub struct EntityRingList<E: IEntityRingListNode> {
473 pub sentinel: PtrID<E>,
474}
475
476impl<E: IEntityRingListNode> EntityRingList<E> {
477 pub fn new(alloc: &EntityAlloc<E>) -> Self {
478 let sentinel = alloc.allocate(E::new_sentinel());
479 let head = Some(sentinel);
480 sentinel.deref(alloc).store_head(EntityListHead(head, head));
481 Self { sentinel }
482 }
483
484 pub fn is_empty(&self, alloc: &EntityAlloc<E>) -> bool {
485 let sentinel_obj = self.sentinel.deref(alloc);
486 match sentinel_obj.get_next_id() {
487 Some(id) => id.deref(alloc).is_sentinel(),
488 None => true,
489 }
490 }
491
492 pub fn foreach(&self, alloc: &EntityAlloc<E>, mut f: impl FnMut(PtrID<E>, &E)) {
493 let mut node_id_opt = self.sentinel.deref(alloc).get_next_id();
494 while let Some(node_id) = node_id_opt {
495 if node_id.deref(alloc).is_sentinel() {
496 break;
497 }
498 let node_obj = node_id.deref(alloc);
499 f(node_id, node_obj);
500 node_id_opt = node_obj.get_next_id();
501 }
502 }
503 pub fn forall_with_sentinel(
504 &self,
505 alloc: &EntityAlloc<E>,
506 mut f: impl FnMut(PtrID<E>, &E) -> bool,
507 ) -> bool {
508 let mut node_id_opt = Some(self.sentinel);
509 let mut n = 0;
510 while let Some(node_id) = node_id_opt {
511 let node_obj = node_id.deref(alloc);
512 if !f(node_id, node_obj) {
513 return false;
514 }
515 let next = node_obj.get_next_id();
516 if next == Some(self.sentinel) {
517 return true;
518 }
519 node_id_opt = next;
520 n += 1;
521 }
522 panic!("Broken ring list detected after {n} iterations");
523 }
524 pub fn len(&self, alloc: &EntityAlloc<E>) -> usize {
525 let mut count = 0;
526 self.foreach(alloc, |_, _| count += 1);
527 count
528 }
529 pub fn front_id(&self, alloc: &EntityAlloc<E>) -> Option<PtrID<E>> {
530 let next = self.sentinel.deref(alloc).get_next_id()?;
531 if next.deref(alloc).is_sentinel() {
532 None
533 } else {
534 Some(next)
535 }
536 }
537 pub fn back_id(&self, alloc: &EntityAlloc<E>) -> Option<PtrID<E>> {
538 let prev = self.sentinel.deref(alloc).get_prev_id()?;
539 if prev.deref(alloc).is_sentinel() {
540 None
541 } else {
542 Some(prev)
543 }
544 }
545 pub fn is_single(&self, alloc: &EntityAlloc<E>) -> bool {
546 let s = self.sentinel.deref(alloc);
547 let next = s.get_next_id().unwrap_or(self.sentinel);
548 let prev = s.get_prev_id().unwrap_or(self.sentinel);
549 next == prev && !next.deref(alloc).is_sentinel()
550 }
551 #[inline]
552 pub fn is_multiple(&self, alloc: &EntityAlloc<E>) -> bool {
553 !self.is_empty(alloc) && !self.is_single(alloc)
554 }
555 pub fn contains(&self, node: PtrID<E>, alloc: &EntityAlloc<E>) -> bool {
556 if !node.deref(alloc).is_attached() {
557 return false;
558 }
559 let mut cur = self.sentinel.deref(alloc).get_next_id();
560 while let Some(id) = cur {
561 if id == node {
562 return true;
563 }
564 if id.deref(alloc).is_sentinel() {
565 break;
566 }
567 cur = id.deref(alloc).get_next_id();
568 }
569 false
570 }
571 #[inline]
573 pub fn clone_view(&self) -> Self {
574 Self {
575 sentinel: self.sentinel,
576 }
577 }
578 pub fn iter<'alloc>(
579 &'alloc self,
580 alloc: &'alloc EntityAlloc<E>,
581 ) -> EntityRingListReadIter<'alloc, E> {
582 EntityRingListReadIter {
583 alloc,
584 curr: self
585 .sentinel
586 .deref(alloc)
587 .get_next_id()
588 .unwrap_or(self.sentinel),
589 }
590 }
591 pub fn back_iter<'alloc>(
592 &'alloc self,
593 alloc: &'alloc EntityAlloc<E>,
594 ) -> Rev<EntityRingListReadIter<'alloc, E>> {
595 EntityRingListReadIter {
596 alloc,
597 curr: self
598 .sentinel
599 .deref(alloc)
600 .get_prev_id()
601 .unwrap_or(self.sentinel),
602 }
603 .rev()
604 }
605
606 pub fn push_back_id(&self, new_node: PtrID<E>, alloc: &EntityAlloc<E>) -> PtrListRes<E> {
608 let sentinel = self.sentinel;
610 let s_obj = sentinel.deref(alloc);
611 assert!(s_obj.is_sentinel());
612 let prev = s_obj
613 .get_prev_id()
614 .expect("ring broken: sentinel.prev is None");
615 assert!(!new_node.deref(alloc).is_attached());
617 new_node
618 .deref(alloc)
619 .store_head(EntityListHead(Some(prev), Some(sentinel)));
620 s_obj.set_prev_id(Some(new_node));
621 prev.deref(alloc).set_next_id(Some(new_node));
622 Ok(())
623 }
624
625 pub fn move_all_to(
630 &self,
631 other: &EntityRingList<E>,
632 alloc: &EntityAlloc<E>,
633 mut on_move: impl FnMut(PtrID<E>),
634 ) -> PtrListRes<E> {
635 if self.sentinel == other.sentinel {
636 return Ok(());
637 }
638 let mut cur = self.front_id(alloc);
639 while let Some(id) = cur {
640 let next = id.deref(alloc).get_next_id();
641 id.detach(alloc)?;
642 other.push_back_id(id, alloc)?;
643 on_move(id);
644 cur = match next {
645 Some(n) if !n.deref(alloc).is_sentinel() => Some(n),
646 _ => None,
647 };
648 }
649 Ok(())
650 }
651 pub fn move_to_if(
653 &self,
654 other: &EntityRingList<E>,
655 alloc: &EntityAlloc<E>,
656 mut predicate: impl FnMut(PtrID<E>, &E) -> bool,
657 mut on_move: impl FnMut(PtrID<E>),
658 ) -> PtrListRes<E> {
659 if self.sentinel == other.sentinel {
660 return Ok(());
661 }
662 let mut cur = self.front_id(alloc);
663 while let Some(id) = cur {
664 let next = id.deref(alloc).get_next_id();
665 let obj = id.deref(alloc);
666 if predicate(id, obj) {
667 id.detach(alloc)?;
668 other.push_back_id(id, alloc)?;
669 on_move(id);
670 }
671 cur = match next {
672 Some(n) if !n.deref(alloc).is_sentinel() => Some(n),
673 _ => None,
674 };
675 }
676 Ok(())
677 }
678
679 pub fn clean(&self, alloc: &EntityAlloc<E>) {
681 let mut node = self.sentinel.deref(alloc).get_next_id();
682 while let Some(node_id) = node {
683 if node_id == self.sentinel {
684 break;
685 }
686 let next_node = node_id.deref(alloc).get_next_id();
687 node_id.deref(alloc).store_head(EntityListHead(None, None));
688 node_id.deref(alloc).on_self_unplug(node_id, alloc);
689 node = next_node;
690 }
691 self.sentinel
692 .deref(alloc)
693 .store_head(EntityListHead(Some(self.sentinel), Some(self.sentinel)));
694 }
695
696 pub fn pop_back(&self, alloc: &EntityAlloc<E>) -> PtrListRes<E, PtrID<E>> {
697 let back_id = self.back_id(alloc).ok_or(EntityListError::EmptyList)?;
698 back_id.detach(alloc)?;
699 back_id.deref(alloc).on_self_unplug(back_id, alloc);
700 Ok(back_id)
701 }
702 pub fn pop_front(&self, alloc: &EntityAlloc<E>) -> PtrListRes<E, PtrID<E>> {
703 let front_id = self.front_id(alloc).ok_or(EntityListError::EmptyList)?;
704 front_id.detach(alloc)?;
705 front_id.deref(alloc).on_self_unplug(front_id, alloc);
706 Ok(front_id)
707 }
708}
709
710pub struct EntityRingListReadIter<'alloc, E: IEntityRingListNode> {
711 alloc: &'alloc EntityAlloc<E>,
712 curr: PtrID<E>,
713}
714
715impl<'alloc, E: IEntityRingListNode> Iterator for EntityRingListReadIter<'alloc, E> {
716 type Item = (PtrID<E>, &'alloc E);
717
718 fn next(&mut self) -> Option<Self::Item> {
719 let curr_id = self.curr;
720 let curr_obj = curr_id.deref(self.alloc);
721 if curr_obj.is_sentinel() {
722 return None;
723 }
724 let next_id = curr_obj.get_next_id()?;
725 if next_id == self.curr {
726 return None;
727 }
728 self.curr = next_id;
729 Some((curr_id, curr_obj))
730 }
731}
732impl<'alloc, E: IEntityRingListNode> DoubleEndedIterator for EntityRingListReadIter<'alloc, E> {
733 fn next_back(&mut self) -> Option<Self::Item> {
734 let curr_id = self.curr;
735 let curr_obj = curr_id.deref(self.alloc);
736 if curr_obj.is_sentinel() {
737 return None;
738 }
739 let prev_id = curr_obj.get_prev_id()?;
740 if prev_id == self.curr {
741 return None;
742 }
743 self.curr = prev_id;
744 Some((curr_id, curr_obj))
745 }
746}