1pub(crate) mod span;
5
6use self::span::decode_span;
7use crate::msgpack_decoder::decode::buffer::Buffer;
8use crate::msgpack_decoder::decode::error::DecodeError;
9use crate::span::v04::{Span, SpanBytes, SpanSlice};
10use crate::span::DeserializableTraceData;
11
12pub fn from_bytes(
55 data: libdd_tinybytes::Bytes,
56) -> Result<(Vec<Vec<SpanBytes>>, usize), DecodeError> {
57 from_buffer(&mut Buffer::new(data))
58}
59
60pub fn from_slice(data: &[u8]) -> Result<(Vec<Vec<SpanSlice<'_>>>, usize), DecodeError> {
103 from_buffer(&mut Buffer::new(data))
104}
105
106#[allow(clippy::type_complexity)]
107pub fn from_buffer<T: DeserializableTraceData>(
108 data: &mut Buffer<T>,
109) -> Result<(Vec<Vec<Span<T>>>, usize), DecodeError> {
110 let trace_count = rmp::decode::read_array_len(data.as_mut_slice()).map_err(|_| {
111 DecodeError::InvalidFormat("Unable to read array len for trace count".to_owned())
112 })?;
113
114 let start_len = data.len();
116
117 #[allow(clippy::expect_used)]
118 Ok((
119 (0..trace_count).try_fold(
120 Vec::with_capacity(
121 trace_count
122 .try_into()
123 .expect("Unable to cast trace_count to usize"),
124 ),
125 |mut traces, _| {
126 let span_count =
127 rmp::decode::read_array_len(data.as_mut_slice()).map_err(|_| {
128 DecodeError::InvalidFormat(
129 "Unable to read array len for span count".to_owned(),
130 )
131 })?;
132
133 let trace = (0..span_count).try_fold(
134 Vec::with_capacity(
135 span_count
136 .try_into()
137 .expect("Unable to cast span_count to usize"),
138 ),
139 |mut trace, _| {
140 let span = decode_span(data)?;
141 trace.push(span);
142 Ok(trace)
143 },
144 )?;
145
146 traces.push(trace);
147
148 Ok(traces)
149 },
150 )?,
151 start_len - data.len(),
152 ))
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::test_utils::{create_test_json_span, create_test_no_alloc_span};
159 use bolero::check;
160 use libdd_tinybytes::{Bytes, BytesString};
161 use rmp_serde;
162 use rmp_serde::to_vec_named;
163 use serde_json::json;
164 use std::collections::HashMap;
165
166 #[test]
167 fn test_empty_array() {
168 let encoded_data = vec![0x90];
169 let slice = encoded_data.as_ref();
170 let (_decoded_traces, decoded_size) = from_slice(slice).expect("Decoding failed");
171
172 assert_eq!(0, decoded_size);
173 }
174
175 #[test]
176 fn test_decoder_size() {
177 let span = SpanBytes {
178 name: BytesString::from_slice("span_name".as_ref()).unwrap(),
179 ..Default::default()
180 };
181 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
182 let expected_size = encoded_data.len() - 1; encoded_data.extend_from_slice(&[0, 0, 0, 0]); let (_decoded_traces, decoded_size) =
185 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
186
187 assert_eq!(expected_size, decoded_size);
188 }
189
190 #[test]
191 fn test_decoder_read_string_success() {
192 let expected_string = "test-service-name";
193 let span = SpanBytes {
194 name: BytesString::from_slice(expected_string.as_ref()).unwrap(),
195 ..Default::default()
196 };
197 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
198 encoded_data.extend_from_slice(&[0, 0, 0, 0]); let (decoded_traces, _) =
200 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
201
202 assert_eq!(1, decoded_traces.len());
203 assert_eq!(1, decoded_traces[0].len());
204 let decoded_span = &decoded_traces[0][0];
205 assert_eq!(expected_string, decoded_span.name.as_str());
206 }
207
208 #[test]
209 fn test_decoder_read_null_string_success() {
210 let mut span = create_test_json_span(1, 2, 0, 0, false);
211 span["name"] = json!(null);
212 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
213 encoded_data.extend_from_slice(&[0, 0, 0, 0]); let (decoded_traces, _) =
215 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
216
217 assert_eq!(1, decoded_traces.len());
218 assert_eq!(1, decoded_traces[0].len());
219 let decoded_span = &decoded_traces[0][0];
220 assert_eq!("", decoded_span.name.as_str());
221 }
222
223 #[test]
224 fn test_decoder_read_number_success() {
225 let span = create_test_json_span(1, 2, 0, 0, false);
226 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
227 encoded_data.extend_from_slice(&[0, 0, 0, 0]); let (decoded_traces, _) =
229 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
230
231 assert_eq!(1, decoded_traces.len());
232 assert_eq!(1, decoded_traces[0].len());
233 let decoded_span = &decoded_traces[0][0];
234 assert_eq!(1, decoded_span.trace_id);
235 }
236
237 #[test]
238 fn test_decoder_read_null_number_success() {
239 let mut span = create_test_json_span(1, 2, 0, 0, false);
240 span["trace_id"] = json!(null);
241 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
242 encoded_data.extend_from_slice(&[0, 0, 0, 0]); let (decoded_traces, _) =
244 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
245
246 assert_eq!(1, decoded_traces.len());
247 assert_eq!(1, decoded_traces[0].len());
248 let decoded_span = &decoded_traces[0][0];
249 assert_eq!(0, decoded_span.trace_id);
250 }
251
252 #[test]
253 fn test_decoder_meta_struct_null_map_success() {
254 let mut span = create_test_json_span(1, 2, 0, 0, false);
255 span["meta_struct"] = json!(null);
256
257 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
258 let (decoded_traces, _) =
259 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
260
261 assert_eq!(1, decoded_traces.len());
262 assert_eq!(1, decoded_traces[0].len());
263 let decoded_span = &decoded_traces[0][0];
264
265 assert!(decoded_span.meta_struct.is_empty());
266 }
267
268 #[test]
269 fn test_decoder_meta_struct_success() {
270 let data = vec![1, 2, 3, 4];
271 let mut span = create_test_no_alloc_span(1, 2, 0, 0, false);
272 span.meta_struct = vec![(BytesString::from("meta_key"), Bytes::from(data.clone()))].into();
273
274 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
275 let (decoded_traces, _) =
276 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
277
278 assert_eq!(1, decoded_traces.len());
279 assert_eq!(1, decoded_traces[0].len());
280 let decoded_span = &decoded_traces[0][0];
281
282 assert_eq!(
283 decoded_span.meta_struct.get("meta_key").unwrap().to_vec(),
284 data
285 );
286 }
287
288 #[test]
289 fn test_decoder_meta_fixed_map_success() {
290 let expected_meta = HashMap::from([
291 ("key1".to_string(), "value1".to_string()),
292 ("key2".to_string(), "value2".to_string()),
293 ]);
294
295 let mut span = create_test_json_span(1, 2, 0, 0, false);
296 span["meta"] = json!(expected_meta.clone());
297
298 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
299 let (decoded_traces, _) =
300 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
301
302 assert_eq!(1, decoded_traces.len());
303 assert_eq!(1, decoded_traces[0].len());
304 let decoded_span = &decoded_traces[0][0];
305
306 for (key, value) in expected_meta.iter() {
307 let bs_key = BytesString::from_slice(key.as_ref()).unwrap();
308 assert_eq!(value, &decoded_span.meta.get(&bs_key).unwrap().as_str());
309 }
310 }
311
312 #[test]
313 fn test_decoder_meta_null_map_success() {
314 let mut span = create_test_json_span(1, 2, 0, 0, false);
315 span["meta"] = json!(null);
316
317 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
318 let (decoded_traces, _) =
319 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
320
321 assert_eq!(1, decoded_traces.len());
322 assert_eq!(1, decoded_traces[0].len());
323 let decoded_span = &decoded_traces[0][0];
324
325 assert!(decoded_span.meta.is_empty());
326 }
327
328 #[test]
329 fn test_decoder_meta_map_16_success() {
330 let expected_meta: HashMap<String, String> = (0..20)
331 .map(|i| {
332 (
333 format!("key {i}").to_owned(),
334 format!("value {i}").to_owned(),
335 )
336 })
337 .collect();
338
339 let mut span = create_test_json_span(1, 2, 0, 0, false);
340 span["meta"] = json!(expected_meta.clone());
341
342 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
343 let (decoded_traces, _) =
344 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
345
346 assert_eq!(1, decoded_traces.len());
347 assert_eq!(1, decoded_traces[0].len());
348 let decoded_span = &decoded_traces[0][0];
349
350 for (key, value) in expected_meta.iter() {
351 let bs_key = BytesString::from_slice(key.as_ref()).unwrap();
352 assert_eq!(value, &decoded_span.meta.get(&bs_key).unwrap().as_str());
353 }
354 }
355
356 #[test]
357 fn test_decoder_metrics_fixed_map_success() {
358 let expected_metrics = HashMap::from([("metric1", 1.23), ("metric2", 4.56)]);
359
360 let mut span = create_test_json_span(1, 2, 0, 0, false);
361 span["metrics"] = json!(expected_metrics.clone());
362 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
363 let (decoded_traces, _) =
364 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
365
366 assert_eq!(1, decoded_traces.len());
367 assert_eq!(1, decoded_traces[0].len());
368 let decoded_span = &decoded_traces[0][0];
369
370 for (key, value) in expected_metrics.iter() {
371 let bs_key = BytesString::from_slice(key.as_ref()).unwrap();
372 assert_eq!(value, decoded_span.metrics.get(&bs_key).unwrap());
373 }
374 }
375
376 #[test]
377 fn test_decoder_metrics_map16_success() {
378 let expected_metrics: HashMap<String, f64> =
379 (0..20).map(|i| (format!("metric{i}"), i as f64)).collect();
380
381 let mut span = create_test_json_span(1, 2, 0, 0, false);
382 span["metrics"] = json!(expected_metrics.clone());
383 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
384 let (decoded_traces, _) =
385 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
386
387 assert_eq!(1, decoded_traces.len());
388 assert_eq!(1, decoded_traces[0].len());
389 let decoded_span = &decoded_traces[0][0];
390
391 for (key, value) in expected_metrics.iter() {
392 let bs_key = BytesString::from_slice(key.as_ref()).unwrap();
393 assert_eq!(value, decoded_span.metrics.get(&bs_key).unwrap());
394 }
395 }
396
397 #[test]
398 fn test_decoder_metrics_null_success() {
399 let mut span = create_test_json_span(1, 2, 0, 0, false);
400 span["metrics"] = json!(null);
401 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
402 let (decoded_traces, _) =
403 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
404
405 assert_eq!(1, decoded_traces.len());
406 assert_eq!(1, decoded_traces[0].len());
407 let decoded_span = &decoded_traces[0][0];
408 assert!(decoded_span.metrics.is_empty());
409 }
410
411 #[test]
412 fn test_decoded_span_maps_are_marked_deduped() {
413 let mut span = create_test_json_span(1, 2, 0, 0, false);
416 span["meta"] = json!({ "key": "value" });
417 span["metrics"] = json!({ "metric": 1.0 });
418 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
421 let (decoded_traces, _) =
422 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
423
424 let decoded_span = &decoded_traces[0][0];
425 assert!(decoded_span.meta.is_deduped(), "meta should be deduped");
426 assert!(
427 decoded_span.metrics.is_deduped(),
428 "metrics should be deduped"
429 );
430 assert!(
431 decoded_span.meta_struct.is_deduped(),
432 "empty meta_struct should be deduped"
433 );
434 }
435
436 #[test]
437 fn test_decoder_span_link_success() {
438 let expected_span_link = json!({
439 "trace_id": 1,
440 "trace_id_high": 0,
441 "span_id": 1,
442 "attributes": {
443 "attr1": "test_value",
444 "attr2": "test_value2"
445 },
446 "tracestate": "state_test",
447 "flags": 0b101
448 });
449
450 let mut span = create_test_json_span(1, 2, 0, 0, false);
451 span["span_links"] = json!([expected_span_link]);
452
453 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
454 let (decoded_traces, _) =
455 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
456
457 assert_eq!(1, decoded_traces.len());
458 assert_eq!(1, decoded_traces[0].len());
459 let decoded_span = &decoded_traces[0][0];
460
461 assert_eq!(
462 expected_span_link["trace_id"],
463 decoded_span.span_links[0].trace_id
464 );
465 assert_eq!(
466 expected_span_link["trace_id_high"],
467 decoded_span.span_links[0].trace_id_high
468 );
469 assert_eq!(
470 expected_span_link["span_id"],
471 decoded_span.span_links[0].span_id
472 );
473 assert_eq!(
474 expected_span_link["tracestate"],
475 decoded_span.span_links[0].tracestate.as_str()
476 );
477 assert_eq!(
478 expected_span_link["flags"],
479 decoded_span.span_links[0].flags
480 );
481 assert_eq!(
482 expected_span_link["attributes"]["attr1"],
483 decoded_span.span_links[0].attributes
484 [&BytesString::from_slice("attr1".as_ref()).unwrap()]
485 .as_str()
486 );
487 assert_eq!(
488 expected_span_link["attributes"]["attr2"],
489 decoded_span.span_links[0].attributes
490 [&BytesString::from_slice("attr2".as_ref()).unwrap()]
491 .as_str()
492 );
493 }
494
495 #[test]
496 fn test_decoder_null_span_link_success() {
497 let mut span = create_test_json_span(1, 2, 0, 0, false);
498 span["span_links"] = json!(null);
499
500 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
501 let (decoded_traces, _) =
502 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
503
504 assert_eq!(1, decoded_traces.len());
505 assert_eq!(1, decoded_traces[0].len());
506 let decoded_span = &decoded_traces[0][0];
507
508 assert!(decoded_span.span_links.is_empty());
509 }
510
511 #[test]
512 fn test_decoder_meta_with_null_values() {
513 let mut span = create_test_json_span(1, 2, 0, 0, false);
514 span["meta"] = json!({
515 "key1": "value1",
516 "key2": null, "key3": "value3"
518 });
519
520 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
521 let (decoded_traces, _) =
522 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
523
524 assert_eq!(1, decoded_traces.len());
525 assert_eq!(1, decoded_traces[0].len());
526 let decoded_span = &decoded_traces[0][0];
527
528 let key1 = BytesString::from_slice("key1".as_ref()).unwrap();
529 let key2 = BytesString::from_slice("key2".as_ref()).unwrap();
530 let key3 = BytesString::from_slice("key3".as_ref()).unwrap();
531 assert_eq!("value1", decoded_span.meta.get(&key1).unwrap().as_str());
532 assert!(
533 !decoded_span.meta.contains_key(&key2),
534 "Null value should be skipped, but key was present"
535 );
536 assert_eq!("value3", decoded_span.meta.get(&key3).unwrap().as_str());
537 }
538
539 #[test]
540 fn test_decoder_read_string_wrong_format() {
541 let span = SpanBytes {
542 service: BytesString::from_slice("my_service".as_ref()).unwrap(),
543 ..Default::default()
544 };
545 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
546 encoded_data[2] = 0x8c;
548 let slice = encoded_data.as_ref();
549
550 let result = from_slice(slice);
551 assert_eq!(
552 Err(DecodeError::InvalidFormat(
553 "Expected at least bytes 1, but only got 0 (pos 0)".to_owned()
554 )),
555 result
556 );
557 }
558
559 #[test]
560 fn test_decoder_read_string_utf8_error() {
561 let invalid_seq = vec![0, 159, 146, 150];
562 let invalid_str = unsafe { String::from_utf8_unchecked(invalid_seq) };
563 let invalid_str_as_bytes = libdd_tinybytes::Bytes::from(invalid_str);
564 let span = SpanBytes {
565 name: unsafe { BytesString::from_bytes_unchecked(invalid_str_as_bytes) },
566 ..Default::default()
567 };
568 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
569 let slice = encoded_data.as_ref();
570
571 let result = from_slice(slice);
572 assert_eq!(
573 Err(DecodeError::Utf8Error(
574 "invalid utf-8 sequence of 1 bytes from index 1".to_owned()
575 )),
576 result
577 );
578 }
579
580 #[test]
581 fn test_decoder_invalid_marker_for_trace_count_read() {
582 let span = SpanBytes::default();
583 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
584 encoded_data[0] = 0x8c;
587 let slice = encoded_data.as_ref();
588
589 let result = from_slice(slice);
590 assert_eq!(
591 Err(DecodeError::InvalidFormat(
592 "Unable to read array len for trace count".to_string()
593 )),
594 result
595 );
596 }
597
598 #[test]
599 fn test_decoder_invalid_marker_for_span_count_read() {
600 let span = SpanBytes::default();
601 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
602 encoded_data[1] = 0x8c;
605 let slice = encoded_data.as_ref();
606
607 let result = from_slice(slice);
608 assert_eq!(
609 Err(DecodeError::InvalidFormat(
610 "Unable to read array len for span count".to_owned()
611 )),
612 result
613 );
614 }
615
616 #[test]
617 fn test_decoder_read_string_type_mismatch() {
618 let span = SpanBytes::default();
619 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
620 encoded_data[3] = 0x01;
623 let slice = encoded_data.as_ref();
624
625 let result = from_slice(slice);
626 assert_eq!(
627 Err(DecodeError::InvalidType(
628 "Type mismatch at marker FixPos(1)".to_owned()
629 )),
630 result
631 );
632 }
633
634 #[test]
635 #[cfg_attr(miri, ignore)]
636 fn fuzz_from_bytes() {
637 check!()
638 .with_type::<(
639 String,
640 String,
641 String,
642 String,
643 String,
644 String,
645 String,
646 String,
647 u64,
648 u64,
649 u64,
650 i64,
651 )>()
652 .cloned()
653 .for_each(
654 |(
655 name,
656 service,
657 resource,
658 span_type,
659 meta_key,
660 meta_value,
661 metric_key,
662 metric_value,
663 trace_id,
664 span_id,
665 parent_id,
666 start,
667 )| {
668 let span = SpanBytes {
669 name: BytesString::from_slice(name.as_ref()).unwrap(),
670 service: BytesString::from_slice(service.as_ref()).unwrap(),
671 resource: BytesString::from_slice(resource.as_ref()).unwrap(),
672 r#type: BytesString::from_slice(span_type.as_ref()).unwrap(),
673 meta: vec![(
674 BytesString::from_slice(meta_key.as_ref()).unwrap(),
675 BytesString::from_slice(meta_value.as_ref()).unwrap(),
676 )]
677 .into(),
678 metrics: vec![(
679 BytesString::from_slice(metric_key.as_ref()).unwrap(),
680 metric_value.parse::<f64>().unwrap_or_default(),
681 )]
682 .into(),
683 trace_id: trace_id as u128,
684 span_id,
685 parent_id,
686 start,
687 ..Default::default()
688 };
689 let encoded_data = to_vec_named(&vec![vec![span]]).unwrap();
690 let result = from_bytes(libdd_tinybytes::Bytes::from(encoded_data));
691
692 assert!(result.is_ok());
693 },
694 );
695 }
696}