1use super::engine::TEMPLATE_KEY_ESCAPE;
4use super::secrets::SECRET_OPERATOR as SECRET;
5use crate::base::AuthoredPath;
6use serde_json::Value;
7
8pub fn escaped_keys(raw: &Value) -> impl Iterator<Item = AuthoredPath> + '_ {
14 let mut out = Vec::new();
15 let mut at = AuthoredPath::root();
16 walk_escaped(raw, &mut at, &mut out);
17 out.into_iter()
18}
19
20fn walk_escaped(value: &Value, at: &mut AuthoredPath, out: &mut Vec<AuthoredPath>) {
21 match value {
22 Value::Array(items) => {
23 for (i, item) in items.iter().enumerate() {
24 at.push(i);
25 walk_escaped(item, at, out);
26 at.pop();
27 }
28 }
29 Value::Object(map) => {
30 for key in map.keys() {
31 let mut chars = key.chars();
32 if chars.next() == Some(TEMPLATE_KEY_ESCAPE)
33 && chars.next() != Some(TEMPLATE_KEY_ESCAPE)
34 {
35 out.push(at.join(key.as_str()));
36 }
37 }
38 for (key, child) in map {
39 at.push(key.as_str());
40 walk_escaped(child, at, out);
41 at.pop();
42 }
43 }
44 _ => {}
45 }
46}
47
48pub fn secret_refs(raw: &Value) -> impl Iterator<Item = (Option<&str>, AuthoredPath)> + '_ {
55 let mut stack = vec![(raw, AuthoredPath::root())];
60 std::iter::from_fn(move || {
61 while let Some((value, at)) = stack.pop() {
62 match value {
63 Value::Object(map) => {
64 if map.len() == 1
65 && let Some(arg) = map.get(SECRET)
66 {
67 let literal = match arg {
68 Value::String(s) => Some(s.as_str()),
69 Value::Array(items) if items.len() == 1 => items[0].as_str(),
70 _ => None,
71 };
72 stack.push((arg, at.join(SECRET)));
73 return Some((literal, at));
74 }
75 for (key, child) in map.iter().rev() {
76 stack.push((child, at.join(key.as_str())));
77 }
78 }
79 Value::Array(items) => {
80 for (i, child) in items.iter().enumerate().rev() {
81 stack.push((child, at.join(i)));
82 }
83 }
84 _ => {}
85 }
86 }
87 None
88 })
89}
90
91pub(crate) fn reads_secret(raw: &Value) -> bool {
94 match raw {
95 Value::Object(map) => {
96 (map.len() == 1 && map.contains_key(SECRET)) || map.values().any(reads_secret)
97 }
98 Value::Array(items) => items.iter().any(reads_secret),
99 _ => false,
100 }
101}