use crate::node_pin::{PinDirection, PinEnd};
pub fn direction_ok<N, P, UI>(from: PinEnd<'_, N, P, UI>, to: PinEnd<'_, N, P, UI>) -> bool {
matches!(
(from.direction(), to.direction()),
(PinDirection::Both, _)
| (_, PinDirection::Both)
| (PinDirection::Output, PinDirection::Input)
| (PinDirection::Input, PinDirection::Output)
)
}
pub fn not_same_node<N, P, UI>(from: PinEnd<'_, N, P, UI>, to: PinEnd<'_, N, P, UI>) -> bool
where
N: PartialEq,
{
from.node_id() != to.node_id()
}
pub fn input_not_occupied<N, P, UI>(to: PinEnd<'_, N, P, UI>) -> bool {
!(matches!(to.direction(), PinDirection::Input) && to.is_occupied())
}
pub fn default_can_connect<N, P, UI>(from: PinEnd<'_, N, P, UI>, to: PinEnd<'_, N, P, UI>) -> bool
where
N: PartialEq,
{
direction_ok(from, to) && not_same_node(from, to) && input_not_occupied(to)
}
#[cfg(test)]
mod tests {
use super::*;
fn pin(
node: &'static usize,
dir: PinDirection,
occupied: bool,
) -> PinEnd<'static, usize, usize> {
PinEnd::new(node, &0, dir, &(), occupied)
}
#[test]
fn direction_ok_matches_output_input_and_both() {
let out = pin(&0, PinDirection::Output, false);
let inp = pin(&1, PinDirection::Input, false);
let both = pin(&2, PinDirection::Both, false);
assert!(direction_ok(out, inp));
assert!(direction_ok(inp, out));
assert!(direction_ok(out, both));
assert!(!direction_ok(out, out)); assert!(!direction_ok(inp, inp)); }
#[test]
fn not_same_node_rejects_self_wiring() {
let a = pin(&0, PinDirection::Output, false);
let b = pin(&0, PinDirection::Input, false);
let c = pin(&1, PinDirection::Input, false);
assert!(!not_same_node(a, b));
assert!(not_same_node(a, c));
}
#[test]
fn input_not_occupied_only_limits_inputs() {
let busy_in = pin(&0, PinDirection::Input, true);
let free_in = pin(&0, PinDirection::Input, false);
let busy_out = pin(&0, PinDirection::Output, true);
let busy_both = pin(&0, PinDirection::Both, true);
assert!(!input_not_occupied(busy_in));
assert!(input_not_occupied(free_in));
assert!(input_not_occupied(busy_out)); assert!(input_not_occupied(busy_both)); }
#[test]
fn default_bundles_all_three() {
let out = pin(&0, PinDirection::Output, false);
let free_in = pin(&1, PinDirection::Input, false);
let busy_in = pin(&1, PinDirection::Input, true);
let same_node_in = pin(&0, PinDirection::Input, false);
assert!(default_can_connect(out, free_in));
assert!(!default_can_connect(out, busy_in)); assert!(!default_can_connect(out, same_node_in)); }
}