wyrd/runtime_impl/
recipe.rs1use std::string::String;
4use std::vec::Vec;
5
6use crate::authoring::{BuildError, Weave};
7use crate::foundation::{KnotKind, NumericPath, SignalDomain};
8use crate::runtime_impl::error::{RecipeError, RecipeResolveError};
9use crate::runtime_impl::{BindOpts, PortWriter, Runtime};
10
11#[cfg(feature = "schema")]
12use schemars::JsonSchema;
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15#[cfg(feature = "schema")]
16use std::borrow::ToOwned;
17
18pub trait Recipe: Sized {
23 type Ports;
25
26 fn weave() -> Result<Weave, BuildError>;
28
29 fn resolve_ports(runtime: &Runtime) -> Result<Self::Ports, RecipeResolveError>;
35
36 fn bind() -> Result<RecipeInstance<Self>, RecipeError> {
38 Self::bind_with(BindOpts::default())
39 }
40
41 fn bind_with(opts: BindOpts) -> Result<RecipeInstance<Self>, RecipeError> {
43 let runtime = Runtime::bind(Self::weave()?, opts)?;
44 let ports = Self::resolve_ports(&runtime)?;
45 Ok(RecipeInstance { runtime, ports })
46 }
47
48 fn manifest() -> Result<RecipeManifest, RecipeError> {
50 Ok(RecipeManifest::from_weave(&Self::weave()?))
51 }
52}
53
54pub struct RecipeInstance<R: Recipe> {
56 runtime: Runtime,
57 ports: R::Ports,
58}
59
60impl<R: Recipe> RecipeInstance<R> {
61 pub fn runtime(&self) -> &Runtime {
63 &self.runtime
64 }
65
66 pub fn runtime_mut(&mut self) -> &mut Runtime {
68 &mut self.runtime
69 }
70
71 pub fn ports(&self) -> &R::Ports {
73 &self.ports
74 }
75
76 pub(crate) fn port_writer_with_ports(&mut self) -> (&R::Ports, PortWriter<'_>) {
81 let Self { runtime, ports } = self;
82 (ports, runtime.port_writer())
83 }
84
85 pub fn into_parts(self) -> (Runtime, R::Ports) {
87 (self.runtime, self.ports)
88 }
89}
90
91#[derive(Clone, Debug, PartialEq, Eq)]
93#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
94#[cfg_attr(feature = "schema", derive(JsonSchema))]
95pub struct RecipeManifest {
96 pub weave_id: String,
98 pub numeric: NumericPath,
100 pub signal_inputs: Vec<SignalInManifest>,
102 pub signal_outputs: Vec<SignalOutManifest>,
104 pub emit_commands: Vec<EmitCommandManifest>,
106}
107
108impl RecipeManifest {
109 pub fn from_weave(weave: &Weave) -> Self {
111 let mut signal_inputs = Vec::new();
112 let mut signal_outputs = Vec::new();
113 let mut emit_commands = Vec::new();
114
115 for knot in weave.knots() {
116 match &knot.kind {
117 KnotKind::SignalIn { domain } => signal_inputs.push(SignalInManifest {
118 knot: knot.id.clone(),
119 domain: *domain,
120 }),
121 KnotKind::SignalOut { path, domain } => signal_outputs.push(SignalOutManifest {
122 knot: knot.id.clone(),
123 path: path.clone(),
124 domain: *domain,
125 }),
126 KnotKind::EmitCommand { name } => emit_commands.push(EmitCommandManifest {
127 knot: knot.id.clone(),
128 name: name.clone(),
129 }),
130 _ => {}
131 }
132 }
133
134 signal_inputs.sort_by(|left, right| left.knot.cmp(&right.knot));
135 signal_outputs.sort_by(|left, right| {
136 left.path
137 .cmp(&right.path)
138 .then_with(|| left.knot.cmp(&right.knot))
139 });
140 emit_commands.sort_by(|left, right| {
141 left.name
142 .cmp(&right.name)
143 .then_with(|| left.knot.cmp(&right.knot))
144 });
145
146 Self {
147 weave_id: String::from(weave.id()),
148 numeric: weave.numeric(),
149 signal_inputs,
150 signal_outputs,
151 emit_commands,
152 }
153 }
154}
155
156#[derive(Clone, Debug, PartialEq, Eq)]
158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
159#[cfg_attr(feature = "schema", derive(JsonSchema))]
160pub struct SignalInManifest {
161 pub knot: String,
163 pub domain: SignalDomain,
165}
166
167#[derive(Clone, Debug, PartialEq, Eq)]
169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
170#[cfg_attr(feature = "schema", derive(JsonSchema))]
171pub struct SignalOutManifest {
172 pub knot: String,
174 pub path: String,
176 pub domain: SignalDomain,
178}
179
180#[derive(Clone, Debug, PartialEq, Eq)]
182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
183#[cfg_attr(feature = "schema", derive(JsonSchema))]
184pub struct EmitCommandManifest {
185 pub knot: String,
187 pub name: String,
189}