sound_flow 0.3.0

Execute graphs of functions in real time
Documentation
use crate::builder::compiler::Compilation;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::hash::Hash;

mod compiler;
mod descriptors;
mod error;

use crate::{CompiledGraph, Node};
pub use descriptors::*;
pub use error::*;

/// Builds a [CompiledGraph] from the specified nodes and connections
///
/// This basically means a topological sort so that nodes are executed after their dependencies
pub struct GraphBuilder<Id: Hash + Eq + Copy, N: Node> {
    config: N::Config,
    connections: Vec<Connection<Id>>,
    nodes: HashMap<Id, PendingInstruction<N>>,
}

#[derive(Debug)]
pub struct DuplicateId;

impl<Id: Hash + Eq + Copy, N: Node> GraphBuilder<Id, N>
where
    N::Config: Default,
{
    pub fn new() -> Self {
        Self::new_with_config(N::Config::default())
    }
}

impl<Id: Hash + Eq + Copy, N: Node> GraphBuilder<Id, N> {
    pub fn new_with_config(config: N::Config) -> Self {
        Self {
            config,
            connections: Vec::new(),
            nodes: HashMap::new(),
        }
    }

    pub fn add_node(&mut self, id: Id, node: impl Into<N>) -> Result<(), DuplicateId> {
        match self.nodes.entry(id) {
            Entry::Occupied(_) => Err(DuplicateId),
            Entry::Vacant(v) => {
                v.insert(PendingInstruction::new(node.into(), &self.config));
                Ok(())
            }
        }
    }

    pub fn add_connection(&mut self, connection: Connection<Id>) {
        self.connections.push(connection)
    }

    pub fn build(self) -> Result<CompiledGraph<Id, N>, BuildError<Id>> {
        Compilation::new(self.nodes, self.connections)?.compile()
    }
}