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 =
273 HashMap::from([(BytesString::from("meta_key"), Bytes::from(data.clone()))]);
274
275 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
276 let (decoded_traces, _) =
277 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
278
279 assert_eq!(1, decoded_traces.len());
280 assert_eq!(1, decoded_traces[0].len());
281 let decoded_span = &decoded_traces[0][0];
282
283 assert_eq!(
284 decoded_span.meta_struct.get("meta_key").unwrap().to_vec(),
285 data
286 );
287 }
288
289 #[test]
290 fn test_decoder_meta_fixed_map_success() {
291 let expected_meta = HashMap::from([
292 ("key1".to_string(), "value1".to_string()),
293 ("key2".to_string(), "value2".to_string()),
294 ]);
295
296 let mut span = create_test_json_span(1, 2, 0, 0, false);
297 span["meta"] = json!(expected_meta.clone());
298
299 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
300 let (decoded_traces, _) =
301 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
302
303 assert_eq!(1, decoded_traces.len());
304 assert_eq!(1, decoded_traces[0].len());
305 let decoded_span = &decoded_traces[0][0];
306
307 for (key, value) in expected_meta.iter() {
308 assert_eq!(
309 value,
310 &decoded_span.meta[&BytesString::from_slice(key.as_ref()).unwrap()].as_str()
311 );
312 }
313 }
314
315 #[test]
316 fn test_decoder_meta_null_map_success() {
317 let mut span = create_test_json_span(1, 2, 0, 0, false);
318 span["meta"] = json!(null);
319
320 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
321 let (decoded_traces, _) =
322 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
323
324 assert_eq!(1, decoded_traces.len());
325 assert_eq!(1, decoded_traces[0].len());
326 let decoded_span = &decoded_traces[0][0];
327
328 assert!(decoded_span.meta.is_empty());
329 }
330
331 #[test]
332 fn test_decoder_meta_map_16_success() {
333 let expected_meta: HashMap<String, String> = (0..20)
334 .map(|i| {
335 (
336 format!("key {i}").to_owned(),
337 format!("value {i}").to_owned(),
338 )
339 })
340 .collect();
341
342 let mut span = create_test_json_span(1, 2, 0, 0, false);
343 span["meta"] = json!(expected_meta.clone());
344
345 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
346 let (decoded_traces, _) =
347 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
348
349 assert_eq!(1, decoded_traces.len());
350 assert_eq!(1, decoded_traces[0].len());
351 let decoded_span = &decoded_traces[0][0];
352
353 for (key, value) in expected_meta.iter() {
354 assert_eq!(
355 value,
356 &decoded_span.meta[&BytesString::from_slice(key.as_ref()).unwrap()].as_str()
357 );
358 }
359 }
360
361 #[test]
362 fn test_decoder_metrics_fixed_map_success() {
363 let expected_metrics = HashMap::from([("metric1", 1.23), ("metric2", 4.56)]);
364
365 let mut span = create_test_json_span(1, 2, 0, 0, false);
366 span["metrics"] = json!(expected_metrics.clone());
367 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
368 let (decoded_traces, _) =
369 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
370
371 assert_eq!(1, decoded_traces.len());
372 assert_eq!(1, decoded_traces[0].len());
373 let decoded_span = &decoded_traces[0][0];
374
375 for (key, value) in expected_metrics.iter() {
376 assert_eq!(
377 value,
378 &decoded_span.metrics[&BytesString::from_slice(key.as_ref()).unwrap()]
379 );
380 }
381 }
382
383 #[test]
384 fn test_decoder_metrics_map16_success() {
385 let expected_metrics: HashMap<String, f64> =
386 (0..20).map(|i| (format!("metric{i}"), i as f64)).collect();
387
388 let mut span = create_test_json_span(1, 2, 0, 0, false);
389 span["metrics"] = json!(expected_metrics.clone());
390 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
391 let (decoded_traces, _) =
392 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
393
394 assert_eq!(1, decoded_traces.len());
395 assert_eq!(1, decoded_traces[0].len());
396 let decoded_span = &decoded_traces[0][0];
397
398 for (key, value) in expected_metrics.iter() {
399 assert_eq!(
400 value,
401 &decoded_span.metrics[&BytesString::from_slice(key.as_ref()).unwrap()]
402 );
403 }
404 }
405
406 #[test]
407 fn test_decoder_metrics_null_success() {
408 let mut span = create_test_json_span(1, 2, 0, 0, false);
409 span["metrics"] = json!(null);
410 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
411 let (decoded_traces, _) =
412 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
413
414 assert_eq!(1, decoded_traces.len());
415 assert_eq!(1, decoded_traces[0].len());
416 let decoded_span = &decoded_traces[0][0];
417 assert!(decoded_span.metrics.is_empty());
418 }
419
420 #[test]
421 fn test_decoder_span_link_success() {
422 let expected_span_link = json!({
423 "trace_id": 1,
424 "trace_id_high": 0,
425 "span_id": 1,
426 "attributes": {
427 "attr1": "test_value",
428 "attr2": "test_value2"
429 },
430 "tracestate": "state_test",
431 "flags": 0b101
432 });
433
434 let mut span = create_test_json_span(1, 2, 0, 0, false);
435 span["span_links"] = json!([expected_span_link]);
436
437 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
438 let (decoded_traces, _) =
439 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
440
441 assert_eq!(1, decoded_traces.len());
442 assert_eq!(1, decoded_traces[0].len());
443 let decoded_span = &decoded_traces[0][0];
444
445 assert_eq!(
446 expected_span_link["trace_id"],
447 decoded_span.span_links[0].trace_id
448 );
449 assert_eq!(
450 expected_span_link["trace_id_high"],
451 decoded_span.span_links[0].trace_id_high
452 );
453 assert_eq!(
454 expected_span_link["span_id"],
455 decoded_span.span_links[0].span_id
456 );
457 assert_eq!(
458 expected_span_link["tracestate"],
459 decoded_span.span_links[0].tracestate.as_str()
460 );
461 assert_eq!(
462 expected_span_link["flags"],
463 decoded_span.span_links[0].flags
464 );
465 assert_eq!(
466 expected_span_link["attributes"]["attr1"],
467 decoded_span.span_links[0].attributes
468 [&BytesString::from_slice("attr1".as_ref()).unwrap()]
469 .as_str()
470 );
471 assert_eq!(
472 expected_span_link["attributes"]["attr2"],
473 decoded_span.span_links[0].attributes
474 [&BytesString::from_slice("attr2".as_ref()).unwrap()]
475 .as_str()
476 );
477 }
478
479 #[test]
480 fn test_decoder_null_span_link_success() {
481 let mut span = create_test_json_span(1, 2, 0, 0, false);
482 span["span_links"] = json!(null);
483
484 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
485 let (decoded_traces, _) =
486 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
487
488 assert_eq!(1, decoded_traces.len());
489 assert_eq!(1, decoded_traces[0].len());
490 let decoded_span = &decoded_traces[0][0];
491
492 assert!(decoded_span.span_links.is_empty());
493 }
494
495 #[test]
496 fn test_decoder_meta_with_null_values() {
497 let mut span = create_test_json_span(1, 2, 0, 0, false);
498 span["meta"] = json!({
499 "key1": "value1",
500 "key2": null, "key3": "value3"
502 });
503
504 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
505 let (decoded_traces, _) =
506 from_bytes(libdd_tinybytes::Bytes::from(encoded_data)).expect("Decoding failed");
507
508 assert_eq!(1, decoded_traces.len());
509 assert_eq!(1, decoded_traces[0].len());
510 let decoded_span = &decoded_traces[0][0];
511
512 assert_eq!(
513 "value1",
514 decoded_span.meta[&BytesString::from_slice("key1".as_ref()).unwrap()].as_str()
515 );
516 assert!(
517 !decoded_span
518 .meta
519 .contains_key(&BytesString::from_slice("key2".as_ref()).unwrap()),
520 "Null value should be skipped, but key was present"
521 );
522 assert_eq!(
523 "value3",
524 decoded_span.meta[&BytesString::from_slice("key3".as_ref()).unwrap()].as_str()
525 );
526 }
527
528 #[test]
529 fn test_decoder_read_string_wrong_format() {
530 let span = SpanBytes {
531 service: BytesString::from_slice("my_service".as_ref()).unwrap(),
532 ..Default::default()
533 };
534 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
535 encoded_data[2] = 0x8c;
537 let slice = encoded_data.as_ref();
538
539 let result = from_slice(slice);
540 assert_eq!(
541 Err(DecodeError::InvalidFormat(
542 "Expected at least bytes 1, but only got 0 (pos 0)".to_owned()
543 )),
544 result
545 );
546 }
547
548 #[test]
549 fn test_decoder_read_string_utf8_error() {
550 let invalid_seq = vec![0, 159, 146, 150];
551 let invalid_str = unsafe { String::from_utf8_unchecked(invalid_seq) };
552 let invalid_str_as_bytes = libdd_tinybytes::Bytes::from(invalid_str);
553 let span = SpanBytes {
554 name: unsafe { BytesString::from_bytes_unchecked(invalid_str_as_bytes) },
555 ..Default::default()
556 };
557 let encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
558 let slice = encoded_data.as_ref();
559
560 let result = from_slice(slice);
561 assert_eq!(
562 Err(DecodeError::Utf8Error(
563 "invalid utf-8 sequence of 1 bytes from index 1".to_owned()
564 )),
565 result
566 );
567 }
568
569 #[test]
570 fn test_decoder_invalid_marker_for_trace_count_read() {
571 let span = SpanBytes::default();
572 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
573 encoded_data[0] = 0x8c;
576 let slice = encoded_data.as_ref();
577
578 let result = from_slice(slice);
579 assert_eq!(
580 Err(DecodeError::InvalidFormat(
581 "Unable to read array len for trace count".to_string()
582 )),
583 result
584 );
585 }
586
587 #[test]
588 fn test_decoder_invalid_marker_for_span_count_read() {
589 let span = SpanBytes::default();
590 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
591 encoded_data[1] = 0x8c;
594 let slice = encoded_data.as_ref();
595
596 let result = from_slice(slice);
597 assert_eq!(
598 Err(DecodeError::InvalidFormat(
599 "Unable to read array len for span count".to_owned()
600 )),
601 result
602 );
603 }
604
605 #[test]
606 fn test_decoder_read_string_type_mismatch() {
607 let span = SpanBytes::default();
608 let mut encoded_data = rmp_serde::to_vec_named(&vec![vec![span]]).unwrap();
609 encoded_data[3] = 0x01;
612 let slice = encoded_data.as_ref();
613
614 let result = from_slice(slice);
615 assert_eq!(
616 Err(DecodeError::InvalidType(
617 "Type mismatch at marker FixPos(1)".to_owned()
618 )),
619 result
620 );
621 }
622
623 #[test]
624 #[cfg_attr(miri, ignore)]
625 fn fuzz_from_bytes() {
626 check!()
627 .with_type::<(
628 String,
629 String,
630 String,
631 String,
632 String,
633 String,
634 String,
635 String,
636 u64,
637 u64,
638 u64,
639 i64,
640 )>()
641 .cloned()
642 .for_each(
643 |(
644 name,
645 service,
646 resource,
647 span_type,
648 meta_key,
649 meta_value,
650 metric_key,
651 metric_value,
652 trace_id,
653 span_id,
654 parent_id,
655 start,
656 )| {
657 let span = SpanBytes {
658 name: BytesString::from_slice(name.as_ref()).unwrap(),
659 service: BytesString::from_slice(service.as_ref()).unwrap(),
660 resource: BytesString::from_slice(resource.as_ref()).unwrap(),
661 r#type: BytesString::from_slice(span_type.as_ref()).unwrap(),
662 meta: HashMap::from([(
663 BytesString::from_slice(meta_key.as_ref()).unwrap(),
664 BytesString::from_slice(meta_value.as_ref()).unwrap(),
665 )]),
666 metrics: HashMap::from([(
667 BytesString::from_slice(metric_key.as_ref()).unwrap(),
668 metric_value.parse::<f64>().unwrap_or_default(),
669 )]),
670 trace_id: trace_id as u128,
671 span_id,
672 parent_id,
673 start,
674 ..Default::default()
675 };
676 let encoded_data = to_vec_named(&vec![vec![span]]).unwrap();
677 let result = from_bytes(libdd_tinybytes::Bytes::from(encoded_data));
678
679 assert!(result.is_ok());
680 },
681 );
682 }
683}