protoflow_blocks/
block_config.rs1use super::prelude::{Box, Cow, Named, String, Vec};
4use crate::{
5 BlockConnections, BlockInstantiation, CoreBlockConfig, FlowBlockConfig, HashBlockConfig,
6 IoBlockConfig, MathBlockConfig, SysBlockConfig, System, TextBlockConfig,
7};
8use protoflow_core::Block;
9
10pub type InputPortName = String;
11pub type OutputPortName = String;
12
13#[cfg_attr(feature = "serde", derive(serde::Serialize))]
14#[cfg_attr(feature = "serde", serde(untagged))]
15#[derive(Clone, Debug)]
16pub enum BlockConfig {
17 Core(CoreBlockConfig),
18 Flow(FlowBlockConfig),
19 #[cfg(feature = "hash")]
20 Hash(HashBlockConfig),
21 Io(IoBlockConfig),
22 Math(MathBlockConfig),
23 #[cfg(feature = "std")]
24 Sys(SysBlockConfig),
25 Text(TextBlockConfig),
26}
27
28#[cfg(feature = "serde")]
29impl<'de> serde::Deserialize<'de> for BlockConfig {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: serde::Deserializer<'de>,
33 {
34 use serde_yml::{value::TaggedValue, Value};
35 let value = TaggedValue::deserialize(deserializer)?;
36 match &value {
37 TaggedValue {
38 tag,
39 value: Value::Mapping(_mapping),
40 } => Ok(match tag.string.as_str() {
41 "Buffer" | "Const" | "Count" | "Delay" | "Drop" | "Random" => {
42 CoreBlockConfig::deserialize(value.clone())
43 .map(BlockConfig::Core)
44 .unwrap()
45 }
46
47 #[cfg(feature = "hash")]
48 "Hash" => HashBlockConfig::deserialize(value.clone())
49 .map(BlockConfig::Hash)
50 .unwrap(),
51
52 "Decode" | "Encode" | "EncodeHex" | "EncodeJSON" => {
53 IoBlockConfig::deserialize(value.clone())
54 .map(BlockConfig::Io)
55 .unwrap()
56 }
57
58 #[cfg(feature = "std")]
59 "ReadDir" | "ReadEnv" | "ReadFile" | "ReadStdin" | "WriteFile" | "WriteStderr"
60 | "WriteStdout" => SysBlockConfig::deserialize(value.clone())
61 .map(BlockConfig::Sys)
62 .unwrap(),
63
64 _ => return Err(serde::de::Error::custom("unknown Protoflow block type")),
65 }),
66
67 _ => {
68 return Err(serde::de::Error::custom(
69 "unexpected YAML element, expected a tagged mapping",
70 ))
71 }
72 }
73 }
74}
75
76impl Named for BlockConfig {
77 fn name(&self) -> Cow<str> {
78 use BlockConfig::*;
79 match self {
80 Core(config) => config.name(),
81 Flow(config) => config.name(),
82 #[cfg(feature = "hash")]
83 Hash(config) => config.name(),
84 Io(config) => config.name(),
85 Math(config) => config.name(),
86 #[cfg(feature = "std")]
87 Sys(config) => config.name(),
88 Text(config) => config.name(),
89 }
90 }
91}
92
93impl BlockConnections for BlockConfig {
94 fn output_connections(&self) -> Vec<(&'static str, Option<OutputPortName>)> {
95 use BlockConfig::*;
96 match self {
97 Core(config) => config.output_connections(),
98 Flow(config) => config.output_connections(),
99 #[cfg(feature = "hash")]
100 Hash(config) => config.output_connections(),
101 Io(config) => config.output_connections(),
102 Math(config) => config.output_connections(),
103 #[cfg(feature = "std")]
104 Sys(config) => config.output_connections(),
105 Text(config) => config.output_connections(),
106 }
107 }
108}
109
110impl BlockInstantiation for BlockConfig {
111 fn instantiate(&self, system: &mut System) -> Box<dyn Block> {
112 use BlockConfig::*;
113 match self {
114 Core(config) => config.instantiate(system),
115 Flow(config) => config.instantiate(system),
116 #[cfg(feature = "hash")]
117 Hash(config) => config.instantiate(system),
118 Io(config) => config.instantiate(system),
119 Math(config) => config.instantiate(system),
120 #[cfg(feature = "std")]
121 Sys(config) => config.instantiate(system),
122 Text(config) => config.instantiate(system),
123 }
124 }
125}