saddle_core/
context_json.rs1use serde::{Serialize, Serializer, ser::{SerializeMap, SerializeSeq}};
4
5pub enum JsonKind<'a> {
6 Null,
7 Bool(bool),
8 String(&'a str),
9 Number(&'a str),
10 Array,
11 Object,
12}
13
14pub trait ContextJson {
18 fn kind(&self, index: usize) -> JsonKind<'_>;
19 fn child(&self, parent: usize, after: Option<usize>) -> Option<(Option<&str>, usize)>;
20}
21
22pub trait ContextSource: Send + Sync {
25 fn release(self: std::sync::Arc<Self>) { drop(self); }
28 fn with_tree(&self, visitor: &mut dyn FnMut(JsonSubtree<'_>));
29 fn secret_paths(&self) -> &[String] { &[] }
31 fn with_tree_and_secrets(&self, visitor: &mut dyn FnMut(JsonSubtree<'_>, &[String])) {
35 self.with_tree(&mut |tree| visitor(tree, self.secret_paths()));
36 }
37 fn with_secrets(&self, visitor: &mut dyn FnMut(&[String])) { visitor(self.secret_paths()); }
38}
39
40pub struct ContextSourceRef(Option<std::sync::Arc<dyn ContextSource>>);
42impl ContextSourceRef {
43 pub fn new<T: ContextSource + 'static>(source: std::sync::Arc<T>) -> Self { Self(Some(source)) }
44}
45impl From<std::sync::Arc<dyn ContextSource>> for ContextSourceRef {
46 fn from(source: std::sync::Arc<dyn ContextSource>) -> Self { Self(Some(source)) }
47}
48impl<T: ContextSource + 'static> From<std::sync::Arc<T>> for ContextSourceRef {
49 fn from(source: std::sync::Arc<T>) -> Self { Self::new(source) }
50}
51impl AsRef<dyn ContextSource> for ContextSourceRef {
52 fn as_ref(&self) -> &(dyn ContextSource + 'static) { self.0.as_deref().expect("live source") }
53}
54impl Clone for ContextSourceRef {
55 fn clone(&self) -> Self { Self(self.0.clone()) }
56}
57impl std::ops::Deref for ContextSourceRef {
58 type Target = dyn ContextSource;
59 fn deref(&self) -> &Self::Target { self.0.as_deref().expect("live source") }
60}
61impl Drop for ContextSourceRef {
62 fn drop(&mut self) { if let Some(source) = self.0.take() { source.release(); } }
63}
64
65#[derive(Clone, Copy)]
66pub struct JsonSubtree<'a> {
67 owner: &'a dyn ContextJson,
68 index: usize,
69}
70impl<'a> JsonSubtree<'a> {
71 pub fn same_node(self, other: Self) -> bool {
72 std::ptr::eq(self.owner, other.owner) && self.index == other.index
73 }
74 pub fn new(owner: &'a dyn ContextJson, index: usize) -> Self { Self { owner, index } }
75 pub fn kind(self) -> JsonKind<'a> { self.owner.kind(self.index) }
76 pub fn children(self) -> impl Iterator<Item = (Option<&'a str>, Self)> {
77 let mut previous = None;
78 std::iter::from_fn(move || {
79 let (key, index) = self.owner.child(self.index, previous)?;
80 previous = Some(index);
81 Some((key, Self::new(self.owner, index)))
82 })
83 }
84 pub fn pointer(self, path: &str) -> Result<Option<Self>, crate::json_pointer::InvalidJsonPointer> {
85 let mut current = self;
86 for segment in crate::json_pointer::JsonPointer::parse(path)?.segments() {
87 let next = match current.kind() {
88 JsonKind::Object => current.children()
89 .find(|(key, _)| key.is_some_and(|key| segment.matches(key))).map(|(_, child)| child),
90 JsonKind::Array => segment.array_index()
91 .and_then(|index| current.children().nth(index)).map(|(_, child)| child),
92 _ => None,
93 };
94 let Some(next) = next else { return Ok(None); };
95 current = next;
96 }
97 Ok(Some(current))
98 }
99}
100impl Serialize for JsonSubtree<'_> {
101 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
102 match self.kind() {
103 JsonKind::Null => serializer.serialize_none(),
104 JsonKind::Bool(value) => serializer.serialize_bool(value),
105 JsonKind::String(value) => serializer.serialize_str(value),
106 JsonKind::Number(value) => {
107 let raw: &serde_json::value::RawValue = serde_json::from_str(value)
108 .map_err(serde::ser::Error::custom)?;
109 raw.serialize(serializer)
110 }
111 JsonKind::Array => {
112 let mut seq = serializer.serialize_seq(None)?;
113 for (_, child) in self.children() { seq.serialize_element(&child)?; }
114 seq.end()
115 }
116 JsonKind::Object => {
117 let mut map = serializer.serialize_map(None)?;
118 for (key, child) in self.children() {
119 map.serialize_entry(key.ok_or_else(|| serde::ser::Error::custom("object key absent"))?, &child)?;
120 }
121 map.end()
122 }
123 }
124 }
125}
126
127pub struct RedactedSubtree<'a> {
129 root: JsonSubtree<'a>,
130 node: JsonSubtree<'a>,
131 paths: &'a [String],
132 prefix: &'a str,
133 masked: bool,
134}
135impl<'a> RedactedSubtree<'a> {
136 pub fn new(root: JsonSubtree<'a>, paths: &'a [String], prefix: &'a str) -> Self {
137 Self { root, node: root, paths, prefix, masked: false }
138 }
139 pub fn pointer(&self, path: &str) -> Result<Option<Self>, crate::json_pointer::InvalidJsonPointer> {
142 let pointer = crate::json_pointer::JsonPointer::parse(path)?;
143 let is_secret = |node: JsonSubtree<'a>| self.paths.iter().any(|secret| {
144 secret.strip_prefix(self.prefix).and_then(|path| self.root.pointer(path).ok().flatten())
145 .is_some_and(|target| target.same_node(node))
146 });
147 let mut node = self.node;
148 let mut masked = self.masked || is_secret(node);
149 for segment in pointer.segments() {
150 let next = match node.kind() {
151 JsonKind::Object => node.children().find(|(key, _)| key.is_some_and(|key| segment.matches(key))).map(|(_, child)| child),
152 JsonKind::Array => segment.array_index().and_then(|index| node.children().nth(index)).map(|(_, child)| child),
153 _ => None,
154 };
155 let Some(next) = next else { return Ok(None); };
156 node = next;
157 masked |= is_secret(node);
158 }
159 Ok(Some(Self { node, masked, ..*self }))
160 }
161 fn child(&self, node: JsonSubtree<'a>) -> Self { Self { node, ..*self } }
162}
163impl Serialize for RedactedSubtree<'_> {
164 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
165 let secret = self.paths.iter().any(|path| {
166 path.strip_prefix(self.prefix).and_then(|path| self.root.pointer(path).ok().flatten())
167 .is_some_and(|target| target.same_node(self.node))
168 });
169 if self.masked || secret { return s.serialize_str("<redacted>"); }
170 match self.node.kind() {
171 JsonKind::Object => {
172 let mut map = s.serialize_map(None)?;
173 for (key, child) in self.node.children() {
174 map.serialize_entry(key.ok_or_else(|| serde::ser::Error::custom("object key absent"))?, &self.child(child))?;
175 }
176 map.end()
177 }
178 JsonKind::Array => {
179 let mut seq = s.serialize_seq(None)?;
180 for (_, child) in self.node.children() { seq.serialize_element(&self.child(child))?; }
181 seq.end()
182 }
183 _ => self.node.serialize(s),
184 }
185 }
186}