scratch_test_model/blocks/
any.rs1use crate::{
2 _exports::{AsOpcodeUnit, BlockKindError, ParseJsonBlock},
3 attrs::{DoForAttrs, DoForAttrsStrategy},
4 aux::{JsonBlocks, JsonCtx},
5 blocks::{
6 CmpBlockKind, CmpBlockKindUnit, EventBlockKind, EventBlockKindUnit, ExprBlockKind,
7 ExprBlockKindUnit, ExprOrCmpBlockKind, ExprOrCmpBlockKindUnit, StmtBlockKind,
8 StmtBlockKindUnit,
9 procedures::{ProceduresDefinition, ProceduresPrototype},
10 },
11};
12
13#[derive(Debug, derive_more::From, PartialEq, Clone)]
15pub enum BlockKind {
16 ProceduresDefinition(ProceduresDefinition),
17 ProceduresPrototype(ProceduresPrototype),
18
19 Event(EventBlockKind),
20 ExprCmp(ExprOrCmpBlockKind),
21 Stmt(StmtBlockKind),
22}
23#[derive(
25 Debug,
26 derive_more::From,
27 PartialEq,
28 Clone,
29 Copy,
30 derive_more::Display,
31 Eq,
32 PartialOrd,
33 Ord,
34 Hash,
35)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
38#[cfg_attr(feature = "serde", serde(untagged))]
39#[display("{_variant}")]
40pub enum BlockKindUnit {
41 Event(EventBlockKindUnit),
42 ExprCmp(ExprOrCmpBlockKindUnit),
43 Stmt(StmtBlockKindUnit),
44 Proc(ProcKindUnit),
45}
46
47#[cfg(feature = "utoipa")]
48impl utoipa::PartialSchema for BlockKindUnit {
49 fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
50 let inner = [
51 EventBlockKindUnit::schema(),
52 ExprBlockKindUnit::schema(),
53 CmpBlockKindUnit::schema(),
54 StmtBlockKindUnit::schema(),
55 ProcKindUnit::schema(),
56 ];
57
58 use itertools::Itertools;
59 use utoipa::openapi::RefOr;
60 use utoipa::openapi::schema::Schema;
61
62 let enum_values = inner
63 .into_iter()
64 .flat_map(|s| match s {
65 RefOr::T(Schema::Object(o)) => o.enum_values,
66 _ => panic!("unexpected schema kind"),
67 })
68 .flatten()
69 .sorted_by_key(ToString::to_string)
70 .collect_vec();
71
72 let mut object = utoipa::openapi::schema::Object::new();
73 object.enum_values = Some(enum_values);
74 object.description = Some(r#"For more information see <a href="https://marcel-scherzinger.github.io/scratch-test-model/scratch_test_model/blocks/enum.BlockKindUnit.html">BlockKindUnit</a>"#.to_string());
75
76 RefOr::T(Schema::Object(object))
77 }
78}
79#[cfg(feature = "utoipa")]
80impl utoipa::ToSchema for BlockKindUnit {
81 fn name() -> std::borrow::Cow<'static, str> {
82 "BlockKindUnit".into()
83 }
84}
85
86#[derive(
87 Debug,
88 derive_more::From,
89 PartialEq,
90 Clone,
91 Copy,
92 derive_more::Display,
93 Eq,
94 PartialOrd,
95 Ord,
96 Hash,
97)]
98#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
99#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
100#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
101pub enum ProcKindUnit {
102 #[display("procedures_prototype")]
103 #[cfg_attr(feature = "serde", serde(rename = "procedures_prototype"))]
104 ProceduresPrototype,
105 #[display("procedures_definition")]
106 #[cfg_attr(feature = "serde", serde(rename = "procedures_definition"))]
107 ProceduresDefinition,
108}
109
110impl From<ExprBlockKindUnit> for BlockKindUnit {
111 fn from(value: ExprBlockKindUnit) -> Self {
112 Self::ExprCmp(value.into())
113 }
114}
115impl From<CmpBlockKindUnit> for BlockKindUnit {
116 fn from(value: CmpBlockKindUnit) -> Self {
117 Self::ExprCmp(value.into())
118 }
119}
120impl From<ExprBlockKind> for BlockKind {
121 fn from(value: ExprBlockKind) -> Self {
122 Self::ExprCmp(value.into())
123 }
124}
125impl From<CmpBlockKind> for BlockKind {
126 fn from(value: CmpBlockKind) -> Self {
127 Self::ExprCmp(value.into())
128 }
129}
130
131impl AsOpcodeUnit for BlockKind {
132 type OpcodeUnit = BlockKindUnit;
133
134 fn opcode(&self) -> Self::OpcodeUnit {
135 match self {
136 Self::ExprCmp(ExprOrCmpBlockKind::Cmp(u)) => u.opcode().into(),
137 Self::ExprCmp(ExprOrCmpBlockKind::Expr(u)) => u.opcode().into(),
138 Self::Event(u) => u.opcode().into(),
139 Self::Stmt(u) => u.opcode().into(),
140 Self::ProceduresPrototype(_) => BlockKindUnit::Proc(ProcKindUnit::ProceduresPrototype),
141 Self::ProceduresDefinition(_) => {
142 BlockKindUnit::Proc(ProcKindUnit::ProceduresDefinition)
143 }
144 }
145 }
146}
147
148impl BlockKind {
149 pub(crate) fn from_json<'a>(
150 all_blocks: JsonBlocks<'a>,
151 id: &str,
152 ) -> Result<Self, JsonCtx<'a, BlockKindError<'a>>> {
153 use crate::aux::parse_block::ParseJsonBlock;
154
155 Ok(
156 if let Some(opt) = unknown_no_error::<EventBlockKind>(all_blocks, id)? {
157 opt.into()
158 } else if let Some(opt) = unknown_no_error::<CmpBlockKind>(all_blocks, id)? {
159 opt.into()
160 } else if let Some(opt) = unknown_no_error::<ExprBlockKind>(all_blocks, id)? {
161 opt.into()
162 } else if let Some(opt) = unknown_no_error::<ProceduresDefinition>(all_blocks, id)? {
163 opt.into()
164 } else if let Some(opt) = unknown_no_error::<ProceduresPrototype>(all_blocks, id)? {
165 opt.into()
166 } else {
167 let opt = StmtBlockKind::ctx_parse_json_block(all_blocks, id)?;
168 opt.into()
169 },
170 )
171 }
172}
173
174fn unknown_no_error<'a, T: ParseJsonBlock>(
175 all_blocks: JsonBlocks<'a>,
176 id: &str,
177) -> Result<Option<T>, JsonCtx<'a, BlockKindError<'a>>> {
178 match T::ctx_parse_json_block(all_blocks, id) {
179 Err(ctx) => {
180 let (err, json) = ctx.into_inner();
181 if let BlockKindError::UnknownOpcode(_) = err {
182 return Ok(None);
183 }
184 Err(JsonCtx {
185 inner_error: err,
186 json_ctx: json,
187 })
188 }
189 Ok(ok) => Ok(Some(ok)),
190 }
191}
192
193impl<'a, S: DoForAttrsStrategy<'a>> DoForAttrs<'a, S> for BlockKind
194where
195 ExprOrCmpBlockKind: DoForAttrs<'a, S>,
196 StmtBlockKind: DoForAttrs<'a, S>,
197 EventBlockKind: DoForAttrs<'a, S>,
198 ProceduresPrototype: DoForAttrs<'a, S>,
199 ProceduresDefinition: DoForAttrs<'a, S>,
200{
201 fn do_for_attrs(
202 &'a self,
203 inputs: &<S as DoForAttrsStrategy<'a>>::Inputs,
204 outputs: &mut <S as DoForAttrsStrategy<'a>>::Outputs,
205 ) -> Result<(), <S as DoForAttrsStrategy<'a>>::Error> {
206 match self {
207 Self::ExprCmp(b) => b.do_for_attrs(inputs, outputs),
208 Self::Stmt(b) => b.do_for_attrs(inputs, outputs),
209 Self::Event(b) => b.do_for_attrs(inputs, outputs),
210 Self::ProceduresDefinition(b) => b.do_for_attrs(inputs, outputs),
211 Self::ProceduresPrototype(b) => b.do_for_attrs(inputs, outputs),
212 }
213 }
214}