wasmflow_interface/
signatures.rs

1use std::error::Error;
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5
6use crate::maps::{ComponentMap, FieldMap, TypeMap};
7/// The signature of a Wasmflow component, including its input and output types.
8#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
9#[must_use]
10pub struct ComponentSignature {
11  /// The name of the component.
12  #[serde(default)]
13  pub name: String,
14  /// The component's inputs.
15  #[serde(default)]
16  pub inputs: FieldMap,
17  /// The component's outputs.
18  #[serde(default)]
19  pub outputs: FieldMap,
20}
21
22impl ComponentSignature {
23  /// Create a new [ComponentSignature] with the passed name.
24  pub fn new<T: AsRef<str>>(name: T) -> Self {
25    Self {
26      name: name.as_ref().to_owned(),
27      ..Default::default()
28    }
29  }
30
31  /// Add an input port.
32  pub fn add_input(mut self, name: impl AsRef<str>, input_type: TypeSignature) -> Self {
33    self.inputs.insert(name, input_type);
34    self
35  }
36
37  /// Add an input port.
38  pub fn add_output(mut self, name: impl AsRef<str>, input_type: TypeSignature) -> Self {
39    self.outputs.insert(name, input_type);
40    self
41  }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, serde_repr::Deserialize_repr, serde_repr::Serialize_repr)]
45#[must_use]
46#[repr(u32)]
47/// The umbrella version of the collection.
48pub enum CollectionVersion {
49  /// Version 0 Wasmflow collections.
50  V0 = 0,
51}
52
53impl Default for CollectionVersion {
54  fn default() -> Self {
55    Self::V0
56  }
57}
58
59impl From<CollectionVersion> for u32 {
60  fn from(v: CollectionVersion) -> Self {
61    match v {
62      CollectionVersion::V0 => 0,
63    }
64  }
65}
66
67#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Copy)]
68#[must_use]
69/// The Wasmflow features this collection supports.
70pub struct CollectionFeatures {
71  /// Whether or not this collection's components accept streaming input or produce streaming output.
72  pub streaming: bool,
73  /// Whether or not this collection has a persistent state or context.
74  pub stateful: bool,
75  /// The version of this component.
76  pub version: CollectionVersion,
77}
78
79impl CollectionFeatures {
80  /// Quickly create a v0 feature set.
81  pub fn v0(stateful: bool, streaming: bool) -> Self {
82    Self {
83      streaming,
84      stateful,
85      version: CollectionVersion::V0,
86    }
87  }
88}
89
90/// Signature for Collections.
91#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
92#[must_use]
93pub struct CollectionSignature {
94  /// Name of the collection.
95  pub name: Option<String>,
96  /// Component implementation version.
97  pub features: CollectionFeatures,
98  /// Schema format version.
99  pub format: u32,
100  /// Version of the schema.
101  pub version: String,
102  /// A map of type signatures referenced elsewhere.
103  #[serde(default, skip_serializing_if = "Vec::is_empty")]
104  pub wellknown: Vec<WellKnownSchema>,
105  /// A map of type signatures referenced elsewhere.
106  #[serde(default, skip_serializing_if = "TypeMap::is_empty")]
107  pub types: TypeMap,
108  /// A list of [ComponentSignature]s in this collection.
109  pub components: ComponentMap,
110  /// The component's configuration for this implementation.
111  #[serde(default, skip_serializing_if = "TypeMap::is_empty")]
112  pub config: TypeMap,
113}
114
115impl CollectionSignature {
116  /// Create a new [CollectionSignature] with the passed name.
117  pub fn new<T: AsRef<str>>(name: T) -> Self {
118    Self {
119      name: Some(name.as_ref().to_owned()),
120      ..Default::default()
121    }
122  }
123
124  #[must_use]
125  /// Get the [CollectionSignature] for the requested component.
126  pub fn get_component(&self, field: &str) -> Option<&ComponentSignature> {
127    self.components.get(field)
128  }
129
130  /// Add a [ComponentSignature] to the collection.
131  pub fn add_component(mut self, signature: ComponentSignature) -> Self {
132    self.components.insert(signature.name.clone(), signature);
133    self
134  }
135
136  /// Set the version of the [CollectionSignature].
137  pub fn version(mut self, version: impl AsRef<str>) -> Self {
138    self.version = version.as_ref().to_owned();
139    self
140  }
141
142  /// Set the format of the [CollectionSignature].
143  pub fn format(mut self, format: u32) -> Self {
144    self.format = format;
145    self
146  }
147
148  /// Set the features of the [CollectionSignature].
149  pub fn features(mut self, features: CollectionFeatures) -> Self {
150    self.features = features;
151    self
152  }
153}
154
155/// An entry from a well-known schema
156#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
157pub struct WellKnownSchema {
158  /// The capability the schema provides.
159  pub capabilities: Vec<String>,
160  /// The location where you can find and validate the schema.
161  pub url: String,
162  /// The schema itself.
163  pub schema: CollectionSignature,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
167#[must_use]
168/// A valid type definition.
169#[serde(tag = "type")]
170pub enum TypeDefinition {
171  /// A struct definition.
172  #[serde(rename = "struct")]
173  Struct(StructSignature),
174  /// An enum definition.
175  #[serde(rename = "enum")]
176  Enum(EnumSignature),
177}
178
179/// Signatures of enum type definitions.
180#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
181#[must_use]
182pub struct EnumSignature {
183  /// The name of the enum.
184  pub name: String,
185  /// The variants in the enum.
186  #[serde(default, skip_serializing_if = "Vec::is_empty")]
187  pub values: Vec<EnumVariant>,
188}
189
190impl EnumSignature {
191  /// Constructor for [EnumSignature]
192  pub fn new<T: AsRef<str>>(name: T, values: Vec<EnumVariant>) -> Self {
193    Self {
194      name: name.as_ref().to_owned(),
195      values,
196    }
197  }
198}
199
200#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
201#[must_use]
202/// An enum variant definition
203pub struct EnumVariant {
204  /// The name of the variant.
205  pub name: String,
206  /// The index of the variant.
207  pub index: u32,
208}
209
210impl EnumVariant {
211  /// Constructor for [EnumVariant]
212  pub fn new<T: AsRef<str>>(name: T, index: u32) -> Self {
213    Self {
214      name: name.as_ref().to_owned(),
215      index,
216    }
217  }
218}
219
220/// Signatures of struct-like type definitions.
221#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
222#[must_use]
223pub struct StructSignature {
224  /// The name of the struct.
225  pub name: String,
226  /// The fields in this struct.
227  pub fields: FieldMap,
228}
229
230impl StructSignature {
231  /// Constructor for [StructSignature]
232  pub fn new<T: AsRef<str>>(name: T, fields: FieldMap) -> Self {
233    Self {
234      name: name.as_ref().to_owned(),
235      fields,
236    }
237  }
238}
239
240/// An enum representing the types of components that can be hosted.
241#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
242#[must_use]
243pub enum HostedType {
244  /// A collection.
245  Collection(CollectionSignature),
246}
247
248impl HostedType {
249  /// Get the name of the [HostedType] regardless of kind.
250  #[must_use]
251  pub fn get_name(&self) -> &Option<String> {
252    match self {
253      HostedType::Collection(s) => &s.name,
254    }
255  }
256}
257
258#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
259#[serde(tag = "type")]
260#[serde(rename_all = "lowercase")]
261#[must_use]
262/// Enum of valid types.
263pub enum TypeSignature {
264  /// I8 type.
265  I8,
266  /// I16 type.
267  I16,
268  /// I32 type.
269  I32,
270  /// I64 type.
271  I64,
272  /// u8 type.
273  U8,
274  /// u16 type.
275  U16,
276  /// u32 type.
277  U32,
278  /// u64 type.
279  U64,
280  /// f32 type.
281  F32,
282  /// f64 type.
283  F64,
284  /// Boolean type.
285  Bool,
286  /// String type.
287  String,
288  /// Date type.
289  Datetime,
290  /// Raw bytes.
291  Bytes,
292  /// Any valid value.
293  Value,
294  /// An internal type.
295  Internal(InternalType),
296  /// A reference to another type.
297  Ref {
298    #[serde(rename = "ref")]
299    /// The reference string
300    reference: String,
301  },
302  /// A list type
303  List {
304    /// The type of the list's elements
305    element: Box<TypeSignature>,
306  },
307  /// A type representing an optional value.
308  Optional {
309    /// The actual type that is optional.
310    option: Box<TypeSignature>,
311  },
312  /// A HashMap-like type.
313  Map {
314    /// The type of the map's keys.
315    key: Box<TypeSignature>,
316    /// The type of the map's values.
317    value: Box<TypeSignature>,
318  },
319  /// A type representing a link to another collection.
320  Link {
321    /// The schemas that must be provided with the linked collection.
322    #[serde(default)]
323    schemas: Vec<String>,
324  },
325  /// A JSON-like key/value map.
326  Struct,
327}
328#[derive(Debug)]
329/// Error returned when attempting to convert an invalid source into a Wasmflow type.
330pub struct ParseError(String);
331impl Error for ParseError {}
332impl std::fmt::Display for ParseError {
333  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
334    write!(f, "Could not parse {} into a TypeSignature.", self.0)
335  }
336}
337
338impl FromStr for TypeSignature {
339  type Err = ParseError;
340
341  fn from_str(s: &str) -> Result<Self, Self::Err> {
342    let t = match s {
343      "i8" => Self::I8,
344      "i16" => Self::I16,
345      "i32" => Self::I32,
346      "i64" => Self::I64,
347      "u8" => Self::U8,
348      "u16" => Self::U16,
349      "u32" => Self::U32,
350      "u64" => Self::U64,
351      "f32" => Self::F32,
352      "f64" => Self::F64,
353      "bool" => Self::Bool,
354      "bytes" => Self::Bytes,
355      "value" => Self::Value,
356      "string" => Self::String,
357      "datetime" => Self::Datetime,
358      _ => return Err(ParseError(s.to_owned())),
359    };
360    Ok(t)
361  }
362}
363
364/// Internal types for use within the Wasmflow runtime
365#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
366#[serde(tag = "id")]
367pub enum InternalType {
368  /// Represents a complete set of component inputs
369  #[serde(rename = "__input__")]
370  ComponentInput,
371}
372
373impl FromStr for InternalType {
374  type Err = ParseError;
375
376  fn from_str(s: &str) -> Result<Self, Self::Err> {
377    let t = match s {
378      "component_input" => Self::ComponentInput,
379      _ => return Err(ParseError(s.to_owned())),
380    };
381    Ok(t)
382  }
383}