1use aws_smithy_schema::codec::FinishSerializer;
9use aws_smithy_schema::serde::{SerdeError, SerializableStruct, ShapeSerializer};
10use aws_smithy_schema::Schema;
11use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
12
13#[derive(Clone, Copy, PartialEq, Eq)]
22enum Container {
23 Struct,
24 List,
25 Map,
26}
27
28pub type StructPrefix = fn(&Schema<'_>, &mut dyn ShapeSerializer) -> Result<(), SerdeError>;
35
36pub struct CborSerializer {
41 encoder: crate::Encoder,
42 container_stack: Vec<Container>,
43 struct_prefix: Option<StructPrefix>,
44 use_definite_lengths: bool,
45}
46
47impl CborSerializer {
48 pub(crate) fn new() -> Self {
49 Self {
50 encoder: crate::Encoder::new(Vec::new()),
51 container_stack: Vec::new(),
52 struct_prefix: None,
53 use_definite_lengths: false,
54 }
55 }
56
57 pub(crate) fn with_definite_lengths(mut self, value: bool) -> Self {
58 self.use_definite_lengths = value;
59 self
60 }
61
62 pub fn with_struct_prefix(mut self, prefix: StructPrefix) -> Self {
67 self.struct_prefix = Some(prefix);
68 self
69 }
70
71 #[inline]
75 fn write_member_key(&mut self, schema: &Schema<'_>) {
76 if self.container_stack.last() == Some(&Container::Struct) {
77 if let Some(name) = schema.member_name() {
78 self.encoder.str(name);
79 }
80 }
81 }
82}
83
84impl FinishSerializer for CborSerializer {
85 fn finish(self) -> Vec<u8> {
86 self.encoder.into_writer()
87 }
88}
89
90impl ShapeSerializer for CborSerializer {
91 fn write_struct(
92 &mut self,
93 schema: &Schema<'_>,
94 value: &dyn SerializableStruct,
95 ) -> Result<(), SerdeError> {
96 self.write_member_key(schema);
97 self.encoder.begin_map();
98 self.container_stack.push(Container::Struct);
99 if let Some(prefix) = self.struct_prefix {
100 prefix(value.schema(), self)?;
101 }
102 value.serialize_members(self)?;
103 self.container_stack.pop();
104 self.encoder.end();
105 Ok(())
106 }
107
108 fn write_list(
109 &mut self,
110 schema: &Schema<'_>,
111 write_elements: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
112 ) -> Result<(), SerdeError> {
113 self.write_member_key(schema);
114 self.encoder.begin_array();
115 self.container_stack.push(Container::List);
116 write_elements(self)?;
117 self.container_stack.pop();
118 self.encoder.end();
119 Ok(())
120 }
121
122 fn write_map(
123 &mut self,
124 schema: &Schema<'_>,
125 write_entries: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
126 ) -> Result<(), SerdeError> {
127 self.write_member_key(schema);
128 self.encoder.begin_map();
129 self.container_stack.push(Container::Map);
130 write_entries(self)?;
131 self.container_stack.pop();
132 self.encoder.end();
133 Ok(())
134 }
135
136 fn write_list_with_length(
137 &mut self,
138 schema: &Schema<'_>,
139 length: usize,
140 write_elements: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
141 ) -> Result<(), SerdeError> {
142 if !self.use_definite_lengths {
143 return self.write_list(schema, write_elements);
144 }
145 self.write_member_key(schema);
146 self.encoder.array(length);
147 self.container_stack.push(Container::List);
148 let result = write_elements(self);
149 self.container_stack.pop();
150 result
151 }
152
153 fn write_map_with_length(
154 &mut self,
155 schema: &Schema<'_>,
156 length: usize,
157 write_entries: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
158 ) -> Result<(), SerdeError> {
159 if !self.use_definite_lengths {
160 return self.write_map(schema, write_entries);
161 }
162 self.write_member_key(schema);
163 self.encoder.map(length);
164 self.container_stack.push(Container::Map);
165 let result = write_entries(self);
166 self.container_stack.pop();
167 result
168 }
169
170 fn write_boolean(&mut self, schema: &Schema<'_>, value: bool) -> Result<(), SerdeError> {
171 self.write_member_key(schema);
172 self.encoder.boolean(value);
173 Ok(())
174 }
175
176 fn write_byte(&mut self, schema: &Schema<'_>, value: i8) -> Result<(), SerdeError> {
177 self.write_member_key(schema);
178 self.encoder.byte(value);
179 Ok(())
180 }
181
182 fn write_short(&mut self, schema: &Schema<'_>, value: i16) -> Result<(), SerdeError> {
183 self.write_member_key(schema);
184 self.encoder.short(value);
185 Ok(())
186 }
187
188 fn write_integer(&mut self, schema: &Schema<'_>, value: i32) -> Result<(), SerdeError> {
189 self.write_member_key(schema);
190 self.encoder.integer(value);
191 Ok(())
192 }
193
194 fn write_integer_list(
195 &mut self,
196 schema: &Schema<'_>,
197 values: &[i32],
198 ) -> Result<(), SerdeError> {
199 self.write_member_key(schema);
200 if self.use_definite_lengths {
201 self.encoder.array(values.len());
202 } else {
203 self.encoder.begin_array();
204 }
205 for value in values {
208 self.encoder.integer(*value);
209 }
210 if !self.use_definite_lengths {
211 self.encoder.end();
212 }
213 Ok(())
214 }
215
216 fn write_long(&mut self, schema: &Schema<'_>, value: i64) -> Result<(), SerdeError> {
217 self.write_member_key(schema);
218 self.encoder.long(value);
219 Ok(())
220 }
221
222 fn write_float(&mut self, schema: &Schema<'_>, value: f32) -> Result<(), SerdeError> {
223 self.write_member_key(schema);
224 self.encoder.float(value);
225 Ok(())
226 }
227
228 fn write_double(&mut self, schema: &Schema<'_>, value: f64) -> Result<(), SerdeError> {
229 self.write_member_key(schema);
230 self.encoder.double(value);
231 Ok(())
232 }
233
234 fn write_big_integer(
235 &mut self,
236 schema: &Schema<'_>,
237 value: &BigInteger,
238 ) -> Result<(), SerdeError> {
239 self.write_member_key(schema);
240 self.encoder.big_integer(value);
241 Ok(())
242 }
243
244 fn write_big_decimal(
245 &mut self,
246 schema: &Schema<'_>,
247 value: &BigDecimal,
248 ) -> Result<(), SerdeError> {
249 self.write_member_key(schema);
250 self.encoder.big_decimal(value);
251 Ok(())
252 }
253
254 fn write_string(&mut self, schema: &Schema<'_>, value: &str) -> Result<(), SerdeError> {
255 self.write_member_key(schema);
256 self.encoder.str(value);
257 Ok(())
258 }
259
260 fn write_blob(&mut self, schema: &Schema<'_>, value: Blob) -> Result<(), SerdeError> {
261 self.write_member_key(schema);
262 self.encoder.blob_bytes(value.as_ref());
263 Ok(())
264 }
265
266 fn write_timestamp(&mut self, schema: &Schema<'_>, value: &DateTime) -> Result<(), SerdeError> {
267 self.write_member_key(schema);
268 self.encoder.timestamp(value);
269 Ok(())
270 }
271
272 fn write_document(
273 &mut self,
274 _schema: &Schema<'_>,
275 _value: &Document,
276 ) -> Result<(), SerdeError> {
277 Err(SerdeError::unsupported(
278 "document types are not supported by rpcv2Cbor protocol",
279 ))
280 }
281
282 fn write_null(&mut self, schema: &Schema<'_>) -> Result<(), SerdeError> {
283 self.write_member_key(schema);
284 self.encoder.null();
285 Ok(())
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292 use aws_smithy_schema::codec::{Codec, FinishSerializer};
293 use aws_smithy_schema::prelude::*;
294 use aws_smithy_schema::serde::ShapeSerializer;
295 use aws_smithy_schema::{shape_id, ShapeType};
296 use aws_smithy_types::Blob;
297
298 use crate::codec::CborCodec;
299
300 fn round_trip(f: impl FnOnce(&mut CborSerializer)) -> Vec<u8> {
301 let codec = CborCodec::default();
302 let mut ser = codec.create_serializer();
303 f(&mut ser);
304 ser.finish()
305 }
306
307 #[test]
308 fn test_write_boolean() {
309 let bytes = round_trip(|s| s.write_boolean(&BOOLEAN, true).unwrap());
310 let mut dec = crate::Decoder::new(&bytes);
311 assert!(dec.boolean().unwrap());
312 }
313
314 #[test]
315 fn test_write_integer() {
316 let bytes = round_trip(|s| s.write_integer(&INTEGER, 42).unwrap());
317 let mut dec = crate::Decoder::new(&bytes);
318 assert_eq!(dec.integer().unwrap(), 42);
319 }
320
321 #[test]
322 fn test_write_long() {
323 let bytes = round_trip(|s| s.write_long(&LONG, i64::MAX).unwrap());
324 let mut dec = crate::Decoder::new(&bytes);
325 assert_eq!(dec.long().unwrap(), i64::MAX);
326 }
327
328 #[test]
329 fn test_write_float_nan() {
330 let bytes = round_trip(|s| s.write_float(&FLOAT, f32::NAN).unwrap());
331 let mut dec = crate::Decoder::new(&bytes);
332 assert!(dec.float().unwrap().is_nan());
333 }
334
335 #[test]
336 fn test_write_double_infinity() {
337 let bytes = round_trip(|s| s.write_double(&DOUBLE, f64::INFINITY).unwrap());
338 let mut dec = crate::Decoder::new(&bytes);
339 assert_eq!(dec.double().unwrap(), f64::INFINITY);
340 }
341
342 #[test]
343 fn test_write_big_integer() {
344 let value = "18446744073709551616".parse().unwrap();
345 let bytes = round_trip(|s| s.write_big_integer(&BIG_INTEGER, &value).unwrap());
346 let mut dec = crate::Decoder::new(&bytes);
347 assert_eq!(dec.big_integer().unwrap(), value);
348 }
349
350 #[test]
351 fn test_write_big_decimal() {
352 let value = "273.15".parse().unwrap();
353 let bytes = round_trip(|s| s.write_big_decimal(&BIG_DECIMAL, &value).unwrap());
354 let mut dec = crate::Decoder::new(&bytes);
355 assert_eq!(dec.big_decimal().unwrap(), value);
356 }
357
358 #[test]
359 fn test_write_string() {
360 let bytes = round_trip(|s| s.write_string(&STRING, "hello").unwrap());
361 let mut dec = crate::Decoder::new(&bytes);
362 assert_eq!(dec.str().unwrap().as_ref(), "hello");
363 }
364
365 #[test]
366 fn test_write_blob() {
367 let blob = Blob::new(b"binary data");
368 let bytes = round_trip(|s| s.write_blob(&BLOB, blob.clone()).unwrap());
369 let mut dec = crate::Decoder::new(&bytes);
370 assert_eq!(dec.blob().unwrap(), blob);
371 }
372
373 #[test]
374 fn test_write_timestamp() {
375 let ts = DateTime::from_secs_f64(1700000000.5);
376 let bytes = round_trip(|s| s.write_timestamp(&TIMESTAMP, &ts).unwrap());
377 let mut dec = crate::Decoder::new(&bytes);
378 let decoded = dec.timestamp().unwrap();
379 assert_eq!(decoded.as_secs_f64(), 1700000000.5);
381 }
382
383 #[test]
384 fn test_write_null() {
385 let bytes = round_trip(|s| s.write_null(&STRING).unwrap());
386 let mut dec = crate::Decoder::new(&bytes);
387 dec.null().unwrap();
388 }
389
390 #[test]
391 fn test_write_list() {
392 let list_schema = Schema::new(shape_id!("test", "List"), ShapeType::List);
393 let bytes = round_trip(|s| {
394 s.write_list(&list_schema, &|s| {
395 s.write_integer(&INTEGER, 1)?;
396 s.write_integer(&INTEGER, 2)?;
397 s.write_integer(&INTEGER, 3)?;
398 Ok(())
399 })
400 .unwrap()
401 });
402 let mut dec = crate::Decoder::new(&bytes);
403 let len = dec.list().unwrap();
405 assert!(len.is_none()); assert_eq!(dec.integer().unwrap(), 1);
407 assert_eq!(dec.integer().unwrap(), 2);
408 assert_eq!(dec.integer().unwrap(), 3);
409 }
410
411 #[test]
412 fn known_collection_lengths_are_opt_in() {
413 let schema = Schema::new(shape_id!("test", "List"), ShapeType::List);
414 for (enabled, expected) in [
415 (false, vec![0x9f, 1, 2, 3, 0xff]),
416 (true, vec![0x83, 1, 2, 3]),
417 ] {
418 let codec = CborCodec::new(
419 crate::codec::CborCodecSettings::default().use_definite_lengths(enabled),
420 );
421 let mut ser = codec.create_serializer();
422 ser.write_integer_list(&schema, &[1, 2, 3]).unwrap();
423 assert_eq!(ser.finish(), expected);
424 }
425 }
426
427 #[test]
428 fn integer_list_helper_matches_generic_writes_in_each_container() {
429 static VALUES: Schema = Schema::new_member(
430 shape_id!("test", "Value", "values"),
431 ShapeType::List,
432 "values",
433 0,
434 );
435 static NESTED: Schema = Schema::new_member(
436 shape_id!("test", "Value", "nested"),
437 ShapeType::List,
438 "nested",
439 1,
440 );
441 static MAP: Schema =
442 Schema::new_member(shape_id!("test", "Value", "map"), ShapeType::Map, "map", 2);
443 static AFTER: Schema = Schema::new_member(
444 shape_id!("test", "Value", "after"),
445 ShapeType::Integer,
446 "after",
447 3,
448 );
449 static VALUE: Schema = Schema::new_struct(
450 shape_id!("test", "Value"),
451 ShapeType::Structure,
452 &[&VALUES, &NESTED, &MAP, &AFTER],
453 );
454
455 struct Value<'a> {
456 values: &'a [i32],
457 helper: bool,
458 }
459 impl Value<'_> {
460 fn write_values(
461 &self,
462 ser: &mut dyn ShapeSerializer,
463 schema: &Schema<'_>,
464 ) -> Result<(), SerdeError> {
465 if self.helper {
466 ser.write_integer_list(schema, self.values)
467 } else {
468 ser.write_list_with_length(schema, self.values.len(), &|ser| {
469 for value in self.values {
470 ser.write_integer(&INTEGER, *value)?;
471 }
472 Ok(())
473 })
474 }
475 }
476 }
477 impl SerializableStruct for Value<'_> {
478 fn schema(&self) -> &Schema<'_> {
479 &VALUE
480 }
481
482 fn serialize_members(&self, ser: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
483 self.write_values(ser, &VALUES)?;
484 ser.write_list_with_length(&NESTED, 1, &|ser| self.write_values(ser, &VALUES))?;
485 ser.write_map_with_length(&MAP, 1, &|ser| {
486 ser.write_string(&STRING, "key")?;
487 self.write_values(ser, &VALUES)
488 })?;
489 ser.write_integer(&AFTER, 17)
490 }
491 }
492
493 let integers = [i32::MIN, -25, -1, 0, 23, 24, i32::MAX];
494 for enabled in [false, true] {
495 let codec = CborCodec::new(
496 crate::codec::CborCodecSettings::default().use_definite_lengths(enabled),
497 );
498 for length in [0, 1, 23, 24, 255, 256] {
499 let values: Vec<_> = integers.into_iter().cycle().take(length).collect();
500 let mut generic = codec.create_serializer();
501 generic
502 .write_struct(
503 &VALUE,
504 &Value {
505 values: &values,
506 helper: false,
507 },
508 )
509 .unwrap();
510 let mut helper = codec.create_serializer();
511 helper
512 .write_struct(
513 &VALUE,
514 &Value {
515 values: &values,
516 helper: true,
517 },
518 )
519 .unwrap();
520 assert_eq!(
521 helper.finish(),
522 generic.finish(),
523 "enabled={enabled}, length={length}"
524 );
525
526 let mut helper = codec.create_serializer();
528 helper.write_integer_list(&VALUES, &values).unwrap();
529 let mut encoder = crate::Encoder::new(Vec::new());
530 if enabled {
531 encoder.array(length);
532 } else {
533 encoder.begin_array();
534 }
535 for value in &values {
536 encoder.integer(*value);
537 }
538 if !enabled {
539 encoder.end();
540 }
541 assert_eq!(helper.finish(), encoder.into_writer());
542 }
543 }
544 }
545
546 #[test]
547 fn definite_collections_match_legacy_encoder_at_length_boundaries() {
548 let list = Schema::new(shape_id!("test", "List"), ShapeType::List);
549 let map = Schema::new(shape_id!("test", "Map"), ShapeType::Map);
550 let codec =
551 CborCodec::new(crate::codec::CborCodecSettings::default().use_definite_lengths(true));
552 for length in [0, 1, 23, 24, 255, 256] {
553 let mut ser = codec.create_serializer();
554 ser.write_list_with_length(&list, length, &|ser| {
555 for _ in 0..length {
556 ser.write_null(&STRING)?;
557 }
558 Ok(())
559 })
560 .unwrap();
561 let mut legacy = crate::Encoder::new(Vec::new());
562 legacy.array(length);
563 for _ in 0..length {
564 legacy.null();
565 }
566 assert_eq!(ser.finish(), legacy.into_writer());
567
568 let mut ser = codec.create_serializer();
569 ser.write_map_with_length(&map, length, &|ser| {
570 for i in 0..length {
571 ser.write_string(&STRING, &i.to_string())?;
572 ser.write_null(&STRING)?;
573 }
574 Ok(())
575 })
576 .unwrap();
577 let mut legacy = crate::Encoder::new(Vec::new());
578 legacy.map(length);
579 for i in 0..length {
580 legacy.str(&i.to_string()).null();
581 }
582 assert_eq!(ser.finish(), legacy.into_writer());
583 }
584 }
585
586 #[test]
587 fn definite_nested_collections_preserve_keys_and_unknown_lengths() {
588 static VALUES: Schema = Schema::new_member(
589 shape_id!("test", "Value", "values"),
590 ShapeType::List,
591 "values",
592 0,
593 );
594 static MAP: Schema = Schema::new(shape_id!("test", "Map"), ShapeType::Map);
595 static VALUE: Schema =
596 Schema::new_struct(shape_id!("test", "Value"), ShapeType::Structure, &[&VALUES]);
597 struct Value;
598 impl SerializableStruct for Value {
599 fn schema(&self) -> &Schema<'_> {
600 &VALUE
601 }
602 fn serialize_members(&self, ser: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
603 ser.write_list_with_length(&VALUES, 2, &|ser| {
604 ser.write_map_with_length(&MAP, 1, &|ser| {
605 ser.write_string(&STRING, "key")?;
606 ser.write_null(&STRING)
607 })?;
608 ser.write_list(&VALUES, &|ser| ser.write_integer(&INTEGER, 7))
609 })
610 }
611 }
612 let codec =
613 CborCodec::new(crate::codec::CborCodecSettings::default().use_definite_lengths(true));
614 let mut ser = codec.create_serializer();
615 ser.write_struct(&VALUE, &Value).unwrap();
616 let mut legacy = crate::Encoder::new(Vec::new());
617 legacy
618 .begin_map()
619 .str("values")
620 .array(2)
621 .map(1)
622 .str("key")
623 .null();
624 legacy.begin_array().integer(7).end().end();
625 assert_eq!(ser.finish(), legacy.into_writer());
626 }
627
628 #[test]
629 fn test_write_struct() {
630 static NAME_MEMBER: Schema =
631 Schema::new_member(shape_id!("test", "Struct"), ShapeType::String, "name", 0);
632 static AGE_MEMBER: Schema =
633 Schema::new_member(shape_id!("test", "Struct"), ShapeType::Integer, "age", 1);
634 static STRUCT_SCHEMA: Schema = Schema::new_struct(
635 shape_id!("test", "Struct"),
636 ShapeType::Structure,
637 &[&NAME_MEMBER, &AGE_MEMBER],
638 );
639
640 struct TestStruct;
641 impl SerializableStruct for TestStruct {
642 fn schema(&self) -> &Schema<'_> {
643 &STRUCT_SCHEMA
644 }
645
646 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
647 s.write_string(&NAME_MEMBER, "Alice")?;
648 s.write_integer(&AGE_MEMBER, 30)?;
649 Ok(())
650 }
651 }
652
653 let bytes = round_trip(|s| s.write_struct(&STRUCT_SCHEMA, &TestStruct).unwrap());
654 let mut dec = crate::Decoder::new(&bytes);
655 let len = dec.map().unwrap();
656 assert!(len.is_none()); assert_eq!(dec.str().unwrap().as_ref(), "name");
658 assert_eq!(dec.str().unwrap().as_ref(), "Alice");
659 assert_eq!(dec.str().unwrap().as_ref(), "age");
660 assert_eq!(dec.integer().unwrap(), 30);
661 }
662
663 mod struct_prefix {
664 use super::*;
665
666 static NAME: Schema = Schema::new_member(
667 shape_id!("test", "Value", "name"),
668 ShapeType::String,
669 "name",
670 0,
671 );
672 static VALUE: Schema =
673 Schema::new_struct(shape_id!("test", "Value"), ShapeType::Structure, &[&NAME]);
674 static MEMBER: Schema = Schema::new_member(
675 shape_id!("test", "Container", "value"),
676 ShapeType::Structure,
677 "value",
678 0,
679 );
680 static PREFIX: Schema = Schema::new_member(
681 shape_id!("test", "Value", "prefix"),
682 ShapeType::String,
683 "prefix",
684 1,
685 );
686
687 struct Value;
688 impl SerializableStruct for Value {
689 fn schema(&self) -> &Schema<'_> {
690 &VALUE
691 }
692
693 fn serialize_members(
694 &self,
695 serializer: &mut dyn ShapeSerializer,
696 ) -> Result<(), SerdeError> {
697 serializer.write_string(&NAME, "Alice")
698 }
699 }
700
701 #[test]
702 fn absent_by_default() {
703 let mut serializer = CborCodec::default().create_serializer();
704 serializer.write_struct(&VALUE, &Value).unwrap();
705 let mut expected = crate::Encoder::new(Vec::new());
706 expected.begin_map().str("name").str("Alice").end();
707 assert_eq!(serializer.finish(), expected.into_writer());
708 }
709
710 #[test]
711 fn prefix_precedes_members_and_receives_value_schema() {
712 let mut serializer = CborCodec::default().create_serializer().with_struct_prefix(
713 |schema, serializer| {
714 let expected = &VALUE;
715 assert_eq!(schema.shape_id(), expected.shape_id());
716 assert_eq!(schema.member_name(), expected.member_name());
717 serializer.write_string(&PREFIX, schema.shape_id().as_str())
718 },
719 );
720 serializer
721 .write_list(
722 &Schema::new(shape_id!("test", "Values"), ShapeType::List),
723 &|serializer| serializer.write_struct(&MEMBER, &Value),
724 )
725 .unwrap();
726 let mut expected = crate::Encoder::new(Vec::new());
727 expected
728 .begin_array()
729 .begin_map()
730 .str("prefix")
731 .str(VALUE.shape_id().as_str())
732 .str("name")
733 .str("Alice")
734 .end()
735 .end();
736 assert_eq!(serializer.finish(), expected.into_writer());
737 }
738
739 #[test]
740 fn prefix_failure_prevents_modeled_members() {
741 struct UnreachableMembers;
742 impl SerializableStruct for UnreachableMembers {
743 fn schema(&self) -> &Schema<'_> {
744 &VALUE
745 }
746
747 fn serialize_members(&self, _: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
748 panic!("modeled members must not be serialized after prefix failure")
749 }
750 }
751 let mut serializer = CborCodec::default()
752 .create_serializer()
753 .with_struct_prefix(|_, _| Err(SerdeError::custom("prefix failed")));
754 let error = serializer
755 .write_struct(&VALUE, &UnreachableMembers)
756 .unwrap_err();
757 assert!(error.to_string().contains("prefix failed"));
758 assert_eq!(serializer.finish(), vec![0xbf]);
759 }
760 }
761
762 #[test]
763 fn test_write_map() {
764 let map_schema = Schema::new(shape_id!("test", "Map"), ShapeType::Map);
765 let bytes = round_trip(|s| {
766 s.write_map(&map_schema, &|s| {
767 s.write_string(&STRING, "key1")?;
768 s.write_string(&STRING, "val1")?;
769 Ok(())
770 })
771 .unwrap()
772 });
773 let mut dec = crate::Decoder::new(&bytes);
774 let len = dec.map().unwrap();
775 assert!(len.is_none());
776 assert_eq!(dec.str().unwrap().as_ref(), "key1");
777 assert_eq!(dec.str().unwrap().as_ref(), "val1");
778 }
779
780 mod tagged_union_serialization {
792 use crate::codec::{CborCodec, CborDeserializer, CborSerializer};
793 use aws_smithy_schema::codec::{Codec, FinishSerializer};
794 use aws_smithy_schema::serde::{
795 SerdeError, SerializableStruct, ShapeDeserializer, ShapeSerializer,
796 };
797 use aws_smithy_schema::{shape_id, Schema, ShapeType};
798
799 fn serialize(f: impl FnOnce(&mut CborSerializer)) -> Vec<u8> {
800 let codec = CborCodec::default();
801 let mut ser = codec.create_serializer();
802 f(&mut ser);
803 ser.finish()
804 }
805
806 static EP_ARN: Schema =
808 Schema::new_member(shape_id!("test", "Endpoint"), ShapeType::String, "arn", 0);
809 static EP_CONFIG: Schema = Schema::new_member(
810 shape_id!("test", "Endpoint"),
811 ShapeType::Structure,
812 "config",
813 1,
814 );
815 static ENDPOINT_SCHEMA: Schema = Schema::new_struct(
816 shape_id!("test", "Endpoint"),
817 ShapeType::Union,
818 &[&EP_ARN, &EP_CONFIG],
819 );
820
821 static EC_NAME: Schema = Schema::new_member(
823 shape_id!("test", "EndpointConfig"),
824 ShapeType::String,
825 "name",
826 0,
827 );
828 static ENDPOINT_CONFIG_SCHEMA: Schema = Schema::new_struct(
829 shape_id!("test", "EndpointConfig"),
830 ShapeType::Structure,
831 &[&EC_NAME],
832 );
833
834 static CC_ATTACH: Schema = Schema::new_member(
836 shape_id!("test", "CreateConnectionInput"),
837 ShapeType::Union,
838 "attachPoint",
839 0,
840 );
841 static CC_REMOTE: Schema = Schema::new_member(
842 shape_id!("test", "CreateConnectionInput"),
843 ShapeType::Union,
844 "remoteAccount",
845 1,
846 );
847 static CREATE_CONNECTION_SCHEMA: Schema = Schema::new_struct(
848 shape_id!("test", "CreateConnectionInput"),
849 ShapeType::Structure,
850 &[&CC_ATTACH, &CC_REMOTE],
851 );
852
853 #[derive(Debug, Clone, PartialEq)]
854 struct EndpointConfig {
855 name: String,
856 }
857 impl SerializableStruct for EndpointConfig {
858 fn schema(&self) -> &Schema<'_> {
859 &ENDPOINT_CONFIG_SCHEMA
860 }
861
862 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
863 s.write_string(&EC_NAME, &self.name)
864 }
865 }
866
867 #[derive(Debug, Clone, PartialEq)]
868 enum Endpoint {
869 Arn(String),
870 Config(EndpointConfig),
871 }
872 impl SerializableStruct for Endpoint {
873 fn schema(&self) -> &Schema<'_> {
874 &ENDPOINT_SCHEMA
875 }
876
877 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
878 match self {
880 Endpoint::Arn(v) => s.write_string(&EP_ARN, v),
881 Endpoint::Config(v) => s.write_struct(&EP_CONFIG, v),
882 }
883 }
884 }
885
886 #[derive(Debug, Clone, PartialEq)]
887 struct CreateConnectionInput {
888 attach_point: Endpoint,
889 remote_account: Endpoint,
890 }
891 impl SerializableStruct for CreateConnectionInput {
892 fn schema(&self) -> &Schema<'_> {
893 &CREATE_CONNECTION_SCHEMA
894 }
895
896 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
897 s.write_struct(&CC_ATTACH, &self.attach_point)?;
898 s.write_struct(&CC_REMOTE, &self.remote_account)
899 }
900 }
901
902 fn deser_endpoint_config(
904 d: &mut dyn ShapeDeserializer,
905 ) -> Result<EndpointConfig, SerdeError> {
906 let mut name = String::new();
907 d.read_struct(&ENDPOINT_CONFIG_SCHEMA, &mut |m, de| {
908 if m.member_name() == Some("name") {
909 name = de.read_string(m)?;
910 }
911 Ok(())
912 })?;
913 Ok(EndpointConfig { name })
914 }
915 fn deser_endpoint(d: &mut dyn ShapeDeserializer) -> Result<Endpoint, SerdeError> {
916 let mut out: Option<Endpoint> = None;
917 d.read_struct(&ENDPOINT_SCHEMA, &mut |m, de| {
918 out = Some(match m.member_index() {
919 Some(0) => Endpoint::Arn(de.read_string(m)?),
920 Some(1) => Endpoint::Config(deser_endpoint_config(de)?),
921 _ => return Err(SerdeError::custom("unknown variant")),
922 });
923 Ok(())
924 })?;
925 out.ok_or_else(|| SerdeError::custom("expected a union variant"))
926 }
927 fn deser_create_connection(
928 d: &mut dyn ShapeDeserializer,
929 ) -> Result<CreateConnectionInput, SerdeError> {
930 let mut ap: Option<Endpoint> = None;
931 let mut ra: Option<Endpoint> = None;
932 d.read_struct(&CREATE_CONNECTION_SCHEMA, &mut |m, de| {
933 match m.member_index() {
934 Some(0) => ap = Some(deser_endpoint(de)?),
935 Some(1) => ra = Some(deser_endpoint(de)?),
936 _ => {}
937 }
938 Ok(())
939 })?;
940 Ok(CreateConnectionInput {
941 attach_point: ap.ok_or_else(|| SerdeError::custom("missing attachPoint"))?,
942 remote_account: ra.ok_or_else(|| SerdeError::custom("missing remoteAccount"))?,
943 })
944 }
945
946 #[test]
947 fn scalar_variant_wire_bytes() {
948 let bytes = serialize(|s| {
949 s.write_struct(&ENDPOINT_SCHEMA, &Endpoint::Arn("dxcon-abc".to_string()))
950 .unwrap()
951 });
952 let mut expected = crate::Encoder::new(Vec::new());
954 expected.begin_map().str("arn").str("dxcon-abc").end();
955 assert_eq!(
956 bytes,
957 expected.into_writer(),
958 "tagged union must be a single-entry map keyed by the active variant name"
959 );
960 assert_eq!(bytes[0], 0xBF, "must use an indefinite-length map (0xBF)");
961 assert_eq!(
962 *bytes.last().unwrap(),
963 0xFF,
964 "must be terminated by a break (0xFF)"
965 );
966 }
967
968 #[test]
969 fn struct_variant_wire_bytes() {
970 let bytes = serialize(|s| {
971 s.write_struct(
972 &ENDPOINT_SCHEMA,
973 &Endpoint::Config(EndpointConfig {
974 name: "eth0".to_string(),
975 }),
976 )
977 .unwrap()
978 });
979 let mut expected = crate::Encoder::new(Vec::new());
980 expected
981 .begin_map()
982 .str("config")
983 .begin_map()
984 .str("name")
985 .str("eth0")
986 .end()
987 .end();
988 assert_eq!(bytes, expected.into_writer());
989 }
990
991 #[test]
992 fn two_union_members_in_one_input_wire_bytes() {
993 let input = CreateConnectionInput {
994 attach_point: Endpoint::Arn("ap".to_string()),
995 remote_account: Endpoint::Config(EndpointConfig {
996 name: "ra".to_string(),
997 }),
998 };
999 let bytes = serialize(|s| s.write_struct(&CREATE_CONNECTION_SCHEMA, &input).unwrap());
1000 let mut expected = crate::Encoder::new(Vec::new());
1001 expected
1002 .begin_map()
1003 .str("attachPoint")
1004 .begin_map()
1005 .str("arn")
1006 .str("ap")
1007 .end()
1008 .str("remoteAccount")
1009 .begin_map()
1010 .str("config")
1011 .begin_map()
1012 .str("name")
1013 .str("ra")
1014 .end()
1015 .end()
1016 .end();
1017 assert_eq!(bytes, expected.into_writer());
1018 }
1019
1020 #[test]
1021 fn tagged_unions_round_trip() {
1022 let input = CreateConnectionInput {
1023 attach_point: Endpoint::Arn("dxcon-1".to_string()),
1024 remote_account: Endpoint::Config(EndpointConfig {
1025 name: "primary".to_string(),
1026 }),
1027 };
1028 let bytes = serialize(|s| s.write_struct(&CREATE_CONNECTION_SCHEMA, &input).unwrap());
1029 let mut de = CborDeserializer::new(&bytes, 128);
1031 let decoded = deser_create_connection(&mut de).unwrap();
1032 assert_eq!(
1033 decoded, input,
1034 "serialize -> deserialize must round-trip the tagged unions"
1035 );
1036 }
1037 }
1038}