1#![allow(clippy::module_name_repetitions)]
2use std::convert::AsRef;
3
4use crate::path::OwnedTargetPath;
5use crate::path::PathPrefix;
6use crate::value::{Secrets, Value};
7
8pub trait Target: std::fmt::Debug + SecretTarget {
10 fn target_insert(&mut self, path: &OwnedTargetPath, value: Value) -> Result<(), String>;
39
40 fn target_get(&self, path: &OwnedTargetPath) -> Result<Option<&Value>, String>;
47
48 fn target_get_mut(&mut self, path: &OwnedTargetPath) -> Result<Option<&mut Value>, String>;
57
58 fn target_remove(
69 &mut self,
70 path: &OwnedTargetPath,
71 compact: bool,
72 ) -> Result<Option<Value>, String>;
73}
74
75pub trait SecretTarget {
77 fn get_secret(&self, key: &str) -> Option<&str>;
85
86 fn insert_secret(&mut self, key: &str, value: &str);
92
93 fn remove_secret(&mut self, key: &str);
98}
99
100#[derive(Debug)]
101pub struct TargetValueRef<'a> {
102 pub value: &'a mut Value,
103 pub metadata: &'a mut Value,
104 pub secrets: &'a mut Secrets,
105}
106
107impl Target for TargetValueRef<'_> {
108 fn target_insert(&mut self, target_path: &OwnedTargetPath, value: Value) -> Result<(), String> {
109 match target_path.prefix {
110 PathPrefix::Event => self.value.insert(&target_path.path, value),
111 PathPrefix::Metadata => self.metadata.insert(&target_path.path, value),
112 };
113 Ok(())
114 }
115
116 fn target_get(&self, target_path: &OwnedTargetPath) -> Result<Option<&Value>, String> {
117 let value = match target_path.prefix {
118 PathPrefix::Event => self.value.get(&target_path.path),
119 PathPrefix::Metadata => self.metadata.get(&target_path.path),
120 };
121 Ok(value)
122 }
123
124 fn target_get_mut(
125 &mut self,
126 target_path: &OwnedTargetPath,
127 ) -> Result<Option<&mut Value>, String> {
128 let value = match target_path.prefix {
129 PathPrefix::Event => self.value.get_mut(&target_path.path),
130 PathPrefix::Metadata => self.metadata.get_mut(&target_path.path),
131 };
132 Ok(value)
133 }
134
135 fn target_remove(
136 &mut self,
137 target_path: &OwnedTargetPath,
138 compact: bool,
139 ) -> Result<Option<Value>, String> {
140 let prev_value = match target_path.prefix {
141 PathPrefix::Event => self.value.remove(&target_path.path, compact),
142 PathPrefix::Metadata => self.metadata.remove(&target_path.path, compact),
143 };
144 Ok(prev_value)
145 }
146}
147
148impl SecretTarget for TargetValueRef<'_> {
149 fn get_secret(&self, key: &str) -> Option<&str> {
150 self.secrets.get_secret(key)
151 }
152
153 fn insert_secret(&mut self, key: &str, value: &str) {
154 self.secrets.insert_secret(key, value);
155 }
156
157 fn remove_secret(&mut self, key: &str) {
158 self.secrets.remove_secret(key);
159 }
160}
161
162#[derive(Debug)]
163pub struct TargetValue {
164 pub value: Value,
165 pub metadata: Value,
166 pub secrets: Secrets,
167}
168
169impl Target for TargetValue {
170 fn target_insert(&mut self, target_path: &OwnedTargetPath, value: Value) -> Result<(), String> {
171 match target_path.prefix {
172 PathPrefix::Event => self.value.insert(&target_path.path, value),
173 PathPrefix::Metadata => self.metadata.insert(&target_path.path, value),
174 };
175 Ok(())
176 }
177
178 fn target_get(&self, target_path: &OwnedTargetPath) -> Result<Option<&Value>, String> {
179 let value = match target_path.prefix {
180 PathPrefix::Event => self.value.get(&target_path.path),
181 PathPrefix::Metadata => self.metadata.get(&target_path.path),
182 };
183 Ok(value)
184 }
185
186 fn target_get_mut(
187 &mut self,
188 target_path: &OwnedTargetPath,
189 ) -> Result<Option<&mut Value>, String> {
190 let value = match target_path.prefix {
191 PathPrefix::Event => self.value.get_mut(&target_path.path),
192 PathPrefix::Metadata => self.metadata.get_mut(&target_path.path),
193 };
194 Ok(value)
195 }
196
197 fn target_remove(
198 &mut self,
199 target_path: &OwnedTargetPath,
200 compact: bool,
201 ) -> Result<Option<Value>, String> {
202 let prev_value = match target_path.prefix {
203 PathPrefix::Event => self.value.remove(&target_path.path, compact),
204 PathPrefix::Metadata => self.metadata.remove(&target_path.path, compact),
205 };
206 Ok(prev_value)
207 }
208}
209
210impl SecretTarget for TargetValue {
211 fn get_secret(&self, key: &str) -> Option<&str> {
212 self.secrets.get_secret(key)
213 }
214
215 fn insert_secret(&mut self, key: &str, value: &str) {
216 self.secrets.insert_secret(key, value);
217 }
218
219 fn remove_secret(&mut self, key: &str) {
220 self.secrets.remove_secret(key);
221 }
222}
223
224impl SecretTarget for Secrets {
225 fn get_secret(&self, key: &str) -> Option<&str> {
226 self.get(key).map(AsRef::as_ref)
227 }
228
229 fn insert_secret(&mut self, key: &str, value: &str) {
230 self.insert(key, value);
231 }
232
233 fn remove_secret(&mut self, key: &str) {
234 self.remove(key);
235 }
236}
237
238#[cfg(any(test, feature = "test"))]
239mod value_target_impl {
240 use super::{SecretTarget, Target, Value};
241 use crate::path::{OwnedTargetPath, PathPrefix};
242
243 impl Target for Value {
244 fn target_insert(
245 &mut self,
246 target_path: &OwnedTargetPath,
247 value: Value,
248 ) -> Result<(), String> {
249 match target_path.prefix {
250 PathPrefix::Event => self.insert(&target_path.path, value),
251 PathPrefix::Metadata => panic!("Value has no metadata. Use `TargetValue` instead."),
252 };
253 Ok(())
254 }
255
256 fn target_get(&self, target_path: &OwnedTargetPath) -> Result<Option<&Value>, String> {
257 match target_path.prefix {
258 PathPrefix::Event => Ok(self.get(&target_path.path)),
259 PathPrefix::Metadata => panic!("Value has no metadata. Use `TargetValue` instead."),
260 }
261 }
262
263 fn target_get_mut(
264 &mut self,
265 target_path: &OwnedTargetPath,
266 ) -> Result<Option<&mut Value>, String> {
267 match target_path.prefix {
268 PathPrefix::Event => Ok(self.get_mut(&target_path.path)),
269 PathPrefix::Metadata => panic!("Value has no metadata. Use `TargetValue` instead."),
270 }
271 }
272
273 fn target_remove(
274 &mut self,
275 target_path: &OwnedTargetPath,
276 compact: bool,
277 ) -> Result<Option<Value>, String> {
278 match target_path.prefix {
279 PathPrefix::Event => Ok(self.remove(&target_path.path, compact)),
280 PathPrefix::Metadata => panic!("Value has no metadata. Use `TargetValue` instead."),
281 }
282 }
283 }
284
285 impl SecretTarget for Value {
286 fn get_secret(&self, _key: &str) -> Option<&str> {
287 panic!("Value has no secrets. Use `TargetValue` instead.")
288 }
289
290 fn insert_secret(&mut self, _key: &str, _value: &str) {
291 panic!("Value has no secrets. Use `TargetValue` instead.")
292 }
293
294 fn remove_secret(&mut self, _key: &str) {
295 panic!("Value has no secrets. Use `TargetValue` instead.")
296 }
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 #![allow(clippy::print_stdout)] use crate::{
305 compiler::{TypeDef, parser::Ident, state::LocalEnv, type_def::Details},
306 owned_value_path,
307 };
308
309 use super::*;
310 use crate::value;
311
312 #[test]
313 fn get() {
314 let cases = vec![
315 (value!(true), owned_value_path!(), Ok(Some(value!(true)))),
316 (value!(true), owned_value_path!("foo"), Ok(None)),
317 (value!({}), owned_value_path!(), Ok(Some(value!({})))),
318 (
319 value!({foo: "bar"}),
320 owned_value_path!(),
321 Ok(Some(value!({foo: "bar"}))),
322 ),
323 (
324 value!({foo: "bar"}),
325 owned_value_path!("foo"),
326 Ok(Some(value!("bar"))),
327 ),
328 (value!({foo: "bar"}), owned_value_path!("bar"), Ok(None)),
329 (
330 value!([1, 2, 3, 4, 5]),
331 owned_value_path!(1),
332 Ok(Some(value!(2))),
333 ),
334 (
335 value!({foo: [{bar: true}]}),
336 owned_value_path!("foo", 0, "bar"),
337 Ok(Some(value!(true))),
338 ),
339 ];
340
341 for (value, path, expect) in cases {
342 let value: Value = value;
343 let target = TargetValue {
344 value,
345 metadata: value!({}),
346 secrets: Secrets::new(),
347 };
348 let path = OwnedTargetPath::event(path);
349
350 assert_eq!(
351 target.target_get(&path).map(Option::<&Value>::cloned),
352 expect
353 );
354 }
355 }
356
357 #[test]
358 #[allow(clippy::too_many_lines)]
359 fn insert() {
360 let cases = vec![
361 (
362 value!({foo: "bar"}),
363 owned_value_path!(),
364 value!({baz: "qux"}),
365 value!({baz: "qux"}),
366 Ok(()),
367 ),
368 (
369 value!({foo: "bar"}),
370 owned_value_path!("baz"),
371 true.into(),
372 value!({foo: "bar", baz: true}),
373 Ok(()),
374 ),
375 (
376 value!({foo: [{bar: "baz"}]}),
377 owned_value_path!("foo", 0, "baz"),
378 true.into(),
379 value!({foo: [{bar: "baz", baz: true}]}),
380 Ok(()),
381 ),
382 (
383 value!({foo: {bar: "baz"}}),
384 owned_value_path!("bar", "baz"),
385 true.into(),
386 value!({foo: {bar: "baz"}, bar: {baz: true}}),
387 Ok(()),
388 ),
389 (
390 value!({foo: "bar"}),
391 owned_value_path!("foo"),
392 "baz".into(),
393 value!({foo: "baz"}),
394 Ok(()),
395 ),
396 (
397 value!({foo: "bar"}),
398 owned_value_path!("foo", 2, "bar baz", "a", "b"),
399 true.into(),
400 value!({foo: [null, null, {"bar baz": {"a": {"b": true}}}]}),
401 Ok(()),
402 ),
403 (
404 value!({foo: [0, 1, 2]}),
405 owned_value_path!("foo", 5),
406 "baz".into(),
407 value!({foo: [0, 1, 2, null, null, "baz"]}),
408 Ok(()),
409 ),
410 (
411 value!({foo: "bar"}),
412 owned_value_path!("foo", 0),
413 "baz".into(),
414 value!({foo: ["baz"]}),
415 Ok(()),
416 ),
417 (
418 value!({foo: []}),
419 owned_value_path!("foo", 0),
420 "baz".into(),
421 value!({foo: ["baz"]}),
422 Ok(()),
423 ),
424 (
425 value!({foo: [0]}),
426 owned_value_path!("foo", 0),
427 "baz".into(),
428 value!({foo: ["baz"]}),
429 Ok(()),
430 ),
431 (
432 value!({foo: [0, 1]}),
433 owned_value_path!("foo", 0),
434 "baz".into(),
435 value!({foo: ["baz", 1]}),
436 Ok(()),
437 ),
438 (
439 value!({foo: [0, 1]}),
440 owned_value_path!("foo", 1),
441 "baz".into(),
442 value!({foo: [0, "baz"]}),
443 Ok(()),
444 ),
445 ];
446
447 for (target, path, value, expect, result) in cases {
448 let mut target = TargetValue {
449 value: target,
450 metadata: value!({}),
451 secrets: Secrets::new(),
452 };
453 let path = OwnedTargetPath::event(path);
454
455 assert_eq!(
456 Target::target_insert(&mut target, &path, value.clone()),
457 result
458 );
459 assert_eq!(target.value, expect);
460 assert_eq!(
461 Target::target_get(&target, &path).map(Option::<&Value>::cloned),
462 Ok(Some(value))
463 );
464 }
465 }
466
467 #[test]
468 fn remove() {
469 let cases = vec![
470 (
471 value!({foo: "bar"}),
472 owned_value_path!("baz"),
473 false,
474 None,
475 Some(value!({foo: "bar"})),
476 ),
477 (
478 value!({foo: "bar"}),
479 owned_value_path!("foo"),
480 false,
481 Some(value!("bar")),
482 Some(value!({})),
483 ),
484 (
485 value!({foo: "bar", baz: "qux"}),
486 owned_value_path!(),
487 false,
488 Some(value!({foo: "bar", baz: "qux"})),
489 Some(value!({})),
490 ),
491 (
492 value!({foo: "bar", baz: "qux"}),
493 owned_value_path!(),
494 true,
495 Some(value!({foo: "bar", baz: "qux"})),
496 Some(value!({})),
497 ),
498 (
499 value!({foo: [0]}),
500 owned_value_path!("foo", 0),
501 false,
502 Some(value!(0)),
503 Some(value!({foo: []})),
504 ),
505 (
506 value!({foo: [0]}),
507 owned_value_path!("foo", 0),
508 true,
509 Some(value!(0)),
510 Some(value!({})),
511 ),
512 (
513 value!({foo: {"bar baz": [0]}, bar: "baz"}),
514 owned_value_path!("foo", "bar baz", 0),
515 false,
516 Some(value!(0)),
517 Some(value!({foo: {"bar baz": []}, bar: "baz"})),
518 ),
519 (
520 value!({foo: {"bar baz": [0]}, bar: "baz"}),
521 owned_value_path!("foo", "bar baz", 0),
522 true,
523 Some(value!(0)),
524 Some(value!({bar: "baz"})),
525 ),
526 ];
527
528 for (target, path, compact, value, expect) in cases {
529 let path = OwnedTargetPath::event(path);
530
531 let mut target = TargetValue {
532 value: target,
533 metadata: value!({}),
534 secrets: Secrets::new(),
535 };
536 assert_eq!(
537 Target::target_remove(&mut target, &path, compact),
538 Ok(value)
539 );
540 assert_eq!(
541 Target::target_get(&target, &OwnedTargetPath::event_root())
542 .map(Option::<&Value>::cloned),
543 Ok(expect)
544 );
545 }
546 }
547
548 #[test]
549 fn merge_multiple_local_env() {
550 let mut a = LocalEnv::default();
551 a.insert_variable(
552 Ident("foo".into()),
553 Details {
554 type_def: TypeDef::any(),
555 value: None,
556 },
557 );
558
559 let mut b = LocalEnv::default();
560 b.insert_variable(
561 Ident("bar".into()),
562 Details {
563 type_def: TypeDef::any(),
564 value: None,
565 },
566 );
567
568 let merged = a.merge(b);
569 assert_eq!(merged.bindings.len(), 2);
570 }
571}