1use datavalue::{NumberValue, OwnedDataValue};
8use serde::de::{self, MapAccess, SeqAccess, Visitor};
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use std::collections::HashSet;
11use std::fmt;
12
13pub(crate) const ROOTS: [&str; 3] = ["data", "metadata", "temp_data"];
15
16#[derive(Clone, Debug, PartialEq)]
28pub struct Context {
29 pub(crate) root: OwnedDataValue,
30}
31
32fn slot(seed: OwnedDataValue, cap: usize) -> OwnedDataValue {
35 if seed.is_object() {
36 seed
37 } else {
38 OwnedDataValue::Object(Vec::with_capacity(cap))
39 }
40}
41
42impl Context {
43 pub(crate) fn new(data: OwnedDataValue, metadata: OwnedDataValue) -> Self {
48 Self::from_roots([
49 slot(data, 0),
50 slot(metadata, 4),
51 OwnedDataValue::Object(Vec::new()),
52 ])
53 }
54
55 pub(crate) fn from_root(root: OwnedDataValue) -> Self {
58 Self { root }
59 }
60
61 fn from_roots([data, metadata, temp_data]: [OwnedDataValue; 3]) -> Self {
66 let [d, m, t] = ROOTS;
67 Self::from_root(OwnedDataValue::Object(vec![
68 (d.to_owned(), data),
69 (m.to_owned(), metadata),
70 (t.to_owned(), temp_data),
71 ]))
72 }
73
74 fn root(&self, key: &str) -> &OwnedDataValue {
75 &self.root[key]
76 }
77
78 pub fn data(&self) -> &OwnedDataValue {
80 self.root("data")
81 }
82
83 pub fn metadata(&self) -> &OwnedDataValue {
85 self.root("metadata")
86 }
87
88 pub fn temp_data(&self) -> &OwnedDataValue {
90 self.root("temp_data")
91 }
92
93 pub fn as_value(&self) -> &OwnedDataValue {
95 &self.root
96 }
97}
98
99impl Serialize for Context {
100 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
101 self.root.serialize(s)
102 }
103}
104
105impl<'de> Deserialize<'de> for Context {
106 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
107 d.deserialize_map(Roots)
108 }
109}
110
111#[cfg(feature = "ts")]
112crate::base::ts::ts_decl!(
113 Context,
114 "Context",
115 [
116 " The context: `data`, `metadata` and `temp_data`, in that order. Each",
117 " root starts as an object; a trace's redacted root is `null`.",
118 ],
119 |_cfg| {
120 use crate::base::ts::{Prop, object};
121 object(&[
122 Prop::new("data", "JsonValue", &[" The `data` root."]),
123 Prop::new("metadata", "JsonValue", &[" The `metadata` root."]),
124 Prop::new("temp_data", "JsonValue", &[" The `temp_data` root."]),
125 ])
126 }
127);
128
129struct Roots;
131
132impl<'de> Visitor<'de> for Roots {
133 type Value = Context;
134
135 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.write_str("a context: an object holding `data`, `metadata` and `temp_data`")
137 }
138
139 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Context, A::Error> {
140 let mut values: [Option<OwnedDataValue>; 3] = [None, None, None];
141 while let Some(key) = map.next_key::<String>()? {
142 let Some(at) = ROOTS.iter().position(|root| *root == key) else {
143 return Err(de::Error::custom(format_args!(
144 "a context holds only `data`, `metadata` and `temp_data`, not `{key}`"
145 )));
146 };
147 if values[at].is_some() {
148 return Err(de::Error::duplicate_field(ROOTS[at]));
149 }
150 values[at] = Some(map.next_value::<ReadValue<false>>()?.0);
151 }
152 Ok(Context::from_roots(values.map(|value| {
153 value.unwrap_or_else(|| OwnedDataValue::Object(Vec::new()))
154 })))
155 }
156}
157
158pub(crate) fn exact<'de, D: Deserializer<'de>>(d: D) -> Result<OwnedDataValue, D::Error> {
166 d.deserialize_any(ValueVisitor::<false>)
167}
168
169pub(crate) fn in_order<'de, D: Deserializer<'de>>(d: D) -> Result<OwnedDataValue, D::Error> {
173 d.deserialize_any(ValueVisitor::<true>)
174}
175
176struct ReadValue<const DEDUP: bool>(OwnedDataValue);
178
179impl<'de, const DEDUP: bool> Deserialize<'de> for ReadValue<DEDUP> {
180 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
181 d.deserialize_any(ValueVisitor::<DEDUP>).map(Self)
182 }
183}
184
185struct ValueVisitor<const DEDUP: bool>;
189
190impl<'de, const DEDUP: bool> Visitor<'de> for ValueVisitor<DEDUP> {
191 type Value = OwnedDataValue;
192
193 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 f.write_str("any valid JSON value")
195 }
196
197 fn visit_unit<E: de::Error>(self) -> Result<OwnedDataValue, E> {
198 Ok(OwnedDataValue::Null)
199 }
200
201 fn visit_none<E: de::Error>(self) -> Result<OwnedDataValue, E> {
202 Ok(OwnedDataValue::Null)
203 }
204
205 fn visit_some<D: Deserializer<'de>>(self, d: D) -> Result<OwnedDataValue, D::Error> {
206 d.deserialize_any(Self)
207 }
208
209 fn visit_bool<E: de::Error>(self, v: bool) -> Result<OwnedDataValue, E> {
210 Ok(OwnedDataValue::Bool(v))
211 }
212
213 fn visit_i64<E: de::Error>(self, v: i64) -> Result<OwnedDataValue, E> {
214 Ok(OwnedDataValue::Number(NumberValue::Integer(v)))
215 }
216
217 fn visit_u64<E: de::Error>(self, v: u64) -> Result<OwnedDataValue, E> {
218 Ok(OwnedDataValue::Number(NumberValue::from_u64(v)))
219 }
220
221 fn visit_i128<E: de::Error>(self, v: i128) -> Result<OwnedDataValue, E> {
222 Ok(OwnedDataValue::Number(match i64::try_from(v) {
223 Ok(i) => NumberValue::Integer(i),
224 Err(_) => NumberValue::Float(v as f64),
225 }))
226 }
227
228 fn visit_u128<E: de::Error>(self, v: u128) -> Result<OwnedDataValue, E> {
229 Ok(OwnedDataValue::Number(match i64::try_from(v) {
230 Ok(i) => NumberValue::Integer(i),
231 Err(_) => NumberValue::Float(v as f64),
232 }))
233 }
234
235 fn visit_f64<E: de::Error>(self, v: f64) -> Result<OwnedDataValue, E> {
236 Ok(if v.is_finite() {
237 OwnedDataValue::Number(NumberValue::Float(v))
238 } else {
239 OwnedDataValue::Null
240 })
241 }
242
243 fn visit_str<E: de::Error>(self, v: &str) -> Result<OwnedDataValue, E> {
244 Ok(OwnedDataValue::String(v.to_owned()))
245 }
246
247 fn visit_string<E: de::Error>(self, v: String) -> Result<OwnedDataValue, E> {
248 Ok(OwnedDataValue::String(v))
249 }
250
251 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<OwnedDataValue, A::Error> {
252 let mut items = Vec::with_capacity(seq.size_hint().unwrap_or(0));
253 while let Some(ReadValue(item)) = seq.next_element::<ReadValue<DEDUP>>()? {
254 items.push(item);
255 }
256 Ok(OwnedDataValue::Array(items))
257 }
258
259 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<OwnedDataValue, A::Error> {
260 let mut pairs = Vec::with_capacity(map.size_hint().unwrap_or(0));
261 while let Some((key, ReadValue(value))) = map.next_entry::<String, ReadValue<DEDUP>>()? {
262 pairs.push((key, value));
263 }
264 if DEDUP {
265 dedup_object(&mut pairs);
266 } else if let Some(key) = repeated_key(&pairs) {
267 return Err(de::Error::custom(format_args!(
268 "an object holds the key `{key}` twice"
269 )));
270 }
271 Ok(OwnedDataValue::Object(pairs))
272 }
273}
274
275const SCAN: usize = 8;
278
279fn repeated_key(pairs: &[(String, OwnedDataValue)]) -> Option<&str> {
281 if pairs.len() <= SCAN {
282 return pairs
283 .iter()
284 .enumerate()
285 .find(|(i, (key, _))| pairs[..*i].iter().any(|(k, _)| k == key))
286 .map(|(_, (key, _))| key.as_str());
287 }
288 let mut seen = HashSet::with_capacity(pairs.len());
289 pairs
290 .iter()
291 .map(|(key, _)| key.as_str())
292 .find(|key| !seen.insert(*key))
293}
294
295fn dedup_object(pairs: &mut Vec<(String, OwnedDataValue)>) {
298 if repeated_key(pairs).is_some() {
299 fold_repeats(pairs);
300 }
301}
302
303pub(crate) fn keep_last(value: &mut OwnedDataValue) {
307 match value {
308 OwnedDataValue::Object(pairs) => {
309 dedup_object(pairs);
310 pairs.iter_mut().for_each(|(_, v)| keep_last(v));
311 }
312 OwnedDataValue::Array(items) => items.iter_mut().for_each(keep_last),
313 _ => {}
314 }
315}
316
317#[cold]
319fn fold_repeats(pairs: &mut Vec<(String, OwnedDataValue)>) {
320 let mut len = 0;
321 for i in 0..pairs.len() {
322 let (key, value) = std::mem::take(&mut pairs[i]);
323 if let Some((_, slot)) = pairs[..len].iter_mut().find(|(k, _)| *k == key) {
324 *slot = value;
325 } else {
326 pairs[len] = (key, value);
327 len += 1;
328 }
329 }
330 pairs.truncate(len);
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336 use serde_json::json;
337
338 fn text(c: &Context) -> String {
339 serde_json::to_string(c).unwrap()
340 }
341
342 #[test]
343 fn a_seed_that_is_not_an_object_is_ignored() {
344 let c = Context::new(
345 OwnedDataValue::from(&json!([1])),
346 OwnedDataValue::from(&json!({"m": 1})),
347 );
348 assert_eq!(text(&c), r#"{"data":{},"metadata":{"m":1},"temp_data":{}}"#);
349 }
350
351 #[test]
352 fn a_context_reads_what_it_writes() {
353 let wire = r#"{"data":{"b":1,"a":[null]},"metadata":null,"temp_data":"t"}"#;
354 let c: Context = serde_json::from_str(wire).unwrap();
355 assert_eq!(text(&c), wire);
356 assert_eq!(c.metadata(), &OwnedDataValue::Null);
357 assert_eq!(
358 c,
359 Context::from_root(OwnedDataValue::from(&json!({
360 "data": {"b": 1, "a": [null]}, "metadata": null, "temp_data": "t"
361 })))
362 );
363 }
364
365 #[test]
366 fn a_value_reads_back_as_written_and_as_the_json_bridge_builds_it() {
367 let wire =
368 r#"[2.0,-3.0,2.5,1e+300,7,-7,9223372036854775807,"s",true,null,{"b":[1.0],"a":{}}]"#;
369 let mut de = serde_json::Deserializer::from_str(wire);
370 let read = exact(&mut de).unwrap();
371 assert_eq!(serde_json::to_string(&read).unwrap(), wire);
372 let bridged: serde_json::Value = serde_json::from_str(wire).unwrap();
373 assert_eq!(read, OwnedDataValue::from(&bridged));
374 let collapsed: OwnedDataValue = serde_json::from_str(wire).unwrap();
376 assert!(
377 serde_json::to_string(&collapsed)
378 .unwrap()
379 .starts_with("[2,-3,2.5,")
380 );
381 let big = exact(&mut serde_json::Deserializer::from_str(
383 "18446744073709551615",
384 ))
385 .unwrap();
386 assert_eq!(big, OwnedDataValue::from(&json!(u64::MAX)));
387 }
388 #[test]
389 fn a_repeated_key_keeps_its_first_position_and_its_last_value() {
390 let fold = |text: &str| {
391 let mut value = OwnedDataValue::from_json(text).unwrap();
392 keep_last(&mut value);
393 serde_json::to_string(&value).unwrap()
394 };
395 assert_eq!(
396 fold(r#"{"a":1,"b":2,"a":3,"c":4,"b":5}"#),
397 r#"{"a":3,"b":5,"c":4}"#
398 );
399 assert_eq!(
401 fold(r#"[{"x":{"y":1,"y":2}},{"a":{"q":1},"a":{"q":2,"q":3}}]"#),
402 r#"[{"x":{"y":2}},{"a":{"q":3}}]"#
403 );
404 let wide: String = (0..12).map(|i| format!(r#""k{i}":{i},"#)).collect();
406 let wanted: String = (0..12)
407 .map(|i| format!(r#""k{i}":{},"#, if i == 3 { 99 } else { i }))
408 .collect();
409 assert_eq!(
410 fold(&format!(r#"{{{wide}"k3":99}}"#)),
411 format!("{{{}}}", wanted.trim_end_matches(','))
412 );
413 let plain = r#"{"b":1,"a":{"b":2},"c":[{"b":3}]}"#;
415 assert_eq!(fold(plain), plain);
416 }
417}