protoflow_blocks/
block_config.rs

1// This is free and unencumbered software released into the public domain.
2
3use 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}