1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use ;
use crateNamed;
/// Describe how to update an [InputNode](super::InputNode) value, and how
/// that mutates the internal state. Correct implementation of this trait
/// requires that any temporary state tracked is cleared up when implementing
/// [Clean](super::Clean).
///
/// # Example
///
/// It's not uncommon for a node which wraps a (potentially large) collection to
/// want to provide dependent nodes an accessor to know which of those have
/// changed since this node was last resolved. _Correct_ implementation of that
/// pattern requires implementation of [Clean](super::Clean).
///
/// ```
/// # use depends::{Clean, HashValue, Named, NodeHash, UpdateInput};
/// # use std::hash::Hasher;
/// # #[derive(Default)]
/// pub struct MyNode {
/// // Appends every item to this collection.
/// all_things: Vec<i32>,
/// // An index where the 'new' items start.
/// new_things_index: usize,
/// }
/// #
/// # impl Named for MyNode {
/// # fn name() -> &'static str { unimplemented!() }
/// # }
/// # impl HashValue for MyNode {
/// # fn hash_value(&self, _: &mut impl Hasher) -> NodeHash { unimplemented!() }
/// # }
///
/// impl UpdateInput for MyNode {
/// type Update = i32;
///
/// fn update_mut(&mut self, input: Self::Update) {
/// self.all_things.push(input)
/// }
/// }
///
/// impl MyNode {
/// // Provide a convenience for dependees to iterate only the new things.
/// pub fn just_the_new_things_thanks(&self) -> impl Iterator<Item = i32> + '_ {
/// (self.new_things_index..).map_while(|idx| self.all_things.get(idx).copied())
/// }
/// }
///
/// impl Clean for MyNode {
/// fn clean(&mut self) {
/// // Ensure nothing is yielded next time.
/// self.new_things_index = self.all_things.len();
/// }
/// }
///
/// let mut node = MyNode::default();
///
/// // Add some initial data
/// node.update_mut(5);
///
/// assert_eq!(
/// node.just_the_new_things_thanks().collect::<Vec<_>>(),
/// vec![5]
/// );
///
/// // After cleaning, any temporary state is flushed.
/// node.clean();
/// assert_eq!(
/// node.just_the_new_things_thanks().collect::<Vec<_>>(),
/// vec![]
/// );
///
/// // Only the latest values are shown.
/// node.update_mut(7);
/// node.update_mut(6);
/// assert_eq!(
/// node.just_the_new_things_thanks().collect::<Vec<_>>(),
/// vec![7, 6]
/// );
///
/// // Just to hammer home the point.
/// node.clean();
/// assert_eq!(
/// node.just_the_new_things_thanks().collect::<Vec<_>>(),
/// vec![]
/// );
/// ```
///
/// In the example above, if [Clean](super::Clean) _wasn't_ implemented, the new
/// values would be displayed to dependent nodes _after_ this node had been
/// cleaned. This is an unsound implementation, which violates the caching logic
/// of `depends`.