Adding in UpdateAt for ListChange

This commit is contained in:
Pauan 2018-02-27 21:54:58 -10:00
parent 9bb627ae20
commit e34fc50ad0
1 changed files with 55 additions and 9 deletions

View File

@ -2,7 +2,7 @@ use futures::Async;
//use std::iter::Iterator; //use std::iter::Iterator;
fn update_indexes<A: Copy, F: FnMut(A) -> A>(indexes: &mut [Option<A>], mut f: F) -> Option<A> { fn increment_indexes(indexes: &mut [Option<usize>]) -> Option<usize> {
let mut first = None; let mut first = None;
for index in indexes.into_iter() { for index in indexes.into_iter() {
@ -11,13 +11,21 @@ fn update_indexes<A: Copy, F: FnMut(A) -> A>(indexes: &mut [Option<A>], mut f: F
first = Some(i); first = Some(i);
} }
*index = Some(f(i)); *index = Some(i + 1);
} }
} }
first first
} }
fn decrement_indexes(indexes: &mut [Option<usize>]) {
for index in indexes {
if let Some(i) = *index {
*index = Some(i - 1);
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum ListChange<A> { pub enum ListChange<A> {
@ -30,6 +38,11 @@ pub enum ListChange<A> {
value: A, value: A,
}, },
UpdateAt {
index: usize,
value: A,
},
RemoveAt { RemoveAt {
index: usize, index: usize,
}, },
@ -56,6 +69,7 @@ impl<A> ListChange<A> {
// TODO figure out a more efficient way of implementing this // TODO figure out a more efficient way of implementing this
ListChange::Replace { values } => ListChange::Replace { values: values.into_iter().map(callback).collect() }, ListChange::Replace { values } => ListChange::Replace { values: values.into_iter().map(callback).collect() },
ListChange::InsertAt { index, value } => ListChange::InsertAt { index, value: callback(value) }, ListChange::InsertAt { index, value } => ListChange::InsertAt { index, value: callback(value) },
ListChange::UpdateAt { index, value } => ListChange::UpdateAt { index, value: callback(value) },
ListChange::RemoveAt { index } => ListChange::RemoveAt { index }, ListChange::RemoveAt { index } => ListChange::RemoveAt { index },
ListChange::Push { value } => ListChange::Push { value: callback(value) }, ListChange::Push { value } => ListChange::Push { value: callback(value) },
ListChange::Pop {} => ListChange::Pop {}, ListChange::Pop {} => ListChange::Pop {},
@ -162,7 +176,7 @@ impl<A, B, F> SignalList for FilterMap<A, F>
ListChange::InsertAt { index, value } => { ListChange::InsertAt { index, value } => {
match (self.callback)(value) { match (self.callback)(value) {
Some(value) => { Some(value) => {
let new_index = update_indexes(&mut self.indexes[index..], |index| index + 1).unwrap_or(self.length); let new_index = increment_indexes(&mut self.indexes[index..]).unwrap_or(self.length);
self.indexes.insert(index, Some(new_index)); self.indexes.insert(index, Some(new_index));
self.length += 1; self.length += 1;
@ -176,14 +190,46 @@ impl<A, B, F> SignalList for FilterMap<A, F>
} }
}, },
ListChange::UpdateAt { index, value } => {
match (self.callback)(value) {
Some(value) => {
match self.indexes[index] {
Some(old_index) => {
Async::Ready(Some(ListChange::UpdateAt { index: old_index, value }))
},
None => {
let new_index = increment_indexes(&mut self.indexes[(index + 1)..]).unwrap_or(self.length);
self.indexes[index] = Some(new_index);
self.length += 1;
Async::Ready(Some(ListChange::InsertAt { index: new_index, value }))
},
}
},
None => {
match self.indexes[index] {
Some(old_index) => {
self.indexes[index] = None;
decrement_indexes(&mut self.indexes[(index + 1)..]);
self.length -= 1;
Async::Ready(Some(ListChange::RemoveAt { index: old_index }))
},
None => {
continue;
},
}
},
}
},
ListChange::RemoveAt { index } => { ListChange::RemoveAt { index } => {
match self.indexes.remove(index) { match self.indexes.remove(index) {
Some(old_index) => { Some(old_index) => {
for index in &mut self.indexes[index..] { decrement_indexes(&mut self.indexes[index..]);
if let Some(i) = *index { self.length -= 1;
*index = Some(i - 1);
}
}
Async::Ready(Some(ListChange::RemoveAt { index: old_index })) Async::Ready(Some(ListChange::RemoveAt { index: old_index }))
}, },
@ -209,7 +255,7 @@ impl<A, B, F> SignalList for FilterMap<A, F>
ListChange::Pop {} => { ListChange::Pop {} => {
match self.indexes.pop().expect("Cannot pop from empty vec") { match self.indexes.pop().expect("Cannot pop from empty vec") {
Some(index) => { Some(_) => {
Async::Ready(Some(ListChange::Pop {})) Async::Ready(Some(ListChange::Pop {}))
}, },
None => { None => {