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 #[must_use = "the data root is taken and left empty"]
110 pub fn take_data(&mut self) -> OwnedDataValue {
111 let OwnedDataValue::Object(entries) = &mut self.root else {
112 return OwnedDataValue::Object(Vec::new());
113 };
114 let Some((_, data)) = entries.iter_mut().find(|(key, _)| key.as_str() == "data") else {
115 return OwnedDataValue::Object(Vec::new());
116 };
117 std::mem::replace(data, OwnedDataValue::Object(Vec::new()))
118 }
119}
120
121impl Serialize for Context {
122 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
123 self.root.serialize(s)
124 }
125}
126
127impl<'de> Deserialize<'de> for Context {
128 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
129 d.deserialize_map(Roots)
130 }
131}
132
133#[cfg(feature = "ts")]
134crate::base::ts::ts_decl!(
135 Context,
136 "Context",
137 [
138 " The context: `data`, `metadata` and `temp_data`, in that order. Each",
139 " root starts as an object; a trace's redacted root is `null`.",
140 ],
141 |_cfg| {
142 use crate::base::ts::{Prop, object};
143 object(&[
144 Prop::new("data", "JsonValue", &[" The `data` root."]),
145 Prop::new("metadata", "JsonValue", &[" The `metadata` root."]),
146 Prop::new("temp_data", "JsonValue", &[" The `temp_data` root."]),
147 ])
148 }
149);
150
151struct Roots;
153
154impl<'de> Visitor<'de> for Roots {
155 type Value = Context;
156
157 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 f.write_str("a context: an object holding `data`, `metadata` and `temp_data`")
159 }
160
161 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Context, A::Error> {
162 let mut values: [Option<OwnedDataValue>; 3] = [None, None, None];
163 while let Some(key) = map.next_key::<String>()? {
164 let Some(at) = ROOTS.iter().position(|root| *root == key) else {
165 return Err(de::Error::custom(format_args!(
166 "a context holds only `data`, `metadata` and `temp_data`, not `{key}`"
167 )));
168 };
169 if values[at].is_some() {
170 return Err(de::Error::duplicate_field(ROOTS[at]));
171 }
172 values[at] = Some(map.next_value::<ReadValue<false>>()?.0);
173 }
174 Ok(Context::from_roots(values.map(|value| {
175 value.unwrap_or_else(|| OwnedDataValue::Object(Vec::new()))
176 })))
177 }
178}
179
180pub(crate) fn exact<'de, D: Deserializer<'de>>(d: D) -> Result<OwnedDataValue, D::Error> {
188 d.deserialize_any(ValueVisitor::<false>)
189}
190
191pub(crate) fn in_order<'de, D: Deserializer<'de>>(d: D) -> Result<OwnedDataValue, D::Error> {
195 d.deserialize_any(ValueVisitor::<true>)
196}
197
198struct ReadValue<const DEDUP: bool>(OwnedDataValue);
200
201impl<'de, const DEDUP: bool> Deserialize<'de> for ReadValue<DEDUP> {
202 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
203 d.deserialize_any(ValueVisitor::<DEDUP>).map(Self)
204 }
205}
206
207struct ValueVisitor<const DEDUP: bool>;
211
212impl<'de, const DEDUP: bool> Visitor<'de> for ValueVisitor<DEDUP> {
213 type Value = OwnedDataValue;
214
215 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 f.write_str("any valid JSON value")
217 }
218
219 fn visit_unit<E: de::Error>(self) -> Result<OwnedDataValue, E> {
220 Ok(OwnedDataValue::Null)
221 }
222
223 fn visit_none<E: de::Error>(self) -> Result<OwnedDataValue, E> {
224 Ok(OwnedDataValue::Null)
225 }
226
227 fn visit_some<D: Deserializer<'de>>(self, d: D) -> Result<OwnedDataValue, D::Error> {
228 d.deserialize_any(Self)
229 }
230
231 fn visit_bool<E: de::Error>(self, v: bool) -> Result<OwnedDataValue, E> {
232 Ok(OwnedDataValue::Bool(v))
233 }
234
235 fn visit_i64<E: de::Error>(self, v: i64) -> Result<OwnedDataValue, E> {
236 Ok(OwnedDataValue::Number(NumberValue::Integer(v)))
237 }
238
239 fn visit_u64<E: de::Error>(self, v: u64) -> Result<OwnedDataValue, E> {
240 Ok(OwnedDataValue::Number(NumberValue::from_u64(v)))
241 }
242
243 fn visit_i128<E: de::Error>(self, v: i128) -> Result<OwnedDataValue, E> {
244 Ok(OwnedDataValue::Number(match i64::try_from(v) {
245 Ok(i) => NumberValue::Integer(i),
246 Err(_) => NumberValue::Float(v as f64),
247 }))
248 }
249
250 fn visit_u128<E: de::Error>(self, v: u128) -> Result<OwnedDataValue, E> {
251 Ok(OwnedDataValue::Number(match i64::try_from(v) {
252 Ok(i) => NumberValue::Integer(i),
253 Err(_) => NumberValue::Float(v as f64),
254 }))
255 }
256
257 fn visit_f64<E: de::Error>(self, v: f64) -> Result<OwnedDataValue, E> {
258 Ok(if v.is_finite() {
259 OwnedDataValue::Number(NumberValue::Float(v))
260 } else {
261 OwnedDataValue::Null
262 })
263 }
264
265 fn visit_str<E: de::Error>(self, v: &str) -> Result<OwnedDataValue, E> {
266 Ok(OwnedDataValue::String(v.to_owned()))
267 }
268
269 fn visit_string<E: de::Error>(self, v: String) -> Result<OwnedDataValue, E> {
270 Ok(OwnedDataValue::String(v))
271 }
272
273 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<OwnedDataValue, A::Error> {
274 let mut items = Vec::with_capacity(seq.size_hint().unwrap_or(0));
275 while let Some(ReadValue(item)) = seq.next_element::<ReadValue<DEDUP>>()? {
276 items.push(item);
277 }
278 Ok(OwnedDataValue::Array(items))
279 }
280
281 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<OwnedDataValue, A::Error> {
282 let mut pairs = Vec::with_capacity(map.size_hint().unwrap_or(0));
283 while let Some((key, ReadValue(value))) = map.next_entry::<String, ReadValue<DEDUP>>()? {
284 pairs.push((key, value));
285 }
286 if DEDUP {
287 dedup_object(&mut pairs);
288 } else if let Some(key) = repeated_key(&pairs) {
289 return Err(de::Error::custom(format_args!(
290 "an object holds the key `{key}` twice"
291 )));
292 }
293 Ok(OwnedDataValue::Object(pairs))
294 }
295}
296
297const SCAN: usize = 8;
300
301fn repeated_key(pairs: &[(String, OwnedDataValue)]) -> Option<&str> {
303 if pairs.len() <= SCAN {
304 return pairs
305 .iter()
306 .enumerate()
307 .find(|(i, (key, _))| pairs[..*i].iter().any(|(k, _)| k == key))
308 .map(|(_, (key, _))| key.as_str());
309 }
310 let mut seen = HashSet::with_capacity(pairs.len());
311 pairs
312 .iter()
313 .map(|(key, _)| key.as_str())
314 .find(|key| !seen.insert(*key))
315}
316
317fn dedup_object(pairs: &mut Vec<(String, OwnedDataValue)>) {
320 if repeated_key(pairs).is_some() {
321 fold_repeats(pairs);
322 }
323}
324
325pub(crate) fn keep_last(value: &mut OwnedDataValue) {
329 match value {
330 OwnedDataValue::Object(pairs) => {
331 dedup_object(pairs);
332 pairs.iter_mut().for_each(|(_, v)| keep_last(v));
333 }
334 OwnedDataValue::Array(items) => items.iter_mut().for_each(keep_last),
335 _ => {}
336 }
337}
338
339#[cold]
341fn fold_repeats(pairs: &mut Vec<(String, OwnedDataValue)>) {
342 let mut len = 0;
343 for i in 0..pairs.len() {
344 let (key, value) = std::mem::take(&mut pairs[i]);
345 if let Some((_, slot)) = pairs[..len].iter_mut().find(|(k, _)| *k == key) {
346 *slot = value;
347 } else {
348 pairs[len] = (key, value);
349 len += 1;
350 }
351 }
352 pairs.truncate(len);
353}
354
355#[cfg(test)]
356mod tests {
357 use super::*;
358 use serde_json::json;
359
360 fn text(c: &Context) -> String {
361 serde_json::to_string(c).unwrap()
362 }
363
364 #[test]
365 fn a_seed_that_is_not_an_object_is_ignored() {
366 let c = Context::new(
367 OwnedDataValue::from(&json!([1])),
368 OwnedDataValue::from(&json!({"m": 1})),
369 );
370 assert_eq!(text(&c), r#"{"data":{},"metadata":{"m":1},"temp_data":{}}"#);
371 }
372
373 #[test]
374 fn a_context_reads_what_it_writes() {
375 let wire = r#"{"data":{"b":1,"a":[null]},"metadata":null,"temp_data":"t"}"#;
376 let c: Context = serde_json::from_str(wire).unwrap();
377 assert_eq!(text(&c), wire);
378 assert_eq!(c.metadata(), &OwnedDataValue::Null);
379 assert_eq!(
380 c,
381 Context::from_root(OwnedDataValue::from(&json!({
382 "data": {"b": 1, "a": [null]}, "metadata": null, "temp_data": "t"
383 })))
384 );
385 }
386
387 #[test]
388 fn a_value_reads_back_as_written_and_as_the_json_bridge_builds_it() {
389 let wire =
390 r#"[2.0,-3.0,2.5,1e+300,7,-7,9223372036854775807,"s",true,null,{"b":[1.0],"a":{}}]"#;
391 let mut de = serde_json::Deserializer::from_str(wire);
392 let read = exact(&mut de).unwrap();
393 assert_eq!(serde_json::to_string(&read).unwrap(), wire);
394 let bridged: serde_json::Value = serde_json::from_str(wire).unwrap();
395 assert_eq!(read, OwnedDataValue::from(&bridged));
396 let collapsed: OwnedDataValue = serde_json::from_str(wire).unwrap();
398 assert!(
399 serde_json::to_string(&collapsed)
400 .unwrap()
401 .starts_with("[2,-3,2.5,")
402 );
403 let big = exact(&mut serde_json::Deserializer::from_str(
405 "18446744073709551615",
406 ))
407 .unwrap();
408 assert_eq!(big, OwnedDataValue::from(&json!(u64::MAX)));
409 }
410 #[test]
411 fn a_repeated_key_keeps_its_first_position_and_its_last_value() {
412 let fold = |text: &str| {
413 let mut value = OwnedDataValue::from_json(text).unwrap();
414 keep_last(&mut value);
415 serde_json::to_string(&value).unwrap()
416 };
417 assert_eq!(
418 fold(r#"{"a":1,"b":2,"a":3,"c":4,"b":5}"#),
419 r#"{"a":3,"b":5,"c":4}"#
420 );
421 assert_eq!(
423 fold(r#"[{"x":{"y":1,"y":2}},{"a":{"q":1},"a":{"q":2,"q":3}}]"#),
424 r#"[{"x":{"y":2}},{"a":{"q":3}}]"#
425 );
426 let wide: String = (0..12).map(|i| format!(r#""k{i}":{i},"#)).collect();
428 let wanted: String = (0..12)
429 .map(|i| format!(r#""k{i}":{},"#, if i == 3 { 99 } else { i }))
430 .collect();
431 assert_eq!(
432 fold(&format!(r#"{{{wide}"k3":99}}"#)),
433 format!("{{{}}}", wanted.trim_end_matches(','))
434 );
435 let plain = r#"{"b":1,"a":{"b":2},"c":[{"b":3}]}"#;
437 assert_eq!(fold(plain), plain);
438 }
439
440 fn array_buffer(value: &OwnedDataValue) -> *const OwnedDataValue {
442 let OwnedDataValue::Object(entries) = value else {
443 return std::ptr::null();
444 };
445 let Some((_, OwnedDataValue::Object(inner))) = entries.iter().find(|(key, _)| key == "a")
446 else {
447 return std::ptr::null();
448 };
449 let Some((_, OwnedDataValue::Array(items))) = inner.iter().find(|(key, _)| key == "b")
450 else {
451 return std::ptr::null();
452 };
453 items.as_ptr()
454 }
455
456 #[test]
457 fn taking_the_data_root_moves_the_tree_and_leaves_an_object() {
458 let data = json!({"a": {"b": [1, {"c": 2.0}]}, "big": 12345678901234i64});
459 let mut c = Context::from_root(OwnedDataValue::from(&json!({
460 "data": data, "metadata": {"m": 1}, "temp_data": {"t": true}
461 })));
462 let buffer = array_buffer(c.data());
463 assert!(!buffer.is_null());
464 let taken = c.take_data();
465 assert_eq!(taken, OwnedDataValue::from(&data));
468 assert_eq!(array_buffer(&taken), buffer);
469 assert_eq!(
470 serde_json::to_string(&taken).unwrap(),
471 r#"{"a":{"b":[1,{"c":2.0}]},"big":12345678901234}"#
472 );
473 assert_eq!(
476 text(&c),
477 r#"{"data":{},"metadata":{"m":1},"temp_data":{"t":true}}"#
478 );
479 }
480
481 #[test]
482 fn a_second_take_returns_the_empty_object_the_first_left() {
483 let mut c = Context::new(
484 OwnedDataValue::from(&json!({"a": 1})),
485 OwnedDataValue::from(&json!({"m": 1})),
486 );
487 assert_eq!(c.take_data(), OwnedDataValue::from(&json!({"a": 1})));
488 assert_eq!(c.take_data(), OwnedDataValue::Object(Vec::new()));
489 assert_eq!(text(&c), r#"{"data":{},"metadata":{"m":1},"temp_data":{}}"#);
490 }
491
492 #[test]
493 fn an_empty_data_root_is_taken_as_an_empty_object() {
494 let mut c = Context::new(OwnedDataValue::Object(Vec::new()), OwnedDataValue::Null);
495 assert_eq!(c.take_data(), OwnedDataValue::Object(Vec::new()));
496 assert_eq!(text(&c), r#"{"data":{},"metadata":{},"temp_data":{}}"#);
497 }
498
499 #[test]
500 fn a_redacted_root_is_taken_as_it_is_and_replaced_with_an_object() {
501 let mut c = Context::from_root(OwnedDataValue::from(&json!({
502 "data": null, "metadata": null, "temp_data": null
503 })));
504 assert_eq!(c.take_data(), OwnedDataValue::Null);
505 assert_eq!(text(&c), r#"{"data":{},"metadata":null,"temp_data":null}"#);
506 }
507}