1use aws_smithy_schema::serde::{capped_container_size, SerdeError, ShapeDeserializer};
9use aws_smithy_schema::Schema;
10use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
11
12use crate::data::Type;
13
14pub struct CborDeserializer<'a> {
20 decoder: crate::Decoder<'a>,
21 input_len: usize,
22 depth: u32,
23 max_depth: u32,
24}
25
26impl<'a> CborDeserializer<'a> {
27 pub(crate) fn new(input: &'a [u8], max_depth: u32) -> Self {
28 Self {
29 decoder: crate::Decoder::new(input),
30 input_len: input.len(),
31 depth: 0,
32 max_depth,
33 }
34 }
35
36 fn check_depth(&mut self) -> Result<(), SerdeError> {
37 self.depth += 1;
38 if self.depth > self.max_depth {
39 return Err(SerdeError::custom("maximum nesting depth exceeded"));
40 }
41 Ok(())
42 }
43
44 fn is_break(&self) -> bool {
46 matches!(self.decoder.datatype(), Ok(Type::Break))
47 }
48
49 fn consume_break(&mut self) -> Result<(), SerdeError> {
51 self.decoder.skip().map_err(deser_err)
52 }
53
54 fn read_list_items<T>(
57 &mut self,
58 mut read_element: impl FnMut(&mut crate::Decoder<'_>) -> Result<T, SerdeError>,
59 ) -> Result<Vec<T>, SerdeError> {
60 self.check_depth()?;
61 let len = self.decoder.list().map_err(deser_err)?;
62 let is_indefinite = len.is_none();
63 let count = len.unwrap_or(0) as usize;
64 let mut out = Vec::with_capacity(capped_container_size(count));
65 let mut i = 0;
66 loop {
67 if !is_indefinite && i >= count {
68 break;
69 }
70 if is_indefinite && self.is_break() {
71 self.consume_break()?;
72 break;
73 }
74 out.push(read_element(&mut self.decoder)?);
75 i += 1;
76 }
77 self.depth -= 1;
78 Ok(out)
79 }
80}
81
82impl ShapeDeserializer for CborDeserializer<'_> {
83 fn read_struct(
84 &mut self,
85 schema: &Schema,
86 consumer: &mut dyn FnMut(&Schema, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
87 ) -> Result<(), SerdeError> {
88 if self.decoder.position() >= self.input_len {
90 return Ok(());
91 }
92 self.check_depth()?;
93 let len = self.decoder.map().map_err(deser_err)?;
94 let is_indefinite = len.is_none();
95 let count = len.unwrap_or(0) as usize;
96
97 let mut i = 0;
98 loop {
99 if !is_indefinite && i >= count {
100 break;
101 }
102 if is_indefinite && self.is_break() {
103 self.consume_break()?;
104 break;
105 }
106 let key = self.decoder.str().map_err(deser_err)?;
107 if let Some(member_schema) = schema.member_schema(&key) {
108 consumer(member_schema, self)?;
109 } else {
110 self.decoder.skip().map_err(deser_err)?;
111 }
112 i += 1;
113 }
114 self.depth -= 1;
115 Ok(())
116 }
117
118 fn read_list(
119 &mut self,
120 _schema: &Schema,
121 consumer: &mut dyn FnMut(&mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
122 ) -> Result<(), SerdeError> {
123 self.check_depth()?;
124 let len = self.decoder.list().map_err(deser_err)?;
125 let is_indefinite = len.is_none();
126 let count = len.unwrap_or(0) as usize;
127
128 let mut i = 0;
129 loop {
130 if !is_indefinite && i >= count {
131 break;
132 }
133 if is_indefinite && self.is_break() {
134 self.consume_break()?;
135 break;
136 }
137 consumer(self)?;
138 i += 1;
139 }
140 self.depth -= 1;
141 Ok(())
142 }
143
144 fn read_map(
145 &mut self,
146 _schema: &Schema,
147 consumer: &mut dyn FnMut(String, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
148 ) -> Result<(), SerdeError> {
149 self.check_depth()?;
150 let len = self.decoder.map().map_err(deser_err)?;
151 let is_indefinite = len.is_none();
152 let count = len.unwrap_or(0) as usize;
153
154 let mut i = 0;
155 loop {
156 if !is_indefinite && i >= count {
157 break;
158 }
159 if is_indefinite && self.is_break() {
160 self.consume_break()?;
161 break;
162 }
163 let key = self.decoder.str().map_err(deser_err)?.into_owned();
164 consumer(key, self)?;
165 i += 1;
166 }
167 self.depth -= 1;
168 Ok(())
169 }
170
171 fn read_boolean(&mut self, _schema: &Schema) -> Result<bool, SerdeError> {
172 self.decoder.boolean().map_err(deser_err)
173 }
174
175 fn read_byte(&mut self, _schema: &Schema) -> Result<i8, SerdeError> {
176 self.decoder.byte().map_err(deser_err)
177 }
178
179 fn read_short(&mut self, _schema: &Schema) -> Result<i16, SerdeError> {
180 self.decoder.short().map_err(deser_err)
181 }
182
183 fn read_integer(&mut self, _schema: &Schema) -> Result<i32, SerdeError> {
184 self.decoder.integer().map_err(deser_err)
185 }
186
187 fn read_long(&mut self, _schema: &Schema) -> Result<i64, SerdeError> {
188 self.decoder.long().map_err(deser_err)
189 }
190
191 fn read_float(&mut self, _schema: &Schema) -> Result<f32, SerdeError> {
192 self.decoder.float().map_err(deser_err)
193 }
194
195 fn read_double(&mut self, _schema: &Schema) -> Result<f64, SerdeError> {
196 self.decoder.double().map_err(deser_err)
197 }
198
199 fn read_big_integer(&mut self, _schema: &Schema) -> Result<BigInteger, SerdeError> {
200 Err(SerdeError::UnsupportedOperation {
201 message: "CBOR big integer not yet supported (smithy-rs#4611)".into(),
202 })
203 }
204
205 fn read_big_decimal(&mut self, _schema: &Schema) -> Result<BigDecimal, SerdeError> {
206 Err(SerdeError::UnsupportedOperation {
207 message: "CBOR big decimal not yet supported (smithy-rs#4611)".into(),
208 })
209 }
210
211 fn read_string(&mut self, _schema: &Schema) -> Result<String, SerdeError> {
212 self.decoder
213 .str()
214 .map(|cow| cow.into_owned())
215 .map_err(deser_err)
216 }
217
218 fn read_blob(&mut self, _schema: &Schema) -> Result<Blob, SerdeError> {
219 self.decoder.blob().map_err(deser_err)
220 }
221
222 fn read_timestamp(&mut self, _schema: &Schema) -> Result<DateTime, SerdeError> {
223 self.decoder.timestamp().map_err(deser_err)
224 }
225
226 fn read_document(&mut self, _schema: &Schema) -> Result<Document, SerdeError> {
227 Err(SerdeError::UnsupportedOperation {
228 message: "document types are not supported by rpcv2Cbor protocol".into(),
229 })
230 }
231
232 fn is_null(&self) -> bool {
233 matches!(self.decoder.datatype(), Ok(Type::Null))
234 }
235
236 fn read_null(&mut self) -> Result<(), SerdeError> {
237 self.decoder.null().map_err(deser_err)
238 }
239
240 fn container_size(&self) -> Option<usize> {
241 let mut peek = self.decoder.clone();
242 match peek.datatype().ok()? {
243 Type::Array | Type::ArrayIndef => {
244 peek.list().ok()?.map(|n| capped_container_size(n as usize))
245 }
246 Type::Map | Type::MapIndef => {
247 peek.map().ok()?.map(|n| capped_container_size(n as usize))
248 }
249 _ => None,
250 }
251 }
252
253 fn read_string_list(&mut self, _schema: &Schema) -> Result<Vec<String>, SerdeError> {
254 self.read_list_items(|dec| dec.str().map(|c| c.into_owned()).map_err(deser_err))
255 }
256
257 fn read_blob_list(&mut self, _schema: &Schema) -> Result<Vec<Blob>, SerdeError> {
258 self.read_list_items(|dec| dec.blob().map_err(deser_err))
259 }
260
261 fn read_integer_list(&mut self, _schema: &Schema) -> Result<Vec<i32>, SerdeError> {
262 self.read_list_items(|dec| dec.integer().map_err(deser_err))
263 }
264
265 fn read_long_list(&mut self, _schema: &Schema) -> Result<Vec<i64>, SerdeError> {
266 self.read_list_items(|dec| dec.long().map_err(deser_err))
267 }
268
269 fn read_string_string_map(
270 &mut self,
271 _schema: &Schema,
272 ) -> Result<std::collections::HashMap<String, String>, SerdeError> {
273 self.check_depth()?;
274 let len = self.decoder.map().map_err(deser_err)?;
275 let is_indefinite = len.is_none();
276 let count = len.unwrap_or(0) as usize;
277 let mut out = std::collections::HashMap::with_capacity(capped_container_size(count));
278 let mut i = 0;
279 loop {
280 if !is_indefinite && i >= count {
281 break;
282 }
283 if is_indefinite && self.is_break() {
284 self.consume_break()?;
285 break;
286 }
287 let key = self
288 .decoder
289 .str()
290 .map(|c| c.into_owned())
291 .map_err(deser_err)?;
292 let val = self
293 .decoder
294 .str()
295 .map(|c| c.into_owned())
296 .map_err(deser_err)?;
297 out.insert(key, val);
298 i += 1;
299 }
300 self.depth -= 1;
301 Ok(out)
302 }
303}
304
305fn deser_err(e: crate::decode::DeserializeError) -> SerdeError {
306 SerdeError::InvalidInput {
307 message: e.to_string(),
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314 use aws_smithy_schema::codec::Codec;
315 use aws_smithy_schema::prelude::*;
316 use aws_smithy_schema::serde::{SerializableStruct, ShapeSerializer};
317 use aws_smithy_schema::{shape_id, ShapeType};
318
319 use crate::codec::CborCodec;
320
321 fn make_deser(f: impl FnOnce(&mut crate::codec::CborSerializer)) -> Vec<u8> {
323 use aws_smithy_schema::codec::FinishSerializer;
324 let codec = CborCodec::default();
325 let mut ser = codec.create_serializer();
326 f(&mut ser);
327 ser.finish()
328 }
329
330 #[test]
331 fn test_read_boolean() {
332 let bytes = make_deser(|s| s.write_boolean(&BOOLEAN, true).unwrap());
333 let mut de = CborDeserializer::new(&bytes, 128);
334 assert_eq!(de.read_boolean(&BOOLEAN).unwrap(), true);
335 }
336
337 #[test]
338 fn test_read_byte() {
339 let bytes = make_deser(|s| s.write_byte(&BYTE, -42).unwrap());
340 let mut de = CborDeserializer::new(&bytes, 128);
341 assert_eq!(de.read_byte(&BYTE).unwrap(), -42);
342 }
343
344 #[test]
345 fn test_read_short() {
346 let bytes = make_deser(|s| s.write_short(&SHORT, 1234).unwrap());
347 let mut de = CborDeserializer::new(&bytes, 128);
348 assert_eq!(de.read_short(&SHORT).unwrap(), 1234);
349 }
350
351 #[test]
352 fn test_read_integer() {
353 let bytes = make_deser(|s| s.write_integer(&INTEGER, -99999).unwrap());
354 let mut de = CborDeserializer::new(&bytes, 128);
355 assert_eq!(de.read_integer(&INTEGER).unwrap(), -99999);
356 }
357
358 #[test]
359 fn test_read_long() {
360 let bytes = make_deser(|s| s.write_long(&LONG, i64::MIN).unwrap());
361 let mut de = CborDeserializer::new(&bytes, 128);
362 assert_eq!(de.read_long(&LONG).unwrap(), i64::MIN);
363 }
364
365 #[test]
366 fn test_read_float_nan() {
367 let bytes = make_deser(|s| s.write_float(&FLOAT, f32::NAN).unwrap());
368 let mut de = CborDeserializer::new(&bytes, 128);
369 assert!(de.read_float(&FLOAT).unwrap().is_nan());
370 }
371
372 #[test]
373 fn test_read_double_neg_infinity() {
374 let bytes = make_deser(|s| s.write_double(&DOUBLE, f64::NEG_INFINITY).unwrap());
375 let mut de = CborDeserializer::new(&bytes, 128);
376 assert_eq!(de.read_double(&DOUBLE).unwrap(), f64::NEG_INFINITY);
377 }
378
379 #[test]
380 fn test_read_string() {
381 let bytes = make_deser(|s| s.write_string(&STRING, "hello world").unwrap());
382 let mut de = CborDeserializer::new(&bytes, 128);
383 assert_eq!(de.read_string(&STRING).unwrap(), "hello world");
384 }
385
386 #[test]
387 fn test_read_blob() {
388 let blob = Blob::new(b"binary");
389 let bytes = make_deser(|s| s.write_blob(&BLOB, blob.as_ref()).unwrap());
390 let mut de = CborDeserializer::new(&bytes, 128);
391 assert_eq!(de.read_blob(&BLOB).unwrap(), blob);
392 }
393
394 #[test]
395 fn test_read_timestamp() {
396 let ts = DateTime::from_secs_f64(1700000000.123);
397 let bytes = make_deser(|s| s.write_timestamp(&TIMESTAMP, &ts).unwrap());
398 let mut de = CborDeserializer::new(&bytes, 128);
399 let decoded = de.read_timestamp(&TIMESTAMP).unwrap();
400 assert_eq!(decoded.subsec_nanos() % 1_000_000, 0);
402 }
403
404 #[test]
405 fn test_is_null() {
406 let bytes = make_deser(|s| s.write_null(&STRING).unwrap());
407 let de = CborDeserializer::new(&bytes, 128);
408 assert!(de.is_null());
409 }
410
411 #[test]
412 fn test_read_null() {
413 let bytes = make_deser(|s| s.write_null(&STRING).unwrap());
414 let mut de = CborDeserializer::new(&bytes, 128);
415 de.read_null().unwrap();
416 }
417
418 #[test]
419 fn test_read_struct() {
420 static NAME: Schema =
421 Schema::new_member(shape_id!("test", "S"), ShapeType::String, "name", 0);
422 static AGE: Schema =
423 Schema::new_member(shape_id!("test", "S"), ShapeType::Integer, "age", 1);
424 static SCHEMA: Schema =
425 Schema::new_struct(shape_id!("test", "S"), ShapeType::Structure, &[&NAME, &AGE]);
426
427 struct TestStruct;
428 impl SerializableStruct for TestStruct {
429 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
430 s.write_string(&NAME, "Bob")?;
431 s.write_integer(&AGE, 25)?;
432 Ok(())
433 }
434 }
435
436 let bytes = make_deser(|s| s.write_struct(&SCHEMA, &TestStruct).unwrap());
437 let mut de = CborDeserializer::new(&bytes, 128);
438 let mut name = String::new();
439 let mut age = 0i32;
440 de.read_struct(&SCHEMA, &mut |member, d| {
441 match member.member_name() {
442 Some("name") => name = d.read_string(member)?,
443 Some("age") => age = d.read_integer(member)?,
444 _ => {}
445 }
446 Ok(())
447 })
448 .unwrap();
449 assert_eq!(name, "Bob");
450 assert_eq!(age, 25);
451 }
452
453 #[test]
454 fn test_read_struct_unknown_members_skipped() {
455 let mut enc = crate::Encoder::new(Vec::new());
457 enc.begin_map()
458 .str("name")
459 .str("Alice")
460 .str("unknown_field")
461 .integer(999)
462 .str("age")
463 .integer(30)
464 .end();
465 let bytes = enc.into_writer();
466
467 static NAME: Schema =
468 Schema::new_member(shape_id!("test", "S"), ShapeType::String, "name", 0);
469 static AGE: Schema =
470 Schema::new_member(shape_id!("test", "S"), ShapeType::Integer, "age", 1);
471 static SCHEMA: Schema =
472 Schema::new_struct(shape_id!("test", "S"), ShapeType::Structure, &[&NAME, &AGE]);
473
474 let mut de = CborDeserializer::new(&bytes, 128);
475 let mut name = String::new();
476 let mut age = 0i32;
477 de.read_struct(&SCHEMA, &mut |member, d| {
478 match member.member_name() {
479 Some("name") => name = d.read_string(member)?,
480 Some("age") => age = d.read_integer(member)?,
481 _ => {}
482 }
483 Ok(())
484 })
485 .unwrap();
486 assert_eq!(name, "Alice");
487 assert_eq!(age, 30);
488 }
489
490 #[test]
491 fn test_read_struct_definite_length_map() {
492 let mut enc = crate::Encoder::new(Vec::new());
494 enc.map(1).str("name").str("Charlie");
495 let bytes = enc.into_writer();
496
497 static NAME: Schema =
498 Schema::new_member(shape_id!("test", "S"), ShapeType::String, "name", 0);
499 static SCHEMA: Schema =
500 Schema::new_struct(shape_id!("test", "S"), ShapeType::Structure, &[&NAME]);
501
502 let mut de = CborDeserializer::new(&bytes, 128);
503 let mut name = String::new();
504 de.read_struct(&SCHEMA, &mut |member, d| {
505 if member.member_name() == Some("name") {
506 name = d.read_string(member)?;
507 }
508 Ok(())
509 })
510 .unwrap();
511 assert_eq!(name, "Charlie");
512 }
513
514 #[test]
515 fn test_read_list() {
516 let bytes = make_deser(|s| {
517 let schema = Schema::new(shape_id!("test", "L"), ShapeType::List);
518 s.write_list(&schema, &|s| {
519 s.write_integer(&INTEGER, 10)?;
520 s.write_integer(&INTEGER, 20)?;
521 Ok(())
522 })
523 .unwrap()
524 });
525 let list_schema = Schema::new(shape_id!("test", "L"), ShapeType::List);
526 let mut de = CborDeserializer::new(&bytes, 128);
527 let mut items = Vec::new();
528 de.read_list(&list_schema, &mut |d| {
529 items.push(d.read_integer(&INTEGER)?);
530 Ok(())
531 })
532 .unwrap();
533 assert_eq!(items, vec![10, 20]);
534 }
535
536 #[test]
537 fn test_read_map() {
538 let bytes = make_deser(|s| {
539 let schema = Schema::new(shape_id!("test", "M"), ShapeType::Map);
540 s.write_map(&schema, &|s| {
541 s.write_string(&STRING, "k1")?;
542 s.write_string(&STRING, "v1")?;
543 s.write_string(&STRING, "k2")?;
544 s.write_string(&STRING, "v2")?;
545 Ok(())
546 })
547 .unwrap()
548 });
549 let map_schema = Schema::new(shape_id!("test", "M"), ShapeType::Map);
550 let mut de = CborDeserializer::new(&bytes, 128);
551 let mut map = std::collections::HashMap::new();
552 de.read_map(&map_schema, &mut |key, d| {
553 map.insert(key, d.read_string(&STRING)?);
554 Ok(())
555 })
556 .unwrap();
557 assert_eq!(map.get("k1").unwrap(), "v1");
558 assert_eq!(map.get("k2").unwrap(), "v2");
559 }
560
561 #[test]
562 fn test_empty_input_treated_as_empty_struct() {
563 static SCHEMA: Schema =
564 Schema::new_struct(shape_id!("test", "S"), ShapeType::Structure, &[]);
565 let mut de = CborDeserializer::new(&[], 128);
566 de.read_struct(&SCHEMA, &mut |_, _| Ok(())).unwrap();
567 }
568
569 #[test]
570 fn test_container_size_definite() {
571 let mut enc = crate::Encoder::new(Vec::new());
572 enc.array(5);
573 let bytes = enc.into_writer();
574 let de = CborDeserializer::new(&bytes, 128);
575 assert_eq!(de.container_size(), Some(5));
576 }
577
578 #[test]
579 fn test_container_size_indefinite_returns_none() {
580 let mut enc = crate::Encoder::new(Vec::new());
581 enc.begin_array();
582 let bytes = enc.into_writer();
583 let de = CborDeserializer::new(&bytes, 128);
584 assert_eq!(de.container_size(), None);
585 }
586
587 #[test]
588 fn test_depth_limit_rejects_deeply_nested() {
589 let mut enc = crate::Encoder::new(Vec::new());
591 for _ in 0..200 {
592 enc.begin_map().str("a");
593 }
594 enc.begin_map().end(); for _ in 0..200 {
596 enc.end();
597 }
598 let bytes = enc.into_writer();
599
600 static MEMBER: Schema =
601 Schema::new_member(shape_id!("test", "R"), ShapeType::Structure, "a", 0);
602 static SCHEMA: Schema =
603 Schema::new_struct(shape_id!("test", "R"), ShapeType::Structure, &[&MEMBER]);
604
605 let mut de = CborDeserializer::new(&bytes, 128);
606 fn recursive_consumer(
607 _member: &Schema,
608 deser: &mut dyn ShapeDeserializer,
609 ) -> Result<(), SerdeError> {
610 static MEMBER: Schema =
611 Schema::new_member(shape_id!("test", "R"), ShapeType::Structure, "a", 0);
612 static SCHEMA: Schema =
613 Schema::new_struct(shape_id!("test", "R"), ShapeType::Structure, &[&MEMBER]);
614 deser.read_struct(&SCHEMA, &mut recursive_consumer)
615 }
616 let result = de.read_struct(&SCHEMA, &mut recursive_consumer);
617 assert!(result.is_err());
618 assert!(result.unwrap_err().to_string().contains("depth"));
619 }
620
621 #[test]
622 fn test_depth_limit_accepts_under_limit() {
623 let mut enc = crate::Encoder::new(Vec::new());
625 for _ in 0..10 {
626 enc.begin_map().str("a");
627 }
628 enc.begin_map().end();
629 for _ in 0..10 {
630 enc.end();
631 }
632 let bytes = enc.into_writer();
633
634 static MEMBER: Schema =
635 Schema::new_member(shape_id!("test", "R"), ShapeType::Structure, "a", 0);
636 static SCHEMA: Schema =
637 Schema::new_struct(shape_id!("test", "R"), ShapeType::Structure, &[&MEMBER]);
638
639 let mut de = CborDeserializer::new(&bytes, 128);
640 fn recursive_consumer(
641 _member: &Schema,
642 deser: &mut dyn ShapeDeserializer,
643 ) -> Result<(), SerdeError> {
644 static MEMBER: Schema =
645 Schema::new_member(shape_id!("test", "R"), ShapeType::Structure, "a", 0);
646 static SCHEMA: Schema =
647 Schema::new_struct(shape_id!("test", "R"), ShapeType::Structure, &[&MEMBER]);
648 deser.read_struct(&SCHEMA, &mut recursive_consumer)
649 }
650 de.read_struct(&SCHEMA, &mut recursive_consumer).unwrap();
651 }
652
653 #[test]
654 fn test_read_struct_with_null_optional_members() {
655 let mut enc = crate::Encoder::new(Vec::new());
657 enc.begin_map()
658 .str("name")
659 .str("Alice")
660 .str("age")
661 .null()
662 .end();
663 let bytes = enc.into_writer();
664
665 static NAME: Schema =
666 Schema::new_member(shape_id!("test", "S"), ShapeType::String, "name", 0);
667 static AGE: Schema =
668 Schema::new_member(shape_id!("test", "S"), ShapeType::Integer, "age", 1);
669 static SCHEMA: Schema =
670 Schema::new_struct(shape_id!("test", "S"), ShapeType::Structure, &[&NAME, &AGE]);
671
672 let mut de = CborDeserializer::new(&bytes, 128);
673 let mut name: Option<String> = None;
674 let mut age: Option<i32> = None;
675 de.read_struct(&SCHEMA, &mut |member, d| {
676 match member.member_name() {
677 Some("name") => {
678 if !d.is_null() {
679 name = Some(d.read_string(member)?);
680 } else {
681 d.read_null()?;
682 }
683 }
684 Some("age") => {
685 if !d.is_null() {
686 age = Some(d.read_integer(member)?);
687 } else {
688 d.read_null()?;
689 }
690 }
691 _ => {}
692 }
693 Ok(())
694 })
695 .unwrap();
696 assert_eq!(name, Some("Alice".to_string()));
697 assert_eq!(age, None);
698 }
699
700 #[test]
701 fn test_read_sparse_list_with_nulls() {
702 let mut enc = crate::Encoder::new(Vec::new());
704 enc.begin_array().integer(1).null().integer(3).end();
705 let bytes = enc.into_writer();
706
707 let list_schema = Schema::new(shape_id!("test", "L"), ShapeType::List);
708 let mut de = CborDeserializer::new(&bytes, 128);
709 let mut items: Vec<Option<i32>> = Vec::new();
710 de.read_list(&list_schema, &mut |d| {
711 if d.is_null() {
712 d.read_null()?;
713 items.push(None);
714 } else {
715 items.push(Some(d.read_integer(&INTEGER)?));
716 }
717 Ok(())
718 })
719 .unwrap();
720 assert_eq!(items, vec![Some(1), None, Some(3)]);
721 }
722
723 #[test]
724 fn test_read_sparse_map_with_nulls() {
725 let mut enc = crate::Encoder::new(Vec::new());
727 enc.begin_map().str("a").str("hello").str("b").null().end();
728 let bytes = enc.into_writer();
729
730 let map_schema = Schema::new(shape_id!("test", "M"), ShapeType::Map);
731 let mut de = CborDeserializer::new(&bytes, 128);
732 let mut map: std::collections::HashMap<String, Option<String>> =
733 std::collections::HashMap::new();
734 de.read_map(&map_schema, &mut |key, d| {
735 if d.is_null() {
736 d.read_null()?;
737 map.insert(key, None);
738 } else {
739 map.insert(key, Some(d.read_string(&STRING)?));
740 }
741 Ok(())
742 })
743 .unwrap();
744 assert_eq!(map.get("a"), Some(&Some("hello".to_string())));
745 assert_eq!(map.get("b"), Some(&None));
746 }
747}