Skip to content

Commit 4c3bac9

Browse files
committed
wip
1 parent c2ce422 commit 4c3bac9

3 files changed

Lines changed: 64 additions & 3 deletions

File tree

anathema-state/src/value/list.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,33 @@ impl<T: State> Value<List<T>> {
107107
});
108108
}
109109

110+
/// Return all values matching the predicate.
111+
///
112+
/// Note that unlike `Vec::extract_if`, this will allocate a vector for the result
113+
pub fn extract_if<F>(&mut self, mut f: F) -> Vec<Value<T>>
114+
where
115+
F: FnMut(&Value<T>) -> bool,
116+
{
117+
let key = self.key;
118+
self.with_mut(|List { inner: list, .. }| {
119+
let mut extraction = vec![];
120+
121+
let mut del = 0;
122+
123+
for i in 0..list.len() {
124+
let index = i - del;
125+
if f(&list[index]) {
126+
let value = list.remove(index).expect("value is present");
127+
extraction.push(value);
128+
changed(key, Change::Removed(index as u32));
129+
del += 1;
130+
}
131+
}
132+
133+
extraction
134+
})
135+
}
136+
110137
/// Get a reference to a value
111138
pub fn get<'a>(&'a self, index: usize) -> Option<Shared<'a, T>> {
112139
let list = &*self.to_ref();
@@ -361,6 +388,26 @@ mod test {
361388
assert!(matches!(changes.remove(0), (_, Change::Removed(1))));
362389
}
363390

391+
#[test]
392+
fn notify_extract_if() {
393+
let mut list = Value::new(List::<u32>::empty());
394+
list.push_back(1);
395+
list.push_back(2);
396+
list.push_back(3);
397+
list.push_back(4);
398+
399+
list.reference().subscribe(Subscriber::ZERO);
400+
401+
let result = list.extract_if(|val| *val.to_ref() % 2 == 0);
402+
403+
let mut changes = drain_changes();
404+
assert!(matches!(changes.remove(0), (_, Change::Removed(2))));
405+
assert!(matches!(changes.remove(0), (_, Change::Removed(1))));
406+
407+
assert_eq!(*result[0].to_ref(), 2);
408+
assert_eq!(*result[1].to_ref(), 4);
409+
}
410+
364411
#[test]
365412
fn notify_pop_back() {
366413
let mut list = Value::new(List::<u32>::empty());

anathema-state/src/value/maybe.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ impl<T: State + TypeId> Value<Maybe<T>> {
141141
#[cfg(test)]
142142
mod test {
143143
use super::*;
144+
use crate::store::testing::drain_changes;
145+
use crate::{Change, Subscriber};
144146

145147
#[test]
146148
fn nullable_int() {
@@ -155,4 +157,13 @@ mod test {
155157
let one = value.and_then_ref(|inner_map| inner_map.map_ref(|m| *m)).unwrap();
156158
assert_eq!(one, 1);
157159
}
160+
161+
#[test]
162+
fn changing_value() {
163+
let mut value = Value::new(Maybe::<u32>::none());
164+
value.reference().subscribe(Subscriber::ZERO);
165+
value.to_mut().update(Some(1));
166+
let mut changes = drain_changes();
167+
assert!(matches!(changes.remove(0), (_, Change::Changed)));
168+
}
158169
}

anathema-value-resolver/src/expression.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ fn resolve_pending<'bp>(val: PendingValue, ctx: &mut ValueResolutionContext<'_,
349349
let maybe = or_null!(state.as_maybe());
350350
// If there is no value, subscribe to the `Maybe`
351351
let inner = match maybe.get() {
352-
Some(inner) => inner,
352+
Some(inner) => {
353+
ctx.maybe_subscribe(&val);
354+
inner
355+
}
353356
None => {
354357
ctx.maybe_subscribe(&val);
355358
return ValueExpr::Null;
@@ -377,11 +380,11 @@ fn resolve_index<'bp>(
377380
let val = map.lookup(&key);
378381

379382
let val = match val {
380-
Some(key) => {
383+
Some(val) => {
381384
if ctx.is_partially_resolved() {
382385
value.unsubscribe(ctx.sub);
383386
}
384-
key
387+
val
385388
}
386389
None => {
387390
ctx.partially_resolved(value);

0 commit comments

Comments
 (0)