diff --git a/Cargo.toml b/Cargo.toml index 63bffd0..b117559 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ name = "dsp" path = "./src/lib.rs" [dependencies] -daggy = "0.4.0" +daggy = { git = "https://github.com/mitchmindtree/daggy", rev = "bcb36c7b", features = ["stable_dag"] } sample = "0.10.0" [dev-dependencies] diff --git a/examples/synth.rs b/examples/synth.rs index 56d6be3..7ffba8f 100644 --- a/examples/synth.rs +++ b/examples/synth.rs @@ -61,7 +61,7 @@ fn main() -> Result<(), pa::Error> { // Traverse inputs or outputs of a node with the following pattern. let mut inputs = graph.inputs(synth); - while let Some(input_idx) = inputs.next_node(&graph) { + while let Some((_, input_idx)) = inputs.walk_next(&graph) { if let DspNode::Oscillator(_, ref mut pitch, _) = graph[input_idx] { // Pitch down our oscillators for fun. *pitch -= 0.1; diff --git a/src/graph.rs b/src/graph.rs index 73bad6b..2ca2961 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -8,30 +8,34 @@ //! The `Graph` type requires that its nodes implement the [`Node`](../node/trait.Node.html) trait. use crate::node::Node; -use daggy::{self, Walker}; +use daggy::{stabledag, petgraph::{self, visit::{IntoNodeReferences, IntoEdgeReferences}}}; use sample::{self, Frame, Sample}; +// Daggy/petgraph re-exports +pub use stabledag::Walker; +pub use petgraph::visit::EdgeRef; + /// An alias for our Graph's Node Index. -pub type NodeIndex = daggy::NodeIndex; +pub type NodeIndex = stabledag::NodeIndex; /// An alias for our Graph's Edge Index. -pub type EdgeIndex = daggy::EdgeIndex; +pub type EdgeIndex = stabledag::EdgeIndex; -/// An alias for the iterator yielding mutable access to all node weights. -pub type NodesMut<'a, N> = daggy::NodeWeightsMut<'a, N, usize>; +/// An alias for our Graph's Node Indices. +pub type NodeReferences<'a, N> = petgraph::stable_graph::NodeReferences<'a, N, usize>; +/// An alias for our Graph's Edge Indices. +pub type EdgeReferences<'a, N> = petgraph::stable_graph::EdgeReferences<'a, N, usize>; -/// Read only access to a **Graph**'s internal node array. -pub type RawNodes<'a, N> = daggy::RawNodes<'a, N, usize>; -/// Read only access to a **Graph**'s internal edge array. -pub type RawEdges<'a, F> = daggy::RawEdges<'a, Connection, usize>; +/// An alias for the iterator yielding mutable access to all node weights. +pub type NodesMut<'a, N> = stabledag::NodeWeightsMut<'a, N, usize>; /// An iterator yielding indices to recently added connections. -pub type EdgeIndices = daggy::EdgeIndices; +pub type EdgeIndices = stabledag::EdgeIndices; /// An alias for the **Dag** used within our **Graph**. -pub type Dag = daggy::Dag, usize>; +pub type Dag = stabledag::StableDag, usize>; /// An alias for the **PetGraph** used by our **Graph**'s internal **Dag**. -pub type PetGraph = daggy::PetGraph, usize>; +pub type PetGraph = petgraph::stable_graph::StableDiGraph, usize>; /// A directed, acyclic DSP graph. /// @@ -104,12 +108,12 @@ pub struct WouldCycle; /// A walker object for walking over nodes that are inputs to some node. pub struct Inputs { - parents: daggy::Parents, usize>, + parents: stabledag::Parents, usize>, } /// A walker object for walking over nodes that are outputs to some node. pub struct Outputs { - children: daggy::Children, usize>, + children: stabledag::Children, usize>, } /// A walker type for walking over a **Graph**'s nodes in the order in which they will visited when @@ -135,7 +139,7 @@ where /// rough idea of the number of nodes, connections and frames per buffer upon the **Graph**'s /// instantiation. pub fn new() -> Self { - let dag = daggy::Dag::new(); + let dag = Dag::new(); Graph { dag: dag, visit_order: Vec::new(), @@ -152,7 +156,7 @@ where /// for mixing the dry and wet signals when `Node::audio_requested` is called. pub fn with_capacity(nodes: usize, connections: usize, frames_per_buffer: usize) -> Self { Graph { - dag: daggy::Dag::with_capacity(nodes, connections), + dag: Dag::with_capacity(nodes, connections), visit_order: Vec::with_capacity(nodes), dry_buffer: Vec::with_capacity(frames_per_buffer), maybe_master: None, @@ -234,16 +238,14 @@ where self.dag.node_weight_mut(node) } - /// Read only access to the internal node array. - pub fn raw_nodes(&self) -> RawNodes { - self.dag.raw_nodes() + /// An iterator over the graph's nodes. + pub fn node_references(&self) -> NodeReferences { + self.dag.node_references() } - /// An iterator yielding mutable access to all nodes. - /// - /// The order in which nodes are yielded matches the order of their indices. - pub fn nodes_mut(&mut self) -> NodesMut { - self.dag.node_weights_mut() + /// An iterator over the graph's edges. + pub fn edge_references(&self) -> EdgeReferences> { + self.dag.edge_references() } /// A reference to the connection at the given index (or `None` if it doesn't exist). @@ -251,9 +253,9 @@ where self.dag.edge_weight(edge) } - /// Read only access to the internal edge array. - pub fn raw_edges(&self) -> RawEdges { - self.dag.raw_edges() + /// A mutable reference to the connection at the given index (or `None` if it doesn't exist) + fn connection_mut(&mut self, edge: EdgeIndex) -> Option<&mut Connection> { + self.dag.edge_weight_mut(edge) } /// Index the **Graph** by two `NodeIndex`s at once. @@ -480,7 +482,7 @@ where pub fn remove_all_input_connections(&mut self, idx: NodeIndex) -> usize { let mut inputs = self.inputs(idx); let mut num = 0; - while let Some(connection) = inputs.next_edge(&self) { + while let Some((connection, _)) = inputs.walk_next(&self) { self.remove_edge(connection); num += 1; } @@ -493,7 +495,7 @@ where pub fn remove_all_output_connections(&mut self, idx: NodeIndex) -> usize { let mut outputs = self.outputs(idx); let mut num = 0; - while let Some(connection) = outputs.next_edge(&self) { + while let Some((connection, _)) = outputs.walk_next(&self) { self.remove_edge(connection); num += 1; } @@ -509,8 +511,8 @@ where let mut num_removed = 0; for i in 0..self.dag.node_count() { let idx = NodeIndex::new(i); - let num_inputs = self.inputs(idx).count(self); - let num_outputs = self.outputs(idx).count(self); + let num_inputs = self.inputs(idx).iter(self).count(); + let num_outputs = self.outputs(idx).iter(self).count(); if num_inputs == 0 && num_outputs == 0 { if self.maybe_master == Some(idx) { self.maybe_master = None; @@ -535,7 +537,9 @@ where resize_buffer_to(&mut self.dry_buffer, buffer_size); // Initialise all connection buffers. - for connection in self.dag.edge_weights_mut() { + let edge_ids = self.edge_references().map(|e| e.id()).collect::>(); + for edge_id in edge_ids { + let connection = self.connection_mut(edge_id).unwrap(); resize_buffer_to(&mut connection.buffer, buffer_size); } } @@ -566,7 +570,7 @@ where // Walk over each of the input connections to sum their buffers to the output. let mut inputs = self.inputs(node_idx); - while let Some(connection_idx) = inputs.next_edge(self) { + while let Some((connection_idx, _)) = inputs.walk_next(self) { let connection = &self[connection_idx]; // Sum the connection's buffer onto the output. // @@ -621,7 +625,7 @@ where // Walk over each of the outgoing connections and write the rendered output to them. let mut outputs = self.outputs(node_idx); - while let Some(connection_idx) = outputs.next_edge(self) { + while let Some((connection_idx, _)) = outputs.walk_next(self) { let connection = &mut self.dag[connection_idx]; // Ensure the buffer matches the target length. @@ -646,7 +650,8 @@ where /// /// The user should never have to worry about this, thus the method is private. fn prepare_visit_order(&mut self) { - self.visit_order = daggy::petgraph::algo::toposort(self.dag.graph()); + self.visit_order = petgraph::algo::toposort(self.dag.graph(), None) + .expect("A cycle was found in the DAG while toposorting"); } } @@ -686,7 +691,7 @@ where // use the first node that has no output connections. let mut visit_order_rev = self.visit_order_rev(); while let Some(node) = visit_order_rev.next(self) { - if self.inputs(node).count(self) == 0 { + if self.inputs(node).iter(self).count() == 0 { self.audio_requested_from(node, output, sample_hz); return; } @@ -696,47 +701,23 @@ where } } -impl Walker> for Inputs { - type Index = usize; +impl Walker<&Graph> for Inputs { + type Item = (EdgeIndex, NodeIndex); /// The next (connection, node) input pair to some node in our walk for the given **Graph**. #[inline] - fn next(&mut self, graph: &Graph) -> Option<(EdgeIndex, NodeIndex)> { - self.parents.next(&graph.dag) - } - - /// The next input connection to some node in our walk for the given **Graph**. - #[inline] - fn next_edge(&mut self, graph: &Graph) -> Option { - self.parents.next_edge(&graph.dag) - } - - /// The next input node to some node in our walk for the given **Graph**. - #[inline] - fn next_node(&mut self, graph: &Graph) -> Option { - self.parents.next_node(&graph.dag) + fn walk_next(&mut self, graph: &Graph) -> Option<(EdgeIndex, NodeIndex)> { + self.parents.walk_next(&graph.dag) } } -impl Walker> for Outputs { - type Index = usize; +impl Walker<&Graph> for Outputs { + type Item = (EdgeIndex, NodeIndex); /// The next (connection, node) output pair from some node in our walk for the given **Graph**. #[inline] - fn next(&mut self, graph: &Graph) -> Option<(EdgeIndex, NodeIndex)> { - self.children.next(&graph.dag) - } - - /// The next output connection from some node in our walk for the given **Graph**. - #[inline] - fn next_edge(&mut self, graph: &Graph) -> Option { - self.children.next_edge(&graph.dag) - } - - /// The next output node from some node in our walk for the given **Graph**. - #[inline] - fn next_node(&mut self, graph: &Graph) -> Option { - self.children.next_node(&graph.dag) + fn walk_next(&mut self, graph: &Graph) -> Option<(EdgeIndex, NodeIndex)> { + self.children.walk_next(&graph.dag) } } diff --git a/src/lib.rs b/src/lib.rs index a27fc03..23fd0a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,10 +12,10 @@ #![forbid(unsafe_code)] #![deny(missing_docs)] -pub use daggy::{self, Walker}; +pub use daggy::stabledag; pub use graph::{ - Connection, Dag, EdgeIndex, Graph, Inputs, NodeIndex, NodesMut, Outputs, PetGraph, RawEdges, - RawNodes, VisitOrder, VisitOrderReverse, WouldCycle, + Connection, Dag, EdgeIndex, EdgeRef, Graph, Inputs, NodeIndex, NodesMut, Outputs, PetGraph, + VisitOrder, VisitOrderReverse, WouldCycle, Walker, }; pub use node::Node; pub use sample::{