drogue_client/registry/v1/data/app/
process.rs1use crate::{dialect, registry::v1::ExternalEndpoint, serde::is_default};
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(rename_all = "camelCase")]
6pub struct PublishSpec {
7 #[serde(default)]
8 #[serde(skip_serializing_if = "Vec::is_empty")]
9 pub rules: Vec<Rule>,
10}
11
12dialect!(PublishSpec[crate::Section::Spec => "publish"]);
13
14#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct CommandSpec {
17 #[serde(default)]
18 #[serde(skip_serializing_if = "Vec::is_empty")]
19 pub rules: Vec<Rule>,
20}
21
22dialect!(CommandSpec[crate::Section::Spec => "command"]);
23
24#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct Rule {
27 #[serde(default)]
28 pub when: When,
29 #[serde(default)]
30 pub then: Vec<Step>,
31}
32
33#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub enum When {
36 Always,
37 IsChannel(String),
38 Not(Box<When>),
39 And(Vec<When>),
40 Or(Vec<When>),
41}
42
43impl Default for When {
44 fn default() -> Self {
45 Self::Always
46 }
47}
48
49#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub enum Step {
52 Drop,
54 Reject(String),
56 Break,
58 SetAttribute { name: String, value: String },
60 RemoveAttribute(String),
62 SetExtension { name: String, value: String },
64 RemoveExtension(String),
66 Validate(ValidateSpec),
68 Enrich(EnrichSpec),
70}
71
72#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
73#[serde(rename_all = "camelCase")]
74pub struct EnrichSpec {
75 #[serde(default)]
76 #[serde(skip_serializing_if = "is_default")]
77 pub request: RequestType,
78 #[serde(default)]
79 #[serde(skip_serializing_if = "is_default")]
80 pub response: ResponseType,
81 pub endpoint: ExternalEndpoint,
82}
83
84#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
85#[serde(rename_all = "camelCase")]
86pub struct ValidateSpec {
87 #[serde(default)]
88 #[serde(skip_serializing_if = "is_default")]
89 pub request: RequestType,
90 pub endpoint: ExternalEndpoint,
91}
92
93#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95#[serde(tag = "type")]
96pub enum RequestType {
97 CloudEvent {
99 #[serde(default)]
100 #[serde(skip_serializing_if = "is_default")]
101 mode: ContentMode,
102 },
103}
104
105impl Default for RequestType {
106 fn default() -> Self {
107 Self::CloudEvent {
108 mode: Default::default(),
109 }
110 }
111}
112
113#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub enum ContentMode {
116 Binary,
117 Structured,
118}
119
120impl Default for ContentMode {
121 fn default() -> Self {
122 Self::Binary
123 }
124}
125
126#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
127#[serde(rename_all = "camelCase")]
128#[serde(tag = "type")]
129pub enum ResponseType {
130 CloudEvent,
132 Raw,
134 AssumeStructuredCloudEvent,
136}
137
138impl Default for ResponseType {
139 fn default() -> Self {
140 Self::CloudEvent
141 }
142}
143
144#[cfg(test)]
145mod test {
146
147 use super::*;
148 use serde_json::json;
149
150 #[test]
151 fn default_empty() {
152 let spec: PublishSpec = serde_json::from_value(json!({})).unwrap();
153 assert_eq!(PublishSpec::default(), spec);
154 }
155
156 #[test]
157 fn example1() {
158 let spec: PublishSpec = serde_json::from_value(json!({
159 "rules":[
160 {
161 "when": {
162 "and": [
163 { "isChannel": "chan1" },
164 { "not": {
165 "or" : [
166 { "isChannel": "chan2" },
167 { "isChannel": "chan3" },
168 ],
169 } },
170 ]
171 },
172 "then": [
173 {
174 "setExtension": {
175 "name": "ext1",
176 "value": "value1",
177 },
178 },
179 {
180 "removeExtension": "ext2",
181 },
182 ],
183 }
184 ]
185 }))
186 .unwrap();
187 assert_eq!(
188 PublishSpec {
189 rules: vec![Rule {
190 when: When::And(vec![
191 When::IsChannel("chan1".to_string()),
192 When::Not(Box::new(When::Or(vec![
193 When::IsChannel("chan2".to_string()),
194 When::IsChannel("chan3".to_string()),
195 ])))
196 ]),
197 then: vec![
198 Step::SetExtension {
199 name: "ext1".to_string(),
200 value: "value1".to_string()
201 },
202 Step::RemoveExtension("ext2".to_string()),
203 ],
204 }],
205 },
206 spec
207 );
208 }
209
210 #[test]
211 fn test_deser_1() {
212 assert_eq!(
213 EnrichSpec {
214 request: Default::default(),
215 response: Default::default(),
216 endpoint: ExternalEndpoint {
217 method: None,
218 url: "http://localhost:1234".to_string(),
219 tls: None,
220 auth: Default::default(),
221 headers: vec![],
222 timeout: None
223 }
224 },
225 serde_json::from_value(json!({
226 "request": {
227 "type": "cloudEvent",
228 },
229 "response": {
230 "type": "cloudEvent",
231 },
232 "endpoint": {
233 "url": "http://localhost:1234"
234 }
235 }))
236 .unwrap()
237 );
238 }
239
240 #[test]
241 fn test_deser_2() {
242 assert_eq!(
243 EnrichSpec {
244 request: RequestType::CloudEvent {
245 mode: ContentMode::Structured
246 },
247 response: Default::default(),
248 endpoint: ExternalEndpoint {
249 method: None,
250 url: "http://localhost:1234".to_string(),
251 tls: None,
252 auth: Default::default(),
253 headers: vec![],
254 timeout: None
255 }
256 },
257 serde_json::from_value(json!({
258 "request": {
259 "type": "cloudEvent",
260 "mode": "structured",
261 },
262 "response": {
263 "type": "cloudEvent",
264 },
265 "endpoint": {
266 "url": "http://localhost:1234"
267 }
268 }))
269 .unwrap()
270 );
271 }
272
273 #[test]
274 fn test_deser_32() {
275 let spec: PublishSpec = serde_json::from_value(json!({
276 "rules":[
277 {
278 "when": {
279 "not": "always",
280 },
281 "then": [],
282 }
283 ]
284 }))
285 .unwrap();
286 assert_eq!(
287 PublishSpec {
288 rules: vec![Rule {
289 when: When::Not(Box::new(When::Always)),
290 then: vec![],
291 }],
292 },
293 spec
294 );
295 }
296}