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}