streamkit_core/
pins.rs

1// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2//
3// SPDX-License-Identifier: MPL-2.0
4
5//! Pin system for graph validation and type checking.
6//!
7//! This module defines the pin interface used by the graph builder to validate
8//! pipeline connections before execution. Pins declare what types they accept
9//! or produce, enabling pre-flight type checking.
10//!
11//! ## Key concepts:
12//! - [`InputPin`]: Declares accepted packet types for incoming connections
13//! - [`OutputPin`]: Declares the single packet type produced
14//! - [`PinCardinality`]: Defines connection multiplicity (One, Broadcast, Dynamic)
15//! - [`PinUpdate`]: Allows nodes to update pins during initialization
16//! - [`PinManagementMessage`]: Runtime pin management for dynamic pipelines
17
18use crate::types::{Packet, PacketType};
19use schemars::JsonSchema;
20use serde::{Deserialize, Serialize};
21use ts_rs::TS;
22
23// Re-export NodeError for PinManagementMessage
24use crate::error::StreamKitError;
25
26/// Describes the connection cardinality of a pin.
27///
28/// Cardinality defines how many connections a pin can have and the semantics
29/// of those connections.
30#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, TS, PartialEq, Eq)]
31#[ts(export)]
32pub enum PinCardinality {
33    /// Exactly one connection allowed.
34    /// Used for simple one-to-one data flow.
35    One,
36
37    /// Multiple connections allowed (broadcast to all).
38    /// Only valid for output pins.
39    /// The same packet is cloned and sent to all connected destinations.
40    Broadcast,
41
42    /// Dynamic pin family - pins created on demand.
43    /// The `prefix` is used to generate pin names (e.g., "in" -> "in_0", "in_1", ...).
44    /// Typically used for input pins on nodes like mixers or routers.
45    Dynamic { prefix: String },
46}
47
48/// Describes an input pin and the packet types it can accept.
49#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, TS)]
50#[ts(export)]
51pub struct InputPin {
52    pub name: String,
53    pub accepts_types: Vec<PacketType>,
54    pub cardinality: PinCardinality,
55}
56
57/// Describes an output pin and the single packet type it produces.
58#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, TS)]
59#[ts(export)]
60pub struct OutputPin {
61    pub name: String,
62    pub produces_type: PacketType,
63    pub cardinality: PinCardinality,
64}
65
66/// Result of node initialization.
67///
68/// Nodes can update their pin definitions during initialization if they need
69/// to discover types or counts from external sources.
70pub enum PinUpdate {
71    /// Pins are unchanged from the initial definition
72    NoChange,
73    /// Pins have been updated (e.g., discovered from external source)
74    Updated { inputs: Vec<InputPin>, outputs: Vec<OutputPin> },
75}
76
77/// Dynamic pin management messages for runtime graph modifications.
78///
79/// These messages allow the engine to add/remove pins dynamically in response
80/// to connection changes in dynamic pipelines.
81#[derive(Debug)]
82pub enum PinManagementMessage {
83    /// Request to create a new input pin.
84    /// Node responds via oneshot channel with pin definition or error.
85    RequestAddInputPin {
86        suggested_name: Option<String>,
87        response_tx: tokio::sync::oneshot::Sender<Result<InputPin, StreamKitError>>,
88    },
89
90    /// Engine has created the pin and channel, node should start receiving.
91    AddedInputPin { pin: InputPin, channel: tokio::sync::mpsc::Receiver<Packet> },
92
93    /// Remove an input pin (e.g., connection deleted).
94    RemoveInputPin { pin_name: String },
95
96    /// Request to create a new output pin (less common).
97    RequestAddOutputPin {
98        suggested_name: Option<String>,
99        response_tx: tokio::sync::oneshot::Sender<Result<OutputPin, StreamKitError>>,
100    },
101
102    /// Engine has created the pin and channel, node should start sending.
103    AddedOutputPin { pin: OutputPin, channel: tokio::sync::mpsc::Sender<Packet> },
104
105    /// Remove an output pin.
106    RemoveOutputPin { pin_name: String },
107}