1use crate::serde::{SerdeError, SerializableStruct, ShapeDeserializer, ShapeSerializer};
16use crate::Schema;
17use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime};
18
19use aws_smithy_runtime_api::http::header_parse::{self, quote_header_value};
20use aws_smithy_types::Document;
21use std::borrow::Cow;
22
23#[derive(Debug)]
25pub struct HttpStringSerializer {
26 output: String,
27 in_list: bool,
29 wrote_value: bool,
31}
32
33impl HttpStringSerializer {
34 pub fn new() -> Self {
36 Self {
37 output: String::new(),
38 in_list: false,
39 wrote_value: false,
40 }
41 }
42
43 fn push_value(&mut self, value: &str) -> Result<(), SerdeError> {
45 if self.in_list {
46 if self.wrote_value {
47 self.output.push_str(", ");
48 }
49 if value.is_empty() {
50 self.output.push_str("\"\"");
51 } else {
52 self.output.push_str("e_header_value(value));
53 }
54 } else if self.wrote_value {
55 return Err(SerdeError::write_failed(
56 "only one value can be written outside a list",
57 ));
58 } else {
59 self.output.push_str(value);
60 }
61 self.wrote_value = true;
62 Ok(())
63 }
64
65 pub fn finish(self) -> String {
67 self.output
68 }
69}
70
71impl super::FinishSerializer for HttpStringSerializer {
72 fn finish(self) -> Vec<u8> {
73 self.output.into_bytes()
74 }
75}
76
77impl Default for HttpStringSerializer {
78 fn default() -> Self {
79 Self::new()
80 }
81}
82
83impl ShapeSerializer for HttpStringSerializer {
84 fn write_struct(
85 &mut self,
86 _schema: &Schema<'_>,
87 _value: &dyn SerializableStruct,
88 ) -> Result<(), SerdeError> {
89 Err(SerdeError::unsupported(
90 "structures cannot be serialized to strings",
91 ))
92 }
93
94 fn write_list(
95 &mut self,
96 _schema: &Schema<'_>,
97 write_elements: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
98 ) -> Result<(), SerdeError> {
99 if self.in_list {
100 return Err(SerdeError::unsupported(
101 "nested lists cannot be serialized to strings",
102 ));
103 }
104 if self.wrote_value {
105 return Err(SerdeError::write_failed(
106 "only one value can be written outside a list",
107 ));
108 }
109 self.in_list = true;
110 let result = write_elements(self);
111 self.in_list = false;
112 self.wrote_value = true;
114 result
115 }
116
117 fn write_map(
118 &mut self,
119 _schema: &Schema<'_>,
120 _write_entries: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
121 ) -> Result<(), SerdeError> {
122 Err(SerdeError::unsupported(
123 "maps cannot be serialized to strings",
124 ))
125 }
126
127 fn write_boolean(&mut self, _schema: &Schema<'_>, value: bool) -> Result<(), SerdeError> {
128 self.push_value(if value { "true" } else { "false" })
129 }
130
131 fn write_byte(&mut self, _schema: &Schema<'_>, value: i8) -> Result<(), SerdeError> {
132 self.push_value(&value.to_string())
133 }
134
135 fn write_short(&mut self, _schema: &Schema<'_>, value: i16) -> Result<(), SerdeError> {
136 self.push_value(&value.to_string())
137 }
138
139 fn write_integer(&mut self, _schema: &Schema<'_>, value: i32) -> Result<(), SerdeError> {
140 self.push_value(&value.to_string())
141 }
142
143 fn write_long(&mut self, _schema: &Schema<'_>, value: i64) -> Result<(), SerdeError> {
144 self.push_value(&value.to_string())
145 }
146
147 fn write_float(&mut self, _schema: &Schema<'_>, value: f32) -> Result<(), SerdeError> {
148 if value.is_nan() {
149 self.push_value("NaN")
150 } else if value.is_infinite() {
151 self.push_value(if value.is_sign_positive() {
152 "Infinity"
153 } else {
154 "-Infinity"
155 })
156 } else {
157 self.push_value(&value.to_string())
158 }
159 }
160
161 fn write_double(&mut self, _schema: &Schema<'_>, value: f64) -> Result<(), SerdeError> {
162 if value.is_nan() {
163 self.push_value("NaN")
164 } else if value.is_infinite() {
165 self.push_value(if value.is_sign_positive() {
166 "Infinity"
167 } else {
168 "-Infinity"
169 })
170 } else {
171 self.push_value(&value.to_string())
172 }
173 }
174
175 fn write_big_integer(
176 &mut self,
177 _schema: &Schema<'_>,
178 value: &BigInteger,
179 ) -> Result<(), SerdeError> {
180 self.push_value(value.as_ref())
181 }
182
183 fn write_big_decimal(
184 &mut self,
185 _schema: &Schema<'_>,
186 value: &BigDecimal,
187 ) -> Result<(), SerdeError> {
188 self.push_value(value.as_ref())
189 }
190
191 fn write_string(&mut self, _schema: &Schema<'_>, value: &str) -> Result<(), SerdeError> {
192 self.push_value(value)
193 }
194
195 fn write_blob(&mut self, _schema: &Schema<'_>, value: Blob) -> Result<(), SerdeError> {
196 self.push_value(&aws_smithy_types::base64::encode(value.as_ref()))
198 }
199
200 fn write_timestamp(
201 &mut self,
202 _schema: &Schema<'_>,
203 value: &DateTime,
204 ) -> Result<(), SerdeError> {
205 let formatted = value
208 .fmt(aws_smithy_types::date_time::Format::HttpDate)
209 .map_err(|e| SerdeError::write_failed(format!("failed to format timestamp: {e}")))?;
210 self.push_value(&formatted)
212 }
213
214 fn write_document(
215 &mut self,
216 _schema: &Schema<'_>,
217 _value: &Document,
218 ) -> Result<(), SerdeError> {
219 Err(SerdeError::unsupported(
220 "documents cannot be serialized to strings",
221 ))
222 }
223
224 fn write_null(&mut self, _schema: &Schema<'_>) -> Result<(), SerdeError> {
225 Err(SerdeError::unsupported(
226 "null cannot be serialized to strings",
227 ))
228 }
229}
230
231#[derive(Debug)]
233pub struct HttpStringDeserializer<'a> {
234 input: Cow<'a, str>,
235 consumed: bool,
237 list: Option<std::vec::IntoIter<String>>,
239}
240
241impl<'a> HttpStringDeserializer<'a> {
242 pub fn new(input: &'a str) -> Self {
244 Self {
245 input: Cow::Borrowed(input),
246 consumed: false,
247 list: None,
248 }
249 }
250
251 fn list_elements(&self) -> Result<Vec<String>, SerdeError> {
253 if self.input.is_empty() {
254 return Ok(Vec::new());
255 }
256 header_parse::read_many_from_str_bytes::<String>(std::iter::once(self.input.as_bytes()))
257 .map_err(|e| SerdeError::invalid_input(format!("invalid list: {e}")))
258 }
259
260 fn next_value(&mut self, what: &str) -> Result<Cow<'_, str>, SerdeError> {
262 let value = match &mut self.list {
263 Some(elements) => elements.next().map(Cow::Owned),
264 None if self.consumed => None,
265 None => {
266 self.consumed = true;
267 Some(Cow::Borrowed(self.input.as_ref()))
268 }
269 };
270 value.ok_or_else(|| SerdeError::invalid_input(format!("expected {what} value")))
271 }
272}
273
274impl<'a> ShapeDeserializer for HttpStringDeserializer<'a> {
275 fn read_struct(
276 &mut self,
277 _schema: &Schema<'_>,
278 _consumer: &mut dyn FnMut(
279 &Schema<'_>,
280 &mut dyn ShapeDeserializer,
281 ) -> Result<(), SerdeError>,
282 ) -> Result<(), SerdeError> {
283 Err(SerdeError::unsupported(
284 "structures cannot be deserialized from strings",
285 ))
286 }
287
288 fn read_list(
289 &mut self,
290 _schema: &Schema<'_>,
291 consumer: &mut dyn FnMut(&mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
292 ) -> Result<(), SerdeError> {
293 if self.list.is_some() {
297 return Err(SerdeError::unsupported(
298 "nested lists cannot be deserialized from strings",
299 ));
300 }
301 let elements = self.list_elements()?;
302 self.consumed = true;
303 let count = elements.len();
304 self.list = Some(elements.into_iter());
305 let mut result = Ok(());
306 for _ in 0..count {
307 result = consumer(self);
308 if result.is_err() {
309 break;
310 }
311 }
312 self.list = None;
313 result
314 }
315
316 fn read_map(
317 &mut self,
318 _schema: &Schema<'_>,
319 _consumer: &mut dyn FnMut(String, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
320 ) -> Result<(), SerdeError> {
321 Err(SerdeError::unsupported(
322 "maps cannot be deserialized from strings",
323 ))
324 }
325
326 fn read_boolean(&mut self, _schema: &Schema<'_>) -> Result<bool, SerdeError> {
327 let value = self.next_value("boolean")?;
328 let value = value.as_ref();
329 value
330 .parse()
331 .map_err(|_| SerdeError::invalid_input(format!("invalid boolean: {value}")))
332 }
333
334 fn read_byte(&mut self, _schema: &Schema<'_>) -> Result<i8, SerdeError> {
335 let value = self.next_value("byte")?;
336 let value = value.as_ref();
337 value
338 .parse()
339 .map_err(|_| SerdeError::invalid_input(format!("invalid byte: {value}")))
340 }
341
342 fn read_short(&mut self, _schema: &Schema<'_>) -> Result<i16, SerdeError> {
343 let value = self.next_value("short")?;
344 let value = value.as_ref();
345 value
346 .parse()
347 .map_err(|_| SerdeError::invalid_input(format!("invalid short: {value}")))
348 }
349
350 fn read_integer(&mut self, _schema: &Schema<'_>) -> Result<i32, SerdeError> {
351 let value = self.next_value("integer")?;
352 let value = value.as_ref();
353 value
354 .parse()
355 .map_err(|_| SerdeError::invalid_input(format!("invalid integer: {value}")))
356 }
357
358 fn read_long(&mut self, _schema: &Schema<'_>) -> Result<i64, SerdeError> {
359 let value = self.next_value("long")?;
360 let value = value.as_ref();
361 value
362 .parse()
363 .map_err(|_| SerdeError::invalid_input(format!("invalid long: {value}")))
364 }
365
366 fn read_float(&mut self, _schema: &Schema<'_>) -> Result<f32, SerdeError> {
367 let value = self.next_value("float")?;
368 let value = value.as_ref();
369 match value {
370 "NaN" => Ok(f32::NAN),
371 "Infinity" => Ok(f32::INFINITY),
372 "-Infinity" => Ok(f32::NEG_INFINITY),
373 _ => value
374 .parse()
375 .map_err(|_| SerdeError::invalid_input(format!("invalid float: {value}"))),
376 }
377 }
378
379 fn read_double(&mut self, _schema: &Schema<'_>) -> Result<f64, SerdeError> {
380 let value = self.next_value("double")?;
381 let value = value.as_ref();
382 match value {
383 "NaN" => Ok(f64::NAN),
384 "Infinity" => Ok(f64::INFINITY),
385 "-Infinity" => Ok(f64::NEG_INFINITY),
386 _ => value
387 .parse()
388 .map_err(|_| SerdeError::invalid_input(format!("invalid double: {value}"))),
389 }
390 }
391
392 fn read_big_integer(&mut self, _schema: &Schema<'_>) -> Result<BigInteger, SerdeError> {
393 let value = self.next_value("big integer")?;
394 let value = value.as_ref();
395 use std::str::FromStr;
396 BigInteger::from_str(value)
397 .map_err(|_| SerdeError::invalid_input(format!("invalid big integer: {value}")))
398 }
399
400 fn read_big_decimal(&mut self, _schema: &Schema<'_>) -> Result<BigDecimal, SerdeError> {
401 let value = self.next_value("big decimal")?;
402 let value = value.as_ref();
403 use std::str::FromStr;
404 BigDecimal::from_str(value)
405 .map_err(|_| SerdeError::invalid_input(format!("invalid big decimal: {value}")))
406 }
407
408 fn read_string(&mut self, _schema: &Schema<'_>) -> Result<String, SerdeError> {
409 self.next_value("string").map(Cow::into_owned)
410 }
411
412 fn read_blob(&mut self, _schema: &Schema<'_>) -> Result<Blob, SerdeError> {
413 let value = self.next_value("blob")?;
414 let value = value.as_ref();
415 let decoded = aws_smithy_types::base64::decode(value)
416 .map_err(|e| SerdeError::invalid_input(format!("invalid base64: {e}")))?;
417 Ok(Blob::new(decoded))
418 }
419
420 fn read_timestamp(&mut self, _schema: &Schema<'_>) -> Result<DateTime, SerdeError> {
421 let value = self.next_value("timestamp")?;
422 let value = value.as_ref();
423 DateTime::from_str(value, aws_smithy_types::date_time::Format::HttpDate)
426 .or_else(|_| DateTime::from_str(value, aws_smithy_types::date_time::Format::DateTime))
427 .map_err(|e| SerdeError::invalid_input(format!("invalid timestamp: {e}")))
428 }
429
430 fn read_document(&mut self, _schema: &Schema<'_>) -> Result<Document, SerdeError> {
431 Err(SerdeError::unsupported(
432 "documents cannot be deserialized from strings",
433 ))
434 }
435
436 fn is_null(&self) -> bool {
437 self.list.is_none() && self.input.is_empty()
439 }
440
441 fn skip_value(&mut self) -> Result<(), SerdeError> {
446 if let Some(elements) = &mut self.list {
447 elements.next();
448 }
449 Ok(())
450 }
451
452 fn container_size(&self) -> Option<usize> {
453 match &self.list {
454 Some(elements) => Some(elements.len()),
455 None => self.list_elements().ok().map(|elements| elements.len()),
456 }
457 }
458}
459
460#[derive(Debug)]
462pub struct HttpStringCodec;
463
464impl crate::codec::Codec for HttpStringCodec {
465 type Serializer = HttpStringSerializer;
466 type Deserializer<'a> = HttpStringDeserializer<'a>;
467
468 fn create_serializer(&self) -> Self::Serializer {
469 HttpStringSerializer::new()
470 }
471
472 fn create_deserializer<'a>(&self, input: &'a [u8]) -> Self::Deserializer<'a> {
473 let input_str = std::str::from_utf8(input).unwrap_or("");
474 HttpStringDeserializer::new(input_str)
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481 use crate::prelude::*;
482
483 #[test]
484 fn test_serialize_boolean() {
485 let mut ser = HttpStringSerializer::new();
486 ser.write_boolean(&BOOLEAN, true).unwrap();
487 assert_eq!(ser.finish(), "true");
488
489 let mut ser = HttpStringSerializer::new();
490 ser.write_boolean(&BOOLEAN, false).unwrap();
491 assert_eq!(ser.finish(), "false");
492 }
493
494 #[test]
495 fn test_serialize_integers() {
496 let mut ser = HttpStringSerializer::new();
497 ser.write_byte(&BYTE, 42).unwrap();
498 assert_eq!(ser.finish(), "42");
499
500 let mut ser = HttpStringSerializer::new();
501 ser.write_integer(&INTEGER, -123).unwrap();
502 assert_eq!(ser.finish(), "-123");
503
504 let mut ser = HttpStringSerializer::new();
505 ser.write_long(&LONG, 9876543210).unwrap();
506 assert_eq!(ser.finish(), "9876543210");
507 }
508
509 #[test]
510 fn test_serialize_floats() {
511 let mut ser = HttpStringSerializer::new();
512 ser.write_float(&FLOAT, 3.15).unwrap();
513 assert_eq!(ser.finish(), "3.15");
514
515 let mut ser = HttpStringSerializer::new();
516 ser.write_float(&FLOAT, f32::NAN).unwrap();
517 assert_eq!(ser.finish(), "NaN");
518
519 let mut ser = HttpStringSerializer::new();
520 ser.write_float(&FLOAT, f32::INFINITY).unwrap();
521 assert_eq!(ser.finish(), "Infinity");
522 }
523
524 #[test]
525 fn test_serialize_string() {
526 let mut ser = HttpStringSerializer::new();
527 ser.write_string(&STRING, "hello world").unwrap();
528 assert_eq!(ser.finish(), "hello world");
529 }
530
531 #[test]
532 fn test_serialize_list() {
533 let mut ser = HttpStringSerializer::new();
534 ser.write_list(&STRING, &|s: &mut dyn ShapeSerializer| {
535 s.write_string(&STRING, "a")?;
536 s.write_string(&STRING, "b")?;
537 s.write_string(&STRING, "c")?;
538 Ok(())
539 })
540 .unwrap();
541 assert_eq!(ser.finish(), "a, b, c");
542 }
543
544 #[test]
545 fn test_serialize_blob() {
546 let mut ser = HttpStringSerializer::new();
547 let blob = Blob::new(vec![1, 2, 3, 4]);
548 ser.write_blob(&BLOB, blob).unwrap();
549 assert_eq!(ser.finish(), "AQIDBA==");
551 }
552
553 #[test]
554 fn test_deserialize_boolean() {
555 let mut deser = HttpStringDeserializer::new("true");
556 assert!(deser.read_boolean(&BOOLEAN).unwrap());
557
558 let mut deser = HttpStringDeserializer::new("false");
559 assert!(!(deser.read_boolean(&BOOLEAN).unwrap()));
560 }
561
562 #[test]
563 fn test_deserialize_integers() {
564 let mut deser = HttpStringDeserializer::new("42");
565 assert_eq!(deser.read_byte(&BYTE).unwrap(), 42);
566
567 let mut deser = HttpStringDeserializer::new("-123");
568 assert_eq!(deser.read_integer(&INTEGER).unwrap(), -123);
569
570 let mut deser = HttpStringDeserializer::new("9876543210");
571 assert_eq!(deser.read_long(&LONG).unwrap(), 9876543210);
572 }
573
574 #[test]
575 fn test_deserialize_floats() {
576 let mut deser = HttpStringDeserializer::new("3.15");
577 assert!((deser.read_float(&FLOAT).unwrap() - 3.15).abs() < 0.01);
578
579 let mut deser = HttpStringDeserializer::new("NaN");
580 assert!(deser.read_float(&FLOAT).unwrap().is_nan());
581
582 let mut deser = HttpStringDeserializer::new("Infinity");
583 assert_eq!(deser.read_float(&FLOAT).unwrap(), f32::INFINITY);
584 }
585
586 #[test]
587 fn test_deserialize_string() {
588 let mut deser = HttpStringDeserializer::new("hello world");
589 assert_eq!(deser.read_string(&STRING).unwrap(), "hello world");
590 }
591
592 #[test]
593 fn scalar_read_is_the_whole_value() {
594 let mut deser = HttpStringDeserializer::new("a, b,c");
596 assert_eq!(deser.read_string(&STRING).unwrap(), "a, b,c");
597 assert!(
598 deser.read_string(&STRING).is_err(),
599 "the single value was already read"
600 );
601 }
602
603 #[test]
604 fn only_one_value_can_be_written_outside_a_list() {
605 let mut ser = HttpStringSerializer::new();
606 ser.write_string(&STRING, "a").unwrap();
607 assert!(ser.write_string(&STRING, "b").is_err());
608 }
609
610 fn string_list() -> Schema<'static> {
611 Schema::new_list(crate::shape_id!("ns", "StringList"), &STRING)
612 }
613
614 fn write_strings(items: &[&str]) -> String {
615 let mut ser = HttpStringSerializer::new();
616 ser.write_list(&string_list(), &|e| {
617 for it in items {
618 e.write_string(&STRING, it)?;
619 }
620 Ok(())
621 })
622 .unwrap();
623 ser.finish()
624 }
625
626 fn read_strings(wire: &str) -> Result<Vec<String>, SerdeError> {
627 let mut de = HttpStringDeserializer::new(wire);
628 let mut out = Vec::new();
629 de.read_list(&string_list(), &mut |x| {
630 out.push(x.read_string(&STRING)?);
631 Ok(())
632 })?;
633 Ok(out)
634 }
635
636 #[test]
637 fn string_list_round_trips() {
638 let cases: [&[&str]; 11] = [
641 &["a", "b", "c"],
642 &["", "b"],
643 &["a", ""],
644 &["a,b"],
645 &["a, b"],
646 &[" a"],
647 &["a "],
648 &["\"q\""],
649 &["(x)"],
650 &[""],
651 &[],
652 ];
653 for case in cases {
654 let wire = write_strings(case);
655 let res = read_strings(&wire);
656 assert!(res.is_ok(), "read_list failed on wire {wire:?}: {res:?}");
657 assert_eq!(
658 res.unwrap(),
659 case,
660 "round trip changed the list; wire was {wire:?}"
661 );
662 }
663 }
664
665 #[test]
666 fn list_wire_format_matches_header_lists() {
667 assert_eq!(write_strings(&["a", "b", "c"]), "a, b, c");
668 assert_eq!(write_strings(&["a,b", ""]), "\"a,b\", \"\"");
669 assert_eq!(
671 read_strings("a,b , \"c,d\"").unwrap(),
672 vec!["a", "b", "c,d"]
673 );
674 assert!(read_strings("\"unterminated").is_err());
675 }
676
677 #[test]
678 fn timestamp_list_round_trips() {
679 let list = Schema::new_list(crate::shape_id!("ns", "TsList"), &TIMESTAMP);
681 let times = [DateTime::from_secs(0), DateTime::from_secs(1515531081)];
682 let mut ser = HttpStringSerializer::new();
683 ser.write_list(&list, &|e| {
684 for t in × {
685 e.write_timestamp(&TIMESTAMP, t)?;
686 }
687 Ok(())
688 })
689 .unwrap();
690 let wire = ser.finish();
691 let mut de = HttpStringDeserializer::new(&wire);
692 let mut out = Vec::new();
693 de.read_list(&list, &mut |x| {
694 out.push(x.read_timestamp(&TIMESTAMP)?);
695 Ok(())
696 })
697 .unwrap();
698 assert_eq!(out, times, "wire was {wire:?}");
699 }
700
701 #[test]
702 fn integer_list_round_trips() {
703 let list = Schema::new_list(crate::shape_id!("ns", "IntList"), &INTEGER);
704 let mut ser = HttpStringSerializer::new();
705 ser.write_list(&list, &|e| {
706 e.write_integer(&INTEGER, 1)?;
707 e.write_integer(&INTEGER, -2)
708 })
709 .unwrap();
710 let wire = ser.finish();
711 assert_eq!(wire, "1, -2");
712 let mut de = HttpStringDeserializer::new(&wire);
713 let mut out = Vec::new();
714 de.read_list(&list, &mut |x| {
715 out.push(x.read_integer(&INTEGER)?);
716 Ok(())
717 })
718 .unwrap();
719 assert_eq!(out, [1, -2]);
720 }
721
722 #[test]
723 fn skip_value_inside_a_list_consumes_one_element() {
724 let mut de = HttpStringDeserializer::new("a, b, c");
725 let mut out = Vec::new();
726 let mut first = true;
727 de.read_list(&string_list(), &mut |x| {
728 if std::mem::take(&mut first) {
729 x.skip_value()
730 } else {
731 out.push(x.read_string(&STRING)?);
732 Ok(())
733 }
734 })
735 .unwrap();
736 assert_eq!(out, ["b", "c"]);
737 }
738
739 #[test]
740 fn test_read_list_drives_consumer_per_element() {
741 let mut deser = HttpStringDeserializer::new("a,b,c");
742 let mut collected = Vec::new();
743 deser
744 .read_list(&STRING, &mut |d: &mut dyn ShapeDeserializer| {
745 collected.push(d.read_string(&STRING)?);
746 Ok(())
747 })
748 .unwrap();
749 assert_eq!(collected, vec!["a", "b", "c"]);
750 }
751
752 #[test]
753 fn test_read_list_empty_input_is_empty_list() {
754 let mut deser = HttpStringDeserializer::new("");
755 let mut count = 0;
756 deser
757 .read_list(&STRING, &mut |_d: &mut dyn ShapeDeserializer| {
758 count += 1;
759 Ok(())
760 })
761 .unwrap();
762 assert_eq!(count, 0);
763 }
764
765 #[test]
766 fn test_deserialize_blob() {
767 let mut deser = HttpStringDeserializer::new("AQIDBA==");
768 let blob = deser.read_blob(&BLOB).unwrap();
769 assert_eq!(blob.as_ref(), &[1, 2, 3, 4]);
770 }
771
772 #[test]
773 fn test_container_size() {
774 let deser = HttpStringDeserializer::new("a,b,c");
775 assert_eq!(deser.container_size(), Some(3));
776
777 let deser = HttpStringDeserializer::new("single");
778 assert_eq!(deser.container_size(), Some(1));
779 }
780
781 #[test]
782 fn test_is_null() {
783 let deser = HttpStringDeserializer::new("");
784 assert!(deser.is_null());
785
786 let deser = HttpStringDeserializer::new("value");
787 assert!(!deser.is_null());
788 }
789
790 #[test]
791 fn test_codec_trait() {
792 use crate::codec::Codec;
793
794 let codec = HttpStringCodec;
795
796 let mut ser = codec.create_serializer();
798 ser.write_string(&STRING, "test").unwrap();
799 let output = ser.finish();
800 assert_eq!(output, "test");
801
802 let input = b"hello";
804 let mut deser = codec.create_deserializer(input);
805 let result = deser.read_string(&STRING).unwrap();
806 assert_eq!(result, "hello");
807 }
808}
809
810#[cfg(test)]
812mod skip_value_contract {
813 use super::*;
814 use crate::prelude::*;
815 use crate::serde::ShapeDeserializer;
816
817 #[test]
818 fn skip_value_is_a_no_op_and_leaves_the_value_readable() {
819 let mut deser = HttpStringDeserializer::new("hello");
824 let dynamic: &mut dyn ShapeDeserializer = &mut deser;
825 dynamic.skip_value().expect("skip must succeed");
826 assert_eq!(deser.read_string(&STRING).unwrap(), "hello");
827 }
828
829 #[test]
830 fn skip_value_succeeds_where_the_default_would_fail() {
831 let mut deser = HttpStringDeserializer::new("value");
834 assert!(
835 deser.read_document(&DOCUMENT).is_err(),
836 "precondition: this deserializer cannot produce documents"
837 );
838 let mut deser = HttpStringDeserializer::new("value");
839 deser
840 .skip_value()
841 .expect("override must not use read_document");
842 }
843}