41
41
//! Ok(finalize(dependency_graph_so_far))
42
42
//! }
43
43
//! }
44
+ //!
45
+ //! fn activate(&mut dependency_graph: _, &mut unresolved_dependencies: _, candidate:_) -> Result<(), Problem> {
46
+ //! // check that we can use candidate given the other selected packages
47
+ //! if semver conflict { return Err(Problem::Semver); };
48
+ //! if links conflict { return Err(Problem::Links); };
49
+ //! ...
50
+ //! // update other state
51
+ //! if used a [replace] section { update that lookup table };
52
+ //! if used a [patch] section { update that lookup table };
53
+ //! update activated features
54
+ //! ...
55
+ //! // add candidate to dependency_graph
56
+ //! dependency_graph.add_edge(candidate.parent, candidate.id, candidate.dependency);
57
+ //! // add candidate's dependencies to the list to be resolved
58
+ //! unresolved_dependencies.extend(candidate.dependencies);
59
+ //! Ok(())
60
+ //! }
44
61
//! ```
45
62
//!
46
- //! The real resolver is not recursive to avoid blowing the stack, and has lots of other state to
47
- //! maintain. The most expensive (non recursive) call in this algorithm is the
48
- //! `dependency_graph_so_far.clone();`. To make this more annoying the first thing we try will
49
- //! probably work, and any work we do to prepare for the next iteration is wasted. If we had a
50
- //! `undo_activate` we could be much more efficient, completely remove the `.clone()` and just
51
- //! `undo_activate` if things tern out to not work. Unfortunately, making sure `undo_activate`
52
- //! handles all the corner cases correctly is not practical for the resolver. However, this is
53
- //! possible for a graph like thing, a `clone` means record the size of the graph. a `&mut self`
54
- //! method means undo everything newer and do the mutation, a `&self` method means only look at the
55
- //! older part. This module provides a `StackGraph` type to encapsulate this pattern.
63
+ //! The real resolver is not recursive to avoid blowing the stack. The most expensive
64
+ //! (non recursive) call in this algorithm is the `dependency_graph_so_far.clone();`.
65
+ //! To make this more annoying the first thing we try will probably work, and any work we do to
66
+ //! prepare for the next iteration is wasted. If we had a `undo_activate` we could be much more efficient,
67
+ //! completely remove the `.clone()` and just `undo_activate` if things tern out to not work.
68
+ //! Unfortunately, making sure `undo_activate` handles all the corner cases correctly is not
69
+ //! practical for the resolver. However, this is possible for a graph like thing, a `clone` means
70
+ //! record the size of the graph. a `&mut self` method means undo everything newer and do the
71
+ //! mutation, a `&self` method means only look at the older part. This module provides a
72
+ //! `StackGraph` type to encapsulate this pattern.
56
73
57
74
use indexmap:: IndexMap ;
58
75
use std:: borrow:: Borrow ;
@@ -64,6 +81,10 @@ use std::rc::Rc;
64
81
65
82
type EdgeIndex = usize ;
66
83
84
+ /// This stores one Edge or Link element. If the two Nodes have data to connect them then we say it
85
+ /// is an Edge and the `value` is `Some(E)`, if the two Nodes did not have data then we say it is a
86
+ /// Link and the `value` is `None`. If there are other `EdgeLink`s associated with the same two Nodes,
87
+ /// then we make a index based doubly linked list using the `next` and `previous` fields.
67
88
#[ derive( Clone , Debug ) ]
68
89
struct EdgeLink < E : Clone > {
69
90
value : Option < E > ,
@@ -79,11 +100,13 @@ struct EdgeLink<E: Clone> {
79
100
/// that efficiently undoes the most reason modifications.
80
101
#[ derive( Clone ) ]
81
102
pub struct Graph < N : Clone , E : Clone > {
82
- /// an index based linked list of the edge data for links. This maintains insertion order.
103
+ /// An index based linked list of the edge data. This maintains insertion order.
104
+ /// If the connection has data associated with it then that Edge is stored here.
105
+ /// If the connection has no data associated with it then that Link is represented with a dummy here.
83
106
edges : Vec < EdgeLink < E > > ,
84
- /// a hashmap that stores the set of nodes. This is an `IndexMap` so it maintains insertion order .
85
- /// For each node it stores all the other nodes that it links to .
86
- /// For each link it stores the first index into `edges` .
107
+ /// A map from a "from" node to (a map of "to" node to the starting index in the `edges`) .
108
+ /// The inner map may be empty to represent a Node that was `add` but not connected to anything .
109
+ /// The maps are `IndexMap`s so they maintains insertion order .
87
110
nodes : indexmap:: IndexMap < N , indexmap:: IndexMap < N , EdgeIndex > > ,
88
111
}
89
112
@@ -402,7 +425,7 @@ impl<N: Eq + Hash + Clone, E: Eq + Clone> Eq for Graph<N, E> {}
402
425
/// - the clone has no overhead to read the `Graph` as it was
403
426
/// - no overhead over using the `Graph` directly when modifying the biggest clone
404
427
/// Is this too good to be true?
405
- /// - If a modification (`&mut` method) is done to a smaller older clone then a full `O(N)`
428
+ /// - If a modification (`&mut` method) is done to a clone that is not the largest then a full `O(N)`
406
429
/// deep clone will happen internally.
407
430
pub struct StackGraph < N : Clone , E : Clone > {
408
431
/// The `Graph` shared by all clones, this `StackGraph` refers to only the prefix of size `age`
0 commit comments