Skip to content

Commit 92842d6

Browse files
author
blake2-ppc
committed
dlist: Expose ListInsertion trait with insert_before and peek_next
An iterator that allows mutating the list is very useful but needs care to not be unsound. ListIteration exposes only insert_before (used for insert_ordered) and peek_next so far.
1 parent 4fa69ab commit 92842d6

File tree

1 file changed

+35
-12
lines changed

1 file changed

+35
-12
lines changed

src/libextra/dlist.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl<T> List<T> {
272272
///
273273
/// O(N)
274274
#[inline]
275-
pub fn insert_before(&mut self, elt: T, f: &fn(&T, &T) -> bool) {
275+
pub fn insert_when(&mut self, elt: T, f: &fn(&T, &T) -> bool) {
276276
{
277277
let mut it = self.mut_iter();
278278
loop {
@@ -341,7 +341,7 @@ impl<T> List<T> {
341341
/// O(N)
342342
impl<T: cmp::TotalOrd> List<T> {
343343
fn insert_ordered(&mut self, elt: T) {
344-
self.insert_before(elt, |a, b| a.cmp(b) != cmp::Less);
344+
self.insert_when(elt, |a, b| a.cmp(b) != cmp::Less);
345345
}
346346
}
347347

@@ -363,7 +363,7 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> {
363363
}
364364
}
365365

366-
// MutForwardIterator is different because it implements ListInsertCursor,
366+
// MutForwardIterator is different because it implements ListInsertion,
367367
// and can modify the list during traversal, used in insert_when and merge.
368368
impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> {
369369
#[inline]
@@ -433,19 +433,22 @@ impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> {
433433
}
434434
}
435435

436-
// XXX: Should this be `pub`?
437-
trait ListInsertCursor<A> {
436+
/// Allow mutating the List while iterating
437+
pub trait ListInsertion<A> {
438438
/// Insert `elt` just previous to the most recently yielded element
439439
fn insert_before(&mut self, elt: A);
440+
441+
/// Provide a reference to the next element, without changing the iterator
442+
fn peek_next<'a>(&'a mut self) -> Option<&'a mut A>;
440443
}
441444

442-
impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> {
445+
impl<'self, A> ListInsertion<A> for MutForwardIterator<'self, A> {
443446
fn insert_before(&mut self, elt: A) {
444447
match self.curs.resolve() {
445-
None => self.list.push_front(elt),
448+
None => { self.list.push_front(elt); self.next(); }
446449
Some(node) => {
447450
let prev_node = match node.prev.resolve() {
448-
None => return self.list.push_front(elt), // at head
451+
None => return self.list.push_front(elt),
449452
Some(prev) => prev,
450453
};
451454
let mut ins_node = ~Node{value: elt, next: None, prev: Rawlink::none()};
@@ -456,6 +459,16 @@ impl<'self, A> ListInsertCursor<A> for MutForwardIterator<'self, A> {
456459
}
457460
}
458461
}
462+
463+
fn peek_next<'a>(&'a mut self) -> Option<&'a mut A> {
464+
match self.curs.resolve() {
465+
None => self.list.peek_front_mut(),
466+
Some(curs) => match curs.next {
467+
None => None,
468+
Some(ref mut node) => Some(&mut node.value),
469+
}
470+
}
471+
}
459472
}
460473

461474
impl<A> Iterator<A> for ConsumeIterator<A> {
@@ -695,20 +708,30 @@ mod tests {
695708
}
696709

697710
#[test]
698-
fn test_list_cursor() {
699-
let mut m = generate_test();
711+
fn test_insert_prev() {
712+
let mut m = list_from(&[0,2,4,6,8]);
700713
let len = m.len();
701714
{
702715
let mut it = m.mut_iter();
716+
it.insert_before(-2);
703717
loop {
704718
match it.next() {
705719
None => break,
706-
Some(elt) => it.insert_before(*elt * 2),
720+
Some(elt) => {
721+
it.insert_before(*elt + 1);
722+
match it.peek_next() {
723+
Some(x) => assert_eq!(*x, *elt + 2),
724+
None => assert_eq!(8, *elt),
725+
}
726+
}
707727
}
708728
}
729+
it.insert_before(0);
730+
it.insert_before(1);
709731
}
710-
assert_eq!(m.len(), len * 2);
711732
check_links(&m);
733+
assert_eq!(m.len(), 3 + len * 2);
734+
assert_eq!(m.consume_iter().collect::<~[int]>(), ~[-2,1,0,3,2,5,4,7,6,9,0,1,8]);
712735
}
713736

714737
#[test]

0 commit comments

Comments
 (0)