1#[cfg(feature = "decoder")]
2use crate::decoder_buffer::DecoderBuffer;
3#[cfg(feature = "encoder")]
4use crate::encoder_buffer::EncoderBuffer;
5use crate::status::DracoError;
6use std::collections::BTreeMap;
7use std::mem::size_of;
8use std::str;
9
10pub const METADATA_FLAG_MASK: u16 = 0x8000;
12
13#[cfg(feature = "decoder")]
14const MAX_METADATA_NESTING_DEPTH: usize = 1000;
15const MAX_METADATA_NAME_LEN: usize = u8::MAX as usize;
16
17#[derive(Debug, Clone, Default, PartialEq, Eq)]
22pub struct Metadata {
23 entries: BTreeMap<String, Vec<u8>>,
24 sub_metadata: BTreeMap<String, Metadata>,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct AttributeMetadata {
30 attribute_unique_id: u32,
31 metadata: Metadata,
32}
33
34#[derive(Debug, Clone, Default, PartialEq, Eq)]
36pub struct GeometryMetadata {
37 metadata: Metadata,
38 attribute_metadata: Vec<AttributeMetadata>,
39}
40
41impl Metadata {
42 pub fn new() -> Self {
44 Self::default()
45 }
46
47 pub fn is_empty(&self) -> bool {
49 self.entries.is_empty() && self.sub_metadata.is_empty()
50 }
51
52 pub fn entries(&self) -> &BTreeMap<String, Vec<u8>> {
54 &self.entries
55 }
56
57 pub fn sub_metadata(&self) -> &BTreeMap<String, Metadata> {
59 &self.sub_metadata
60 }
61
62 pub fn get_raw(&self, name: &str) -> Option<&[u8]> {
64 self.entries.get(name).map(Vec::as_slice)
65 }
66
67 pub fn set_raw(
69 &mut self,
70 name: impl Into<String>,
71 value: impl Into<Vec<u8>>,
72 ) -> Result<(), DracoError> {
73 let name = name.into();
74 validate_metadata_name(&name)?;
75 let value = value.into();
76 if value.is_empty() {
77 return Err(DracoError::InvalidParameter(
78 "Metadata entry value must not be empty".to_string(),
79 ));
80 }
81 self.entries.insert(name, value);
82 Ok(())
83 }
84
85 pub fn set_i32(&mut self, name: impl Into<String>, value: i32) -> Result<(), DracoError> {
87 self.set_raw(name, value.to_le_bytes().to_vec())
88 }
89
90 pub fn get_i32(&self, name: &str) -> Option<i32> {
92 let bytes = self.get_raw(name)?;
93 let bytes: [u8; size_of::<i32>()] = bytes.try_into().ok()?;
94 Some(i32::from_le_bytes(bytes))
95 }
96
97 pub fn set_i32_array(
99 &mut self,
100 name: impl Into<String>,
101 values: &[i32],
102 ) -> Result<(), DracoError> {
103 let mut bytes = Vec::new();
104 let byte_len = values
105 .len()
106 .checked_mul(size_of::<i32>())
107 .ok_or_else(|| DracoError::InvalidParameter("Metadata array too large".to_string()))?;
108 bytes
109 .try_reserve_exact(byte_len)
110 .map_err(|_| DracoError::InvalidParameter("Metadata array too large".to_string()))?;
111 for value in values {
112 bytes.extend_from_slice(&value.to_le_bytes());
113 }
114 self.set_raw(name, bytes)
115 }
116
117 pub fn get_i32_array(&self, name: &str) -> Option<Vec<i32>> {
119 let bytes = self.get_raw(name)?;
120 decode_le_array::<{ size_of::<i32>() }, i32>(bytes, i32::from_le_bytes)
121 }
122
123 pub fn set_f64(&mut self, name: impl Into<String>, value: f64) -> Result<(), DracoError> {
125 self.set_raw(name, value.to_le_bytes().to_vec())
126 }
127
128 pub fn get_f64(&self, name: &str) -> Option<f64> {
130 let bytes = self.get_raw(name)?;
131 let bytes: [u8; size_of::<f64>()] = bytes.try_into().ok()?;
132 Some(f64::from_le_bytes(bytes))
133 }
134
135 pub fn set_f64_array(
137 &mut self,
138 name: impl Into<String>,
139 values: &[f64],
140 ) -> Result<(), DracoError> {
141 let mut bytes = Vec::new();
142 let byte_len = values
143 .len()
144 .checked_mul(size_of::<f64>())
145 .ok_or_else(|| DracoError::InvalidParameter("Metadata array too large".to_string()))?;
146 bytes
147 .try_reserve_exact(byte_len)
148 .map_err(|_| DracoError::InvalidParameter("Metadata array too large".to_string()))?;
149 for value in values {
150 bytes.extend_from_slice(&value.to_le_bytes());
151 }
152 self.set_raw(name, bytes)
153 }
154
155 pub fn get_f64_array(&self, name: &str) -> Option<Vec<f64>> {
157 let bytes = self.get_raw(name)?;
158 decode_le_array::<{ size_of::<f64>() }, f64>(bytes, f64::from_le_bytes)
159 }
160
161 pub fn set_string(
163 &mut self,
164 name: impl Into<String>,
165 value: impl AsRef<str>,
166 ) -> Result<(), DracoError> {
167 self.set_raw(name, value.as_ref().as_bytes().to_vec())
168 }
169
170 pub fn get_string(&self, name: &str) -> Option<&str> {
172 str::from_utf8(self.get_raw(name)?).ok()
173 }
174
175 pub fn remove_entry(&mut self, name: &str) -> Option<Vec<u8>> {
177 self.entries.remove(name)
178 }
179
180 pub fn get_sub_metadata(&self, name: &str) -> Option<&Metadata> {
182 self.sub_metadata.get(name)
183 }
184
185 pub fn get_sub_metadata_mut(&mut self, name: &str) -> Option<&mut Metadata> {
187 self.sub_metadata.get_mut(name)
188 }
189
190 pub fn insert_sub_metadata(
192 &mut self,
193 name: impl Into<String>,
194 metadata: Metadata,
195 ) -> Result<(), DracoError> {
196 let name = name.into();
197 validate_metadata_name(&name)?;
198 if self.sub_metadata.contains_key(&name) {
199 return Err(DracoError::DracoError(format!(
200 "Duplicate sub-metadata name: {name}"
201 )));
202 }
203 self.sub_metadata.insert(name, metadata);
204 Ok(())
205 }
206
207 #[cfg(feature = "decoder")]
208 pub fn decode(buffer: &mut DecoderBuffer<'_>) -> Result<Self, DracoError> {
210 Self::decode_with_depth(buffer, 0)
211 }
212
213 #[cfg(feature = "decoder")]
214 fn decode_with_depth(buffer: &mut DecoderBuffer<'_>, depth: usize) -> Result<Self, DracoError> {
215 if depth > MAX_METADATA_NESTING_DEPTH {
216 return Err(DracoError::DracoError(
217 "Metadata nesting depth exceeded".to_string(),
218 ));
219 }
220
221 let num_entries = decode_bounded_count(buffer, "metadata entries count")?;
222 let mut metadata = Metadata::new();
223 for _ in 0..num_entries {
224 let name = decode_name(buffer)?;
225 let data_size = usize::try_from(buffer.decode_varint()?).map_err(|_| {
226 DracoError::DracoError("Metadata entry data size too large".to_string())
227 })?;
228 if data_size == 0 {
229 return Err(DracoError::DracoError(
230 "Invalid metadata entry data size".to_string(),
231 ));
232 }
233 if data_size > buffer.remaining_size() {
234 return Err(DracoError::DracoError(
235 "Failed to read metadata entry value".to_string(),
236 ));
237 }
238 let value = buffer.decode_slice(data_size)?.to_vec();
239 metadata.entries.insert(name, value);
240 }
241
242 let num_sub_metadata = decode_bounded_count(buffer, "sub-metadata count")?;
243 if num_sub_metadata > buffer.remaining_size() {
244 return Err(DracoError::DracoError(
245 "Invalid sub-metadata count".to_string(),
246 ));
247 }
248 for _ in 0..num_sub_metadata {
249 let name = decode_name(buffer)?;
250 if metadata.sub_metadata.contains_key(&name) {
251 return Err(DracoError::DracoError(format!(
252 "Duplicate sub-metadata name: {name}"
253 )));
254 }
255 let sub_metadata = Self::decode_with_depth(buffer, depth + 1)?;
256 metadata.sub_metadata.insert(name, sub_metadata);
257 }
258
259 Ok(metadata)
260 }
261
262 #[cfg(feature = "encoder")]
263 pub fn encode(&self, buffer: &mut EncoderBuffer) -> Result<(), DracoError> {
265 buffer.encode_varint(self.entries.len() as u64);
266 for (name, value) in &self.entries {
267 encode_name(buffer, name)?;
268 if value.is_empty() {
269 return Err(DracoError::InvalidParameter(
270 "Metadata entry value must not be empty".to_string(),
271 ));
272 }
273 buffer.encode_varint(value.len() as u64);
274 buffer.encode_data(value);
275 }
276
277 buffer.encode_varint(self.sub_metadata.len() as u64);
278 for (name, metadata) in &self.sub_metadata {
279 encode_name(buffer, name)?;
280 metadata.encode(buffer)?;
281 }
282
283 Ok(())
284 }
285}
286
287impl AttributeMetadata {
288 pub fn new(attribute_unique_id: u32, metadata: Metadata) -> Self {
290 Self {
291 attribute_unique_id,
292 metadata,
293 }
294 }
295
296 pub fn attribute_unique_id(&self) -> u32 {
298 self.attribute_unique_id
299 }
300
301 pub fn metadata(&self) -> &Metadata {
303 &self.metadata
304 }
305
306 pub fn metadata_mut(&mut self) -> &mut Metadata {
308 &mut self.metadata
309 }
310}
311
312impl GeometryMetadata {
313 pub fn new() -> Self {
315 Self::default()
316 }
317
318 pub fn is_empty(&self) -> bool {
320 self.metadata.is_empty() && self.attribute_metadata.is_empty()
321 }
322
323 pub fn metadata(&self) -> &Metadata {
325 &self.metadata
326 }
327
328 pub fn metadata_mut(&mut self) -> &mut Metadata {
330 &mut self.metadata
331 }
332
333 pub fn attribute_metadata(&self) -> &[AttributeMetadata] {
335 &self.attribute_metadata
336 }
337
338 pub fn attribute_metadata_by_unique_id(
340 &self,
341 attribute_unique_id: u32,
342 ) -> Option<&AttributeMetadata> {
343 self.attribute_metadata
344 .iter()
345 .find(|metadata| metadata.attribute_unique_id == attribute_unique_id)
346 }
347
348 pub fn attribute_metadata_by_string_entry(
350 &self,
351 entry_name: &str,
352 entry_value: &str,
353 ) -> Option<&AttributeMetadata> {
354 self.attribute_metadata
355 .iter()
356 .find(|metadata| metadata.metadata.get_string(entry_name) == Some(entry_value))
357 }
358
359 pub fn attribute_metadata_by_unique_id_mut(
361 &mut self,
362 attribute_unique_id: u32,
363 ) -> Option<&mut AttributeMetadata> {
364 self.attribute_metadata
365 .iter_mut()
366 .find(|metadata| metadata.attribute_unique_id == attribute_unique_id)
367 }
368
369 pub fn set_attribute_metadata(&mut self, attribute_unique_id: u32, metadata: Metadata) {
371 if let Some(existing) = self.attribute_metadata_by_unique_id_mut(attribute_unique_id) {
372 existing.metadata = metadata;
373 } else {
374 self.attribute_metadata
375 .push(AttributeMetadata::new(attribute_unique_id, metadata));
376 }
377 }
378
379 #[cfg(feature = "decoder")]
380 pub fn decode(buffer: &mut DecoderBuffer<'_>) -> Result<Self, DracoError> {
382 let num_attribute_metadata = decode_bounded_count(buffer, "attribute metadata count")?;
383 let mut geometry_metadata = GeometryMetadata::new();
384 geometry_metadata
385 .attribute_metadata
386 .try_reserve_exact(num_attribute_metadata)
387 .map_err(|_| DracoError::DracoError("Failed to allocate metadata".to_string()))?;
388
389 for _ in 0..num_attribute_metadata {
390 let attribute_unique_id = u32::try_from(buffer.decode_varint()?).map_err(|_| {
391 DracoError::DracoError("Attribute metadata unique id too large".to_string())
392 })?;
393 let metadata = Metadata::decode(buffer)?;
394 geometry_metadata
395 .attribute_metadata
396 .push(AttributeMetadata::new(attribute_unique_id, metadata));
397 }
398 geometry_metadata.metadata = Metadata::decode(buffer)?;
399 Ok(geometry_metadata)
400 }
401
402 #[cfg(feature = "encoder")]
403 pub fn encode(&self, buffer: &mut EncoderBuffer) -> Result<(), DracoError> {
405 buffer.encode_varint(self.attribute_metadata.len() as u64);
406 for attribute_metadata in &self.attribute_metadata {
407 buffer.encode_varint(attribute_metadata.attribute_unique_id as u64);
408 attribute_metadata.metadata.encode(buffer)?;
409 }
410 self.metadata.encode(buffer)
411 }
412}
413
414fn decode_le_array<const N: usize, T>(
415 bytes: &[u8],
416 decode: impl Fn([u8; N]) -> T,
417) -> Option<Vec<T>> {
418 if bytes.is_empty() || !bytes.len().is_multiple_of(N) {
419 return None;
420 }
421
422 let mut values = Vec::with_capacity(bytes.len() / N);
423 for chunk in bytes.chunks_exact(N) {
424 let mut item = [0u8; N];
425 item.copy_from_slice(chunk);
426 values.push(decode(item));
427 }
428 Some(values)
429}
430
431fn validate_metadata_name(name: &str) -> Result<(), DracoError> {
432 if name.len() > MAX_METADATA_NAME_LEN {
433 return Err(DracoError::InvalidParameter(format!(
434 "Metadata name too long: {} bytes",
435 name.len()
436 )));
437 }
438 Ok(())
439}
440
441#[cfg(feature = "encoder")]
442fn encode_name(buffer: &mut EncoderBuffer, name: &str) -> Result<(), DracoError> {
443 validate_metadata_name(name)?;
444 buffer.encode_u8(name.len() as u8);
445 if !name.is_empty() {
446 buffer.encode_data(name.as_bytes());
447 }
448 Ok(())
449}
450
451#[cfg(feature = "decoder")]
452fn decode_name(buffer: &mut DecoderBuffer<'_>) -> Result<String, DracoError> {
453 let name_len = buffer.decode_u8()? as usize;
454 if name_len > buffer.remaining_size() {
455 return Err(DracoError::DracoError(
456 "Failed to read metadata name".to_string(),
457 ));
458 }
459 let name = buffer.decode_slice(name_len)?.to_vec();
460 String::from_utf8(name)
461 .map_err(|_| DracoError::DracoError("Invalid UTF-8 metadata name".to_string()))
462}
463
464#[cfg(feature = "decoder")]
465fn decode_bounded_count(
466 buffer: &mut DecoderBuffer<'_>,
467 label: &'static str,
468) -> Result<usize, DracoError> {
469 let count = usize::try_from(buffer.decode_varint()?)
470 .map_err(|_| DracoError::DracoError(format!("{label} too large")))?;
471 if count > buffer.remaining_size() {
472 return Err(DracoError::DracoError(format!("Invalid {label}")));
473 }
474 Ok(count)
475}
476
477#[cfg(test)]
478mod tests {
479 use super::*;
480
481 fn encode_metadata(metadata: &Metadata) -> Vec<u8> {
482 let mut buffer = EncoderBuffer::new();
483 metadata.encode(&mut buffer).expect("metadata encode");
484 buffer.data().to_vec()
485 }
486
487 #[test]
488 fn metadata_codec_accepts_empty_metadata() {
489 let metadata = Metadata::new();
490 let bytes = encode_metadata(&metadata);
491 assert_eq!(bytes, vec![0, 0]);
492
493 let mut buffer = DecoderBuffer::new(&bytes);
494 assert_eq!(Metadata::decode(&mut buffer).unwrap(), metadata);
495 }
496
497 #[test]
498 fn metadata_codec_roundtrips_raw_entry() {
499 let mut metadata = Metadata::new();
500 metadata.set_raw("name", b"value".to_vec()).unwrap();
501
502 let bytes = encode_metadata(&metadata);
503 let mut buffer = DecoderBuffer::new(&bytes);
504 let decoded = Metadata::decode(&mut buffer).unwrap();
505
506 assert_eq!(decoded.get_raw("name"), Some(b"value".as_slice()));
507 }
508
509 #[test]
510 fn metadata_typed_helpers_encode_cpp_compatible_bytes() {
511 let mut metadata = Metadata::new();
512 metadata.set_i32("i32", -123).unwrap();
513 metadata.set_i32_array("i32_array", &[1, -2, 3]).unwrap();
514 metadata.set_f64("f64", 1.25).unwrap();
515 metadata.set_f64_array("f64_array", &[0.5, -2.0]).unwrap();
516 metadata.set_string("string", "metadata").unwrap();
517
518 assert_eq!(
519 metadata.get_raw("i32"),
520 Some((-123i32).to_le_bytes().as_slice())
521 );
522 assert_eq!(
523 metadata.get_raw("i32_array"),
524 Some(
525 [
526 1i32.to_le_bytes(),
527 (-2i32).to_le_bytes(),
528 3i32.to_le_bytes()
529 ]
530 .concat()
531 .as_slice()
532 )
533 );
534 assert_eq!(
535 metadata.get_raw("f64"),
536 Some(1.25f64.to_le_bytes().as_slice())
537 );
538 assert_eq!(
539 metadata.get_raw("f64_array"),
540 Some(
541 [0.5f64.to_le_bytes(), (-2.0f64).to_le_bytes()]
542 .concat()
543 .as_slice()
544 )
545 );
546 assert_eq!(metadata.get_raw("string"), Some(b"metadata".as_slice()));
547
548 assert_eq!(metadata.get_i32("i32"), Some(-123));
549 assert_eq!(metadata.get_i32_array("i32_array"), Some(vec![1, -2, 3]));
550 assert_eq!(metadata.get_f64("f64"), Some(1.25));
551 assert_eq!(metadata.get_f64_array("f64_array"), Some(vec![0.5, -2.0]));
552 assert_eq!(metadata.get_string("string"), Some("metadata"));
553 }
554
555 #[test]
556 fn metadata_typed_getters_decode_raw_bytes() {
557 let mut metadata = Metadata::new();
558 metadata
559 .set_raw("i32", 42i32.to_le_bytes().to_vec())
560 .unwrap();
561 metadata
562 .set_raw(
563 "i32_array",
564 [7i32.to_le_bytes(), (-8i32).to_le_bytes()].concat(),
565 )
566 .unwrap();
567 metadata
568 .set_raw("f64", 3.5f64.to_le_bytes().to_vec())
569 .unwrap();
570 metadata
571 .set_raw(
572 "f64_array",
573 [1.0f64.to_le_bytes(), 2.25f64.to_le_bytes()].concat(),
574 )
575 .unwrap();
576 metadata.set_raw("string", b"from raw".to_vec()).unwrap();
577
578 assert_eq!(metadata.get_i32("i32"), Some(42));
579 assert_eq!(metadata.get_i32_array("i32_array"), Some(vec![7, -8]));
580 assert_eq!(metadata.get_f64("f64"), Some(3.5));
581 assert_eq!(metadata.get_f64_array("f64_array"), Some(vec![1.0, 2.25]));
582 assert_eq!(metadata.get_string("string"), Some("from raw"));
583 }
584
585 #[test]
586 fn metadata_typed_getters_reject_wrong_raw_shapes() {
587 let mut metadata = Metadata::new();
588 metadata.set_raw("i32", vec![1, 2, 3]).unwrap();
589 metadata.set_raw("i32_array", vec![1, 2, 3]).unwrap();
590 metadata.set_raw("f64", vec![1, 2, 3, 4]).unwrap();
591 metadata.set_raw("f64_array", vec![1, 2, 3, 4]).unwrap();
592 metadata.set_raw("string", vec![0xff]).unwrap();
593
594 assert_eq!(metadata.get_i32("i32"), None);
595 assert_eq!(metadata.get_i32_array("i32_array"), None);
596 assert_eq!(metadata.get_f64("f64"), None);
597 assert_eq!(metadata.get_f64_array("f64_array"), None);
598 assert_eq!(metadata.get_string("string"), None);
599 }
600
601 #[test]
602 fn metadata_typed_setters_reject_empty_values() {
603 let mut metadata = Metadata::new();
604
605 assert!(metadata.set_string("string", "").is_err());
606 assert!(metadata.set_i32_array("i32_array", &[]).is_err());
607 assert!(metadata.set_f64_array("f64_array", &[]).is_err());
608 }
609
610 #[test]
611 fn metadata_typed_setters_overwrite_existing_entry() {
612 let mut metadata = Metadata::new();
613 metadata.set_i32("key", 5).unwrap();
614 metadata.set_string("key", "value").unwrap();
615
616 assert_eq!(metadata.get_i32("key"), None);
617 assert_eq!(metadata.get_string("key"), Some("value"));
618 assert_eq!(metadata.get_raw("key"), Some(b"value".as_slice()));
619 }
620
621 #[test]
622 fn metadata_codec_encodes_entries_in_sorted_order() {
623 let mut metadata = Metadata::new();
624 metadata.set_raw("z", b"last".to_vec()).unwrap();
625 metadata.set_raw("a", b"first".to_vec()).unwrap();
626
627 let bytes = encode_metadata(&metadata);
628
629 assert_eq!(bytes[0], 2);
630 assert_eq!(bytes[1], 1);
631 assert_eq!(bytes[2], b'a');
632 }
633
634 #[test]
635 fn metadata_codec_roundtrips_nested_metadata() {
636 let mut child = Metadata::new();
637 child.set_raw("child", b"value".to_vec()).unwrap();
638
639 let mut metadata = Metadata::new();
640 metadata.insert_sub_metadata("node", child).unwrap();
641
642 let bytes = encode_metadata(&metadata);
643 let mut buffer = DecoderBuffer::new(&bytes);
644 let decoded = Metadata::decode(&mut buffer).unwrap();
645
646 assert_eq!(
647 decoded
648 .get_sub_metadata("node")
649 .and_then(|metadata| metadata.get_raw("child")),
650 Some(b"value".as_slice())
651 );
652 }
653
654 #[test]
655 fn geometry_metadata_roundtrips_attribute_metadata() {
656 let mut attribute = Metadata::new();
657 attribute.set_raw("semantic", b"POSITION".to_vec()).unwrap();
658
659 let mut geometry = GeometryMetadata::new();
660 geometry.set_attribute_metadata(7, attribute);
661 geometry
662 .metadata_mut()
663 .set_raw("asset", b"fixture".to_vec())
664 .unwrap();
665
666 let mut bytes = EncoderBuffer::new();
667 geometry.encode(&mut bytes).unwrap();
668
669 let mut buffer = DecoderBuffer::new(bytes.data());
670 let decoded = GeometryMetadata::decode(&mut buffer).unwrap();
671
672 assert_eq!(
673 decoded.metadata().get_raw("asset"),
674 Some(b"fixture".as_slice())
675 );
676 assert_eq!(
677 decoded
678 .attribute_metadata_by_unique_id(7)
679 .and_then(|metadata| metadata.metadata().get_raw("semantic")),
680 Some(b"POSITION".as_slice())
681 );
682 }
683
684 #[test]
685 fn geometry_metadata_finds_attribute_metadata_by_string_entry() {
686 let mut invalid_string = Metadata::new();
687 invalid_string.set_raw("name", vec![0xff]).unwrap();
688
689 let mut position = Metadata::new();
690 position.set_string("name", "position").unwrap();
691
692 let mut geometry = GeometryMetadata::new();
693 geometry.set_attribute_metadata(3, invalid_string);
694 geometry.set_attribute_metadata(7, position);
695
696 assert_eq!(
697 geometry
698 .attribute_metadata_by_string_entry("name", "position")
699 .map(AttributeMetadata::attribute_unique_id),
700 Some(7)
701 );
702 assert!(geometry
703 .attribute_metadata_by_string_entry("name", "normal")
704 .is_none());
705 }
706
707 #[test]
708 fn metadata_set_raw_overwrites_existing_entry() {
709 let mut metadata = Metadata::new();
710 metadata.set_raw("key", b"old".to_vec()).unwrap();
711 metadata.set_raw("key", b"new".to_vec()).unwrap();
712
713 assert_eq!(metadata.get_raw("key"), Some(b"new".as_slice()));
714 }
715
716 #[test]
717 fn metadata_decode_rejects_duplicate_sub_metadata() {
718 let bytes = [
719 0, 2, 1, b'a', 0, 0, 1, b'a', 0, 0, ];
723 let mut buffer = DecoderBuffer::new(&bytes);
724
725 assert!(Metadata::decode(&mut buffer).is_err());
726 }
727
728 #[test]
729 fn metadata_decode_rejects_zero_length_entry_value() {
730 let bytes = [1, 1, b'a', 0, 0];
731 let mut buffer = DecoderBuffer::new(&bytes);
732
733 assert!(Metadata::decode(&mut buffer).is_err());
734 }
735
736 #[test]
737 fn metadata_decode_rejects_truncated_name() {
738 let bytes = [1, 5, b'a'];
739 let mut buffer = DecoderBuffer::new(&bytes);
740
741 assert!(Metadata::decode(&mut buffer).is_err());
742 }
743
744 #[test]
745 fn metadata_decode_rejects_truncated_value() {
746 let bytes = [1, 1, b'a', 4, 1, 2];
747 let mut buffer = DecoderBuffer::new(&bytes);
748
749 assert!(Metadata::decode(&mut buffer).is_err());
750 }
751
752 #[test]
753 fn metadata_decode_rejects_unreasonable_sub_metadata_count() {
754 let bytes = [0, 5];
755 let mut buffer = DecoderBuffer::new(&bytes);
756
757 assert!(Metadata::decode(&mut buffer).is_err());
758 }
759
760 #[test]
761 fn metadata_decode_rejects_excessive_nesting() {
762 let mut bytes = Vec::new();
763 for _ in 0..=MAX_METADATA_NESTING_DEPTH {
764 bytes.extend_from_slice(&[0, 1, 1, b'a']);
765 }
766 bytes.extend_from_slice(&[0, 0]);
767
768 let mut buffer = DecoderBuffer::new(&bytes);
769 assert!(Metadata::decode(&mut buffer).is_err());
770 }
771}