1use aws_smithy_schema::serde::SerdeError;
9use aws_smithy_schema::serde::ShapeDeserializer;
10use aws_smithy_schema::Schema;
11use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
12
13use crate::codec::JsonCodecSettings;
14use crate::deserialize::{json_token_iter, Token};
15
16use std::sync::Arc;
17
18pub(crate) const MAX_DESERIALIZE_DEPTH: u32 = 128;
22
23pub struct JsonDeserializer<'a> {
25 input: &'a [u8],
26 position: usize,
27 settings: Arc<JsonCodecSettings>,
28 depth: u32,
29}
30
31impl<'a> JsonDeserializer<'a> {
32 pub(crate) fn new(input: &'a [u8], settings: Arc<JsonCodecSettings>) -> Self {
34 Self {
35 input,
36 position: 0,
37 settings,
38 depth: 0,
39 }
40 }
41
42 fn resolve_member<'s>(&self, schema: &'s Schema, field_name: &str) -> Option<&'s Schema> {
44 self.settings.field_to_member(schema, field_name)
45 }
46
47 fn remaining(&self) -> &[u8] {
48 &self.input[self.position..]
49 }
50
51 fn advance_by(&mut self, n: usize) {
52 self.position = (self.position + n).min(self.input.len());
53 }
54
55 fn parse_key(&mut self) -> Result<std::borrow::Cow<'a, str>, SerdeError> {
60 let start = self.position + 1; self.position += 1;
62 let input = self.input;
63 let remaining = &input[start..];
64 let mut i = 0;
65 let mut has_escapes = false;
66 let mut found_end = false;
67 while i < remaining.len() {
68 match remaining[i] {
69 b'"' => {
70 found_end = true;
71 break;
72 }
73 b'\\' => {
74 has_escapes = true;
75 i += 2;
76 }
77 _ => i += 1,
78 }
79 }
80 if !found_end {
81 return Err(SerdeError::InvalidInput {
82 message: "unterminated string key".into(),
83 });
84 }
85 self.position = start + i + 1; let key_bytes = &input[start..start + i];
87 if has_escapes {
88 let raw = std::str::from_utf8(key_bytes).map_err(|e| SerdeError::InvalidInput {
89 message: e.to_string(),
90 })?;
91 Ok(std::borrow::Cow::Owned(
92 crate::escape::unescape_string(raw)
93 .map_err(|e| SerdeError::InvalidInput {
94 message: e.to_string(),
95 })?
96 .into_owned(),
97 ))
98 } else {
99 Ok(std::borrow::Cow::Borrowed(
100 std::str::from_utf8(key_bytes).map_err(|e| SerdeError::InvalidInput {
101 message: e.to_string(),
102 })?,
103 ))
104 }
105 }
106}
107
108impl<'a> ShapeDeserializer for JsonDeserializer<'a> {
109 fn read_struct(
110 &mut self,
111 schema: &Schema,
112 consumer: &mut dyn FnMut(&Schema, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
113 ) -> Result<(), SerdeError> {
114 self.depth += 1;
115 if self.depth > self.settings.max_depth() {
116 return Err(SerdeError::custom("maximum nesting depth exceeded"));
117 }
118 self.skip_whitespace();
120 if self.remaining().is_empty() {
121 self.depth -= 1;
123 return Ok(());
124 }
125 if self.remaining().first() != Some(&b'{') {
126 return Err(SerdeError::TypeMismatch {
127 message: "expected object".into(),
128 });
129 }
130 self.advance_by(1);
131
132 loop {
133 self.skip_whitespace();
134
135 match self.remaining().first() {
138 Some(&b'}') => {
139 self.advance_by(1);
140 break;
141 }
142 None => {
143 return Err(SerdeError::InvalidInput {
144 message: "unexpected end of input in object".into(),
145 });
146 }
147 Some(&b'"') => {}
148 Some(_) => {
149 return Err(SerdeError::InvalidInput {
150 message: "expected object key".into(),
151 });
152 }
153 }
154
155 let key_str = self.parse_key()?;
157
158 self.skip_whitespace();
160 if self.remaining().first() != Some(&b':') {
161 return Err(SerdeError::InvalidInput {
162 message: "expected colon after key".into(),
163 });
164 }
165 self.advance_by(1);
166 self.skip_whitespace();
167
168 let rem = self.remaining();
170 if rem.starts_with(b"null") && !rem.get(4).is_some_and(|b| b.is_ascii_alphanumeric()) {
171 self.advance_by(4);
172 } else if let Some(member_schema) = self.resolve_member(schema, &key_str) {
173 consumer(member_schema, self)?;
174 } else {
175 self.skip_value()?;
176 }
177 }
178
179 self.depth -= 1;
180 Ok(())
181 }
182
183 fn read_list(
184 &mut self,
185 _schema: &Schema,
186 consumer: &mut dyn FnMut(&mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
187 ) -> Result<(), SerdeError> {
188 self.depth += 1;
189 if self.depth > self.settings.max_depth() {
190 return Err(SerdeError::custom("maximum nesting depth exceeded"));
191 }
192 self.skip_whitespace();
193 if self.remaining().first() != Some(&b'[') {
194 return Err(SerdeError::TypeMismatch {
195 message: "expected array".into(),
196 });
197 }
198 self.advance_by(1);
199
200 loop {
201 self.skip_whitespace();
202 match self.remaining().first() {
203 Some(&b']') => {
204 self.advance_by(1);
205 break;
206 }
207 None => {
208 return Err(SerdeError::InvalidInput {
209 message: "unexpected end of input in array".into(),
210 });
211 }
212 _ => consumer(self)?,
213 }
214 }
215
216 self.depth -= 1;
217 Ok(())
218 }
219
220 fn read_map(
221 &mut self,
222 _schema: &Schema,
223 consumer: &mut dyn FnMut(String, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
224 ) -> Result<(), SerdeError> {
225 self.depth += 1;
226 if self.depth > self.settings.max_depth() {
227 return Err(SerdeError::custom("maximum nesting depth exceeded"));
228 }
229 self.skip_whitespace();
230 if self.remaining().first() != Some(&b'{') {
231 return Err(SerdeError::TypeMismatch {
232 message: "expected object".into(),
233 });
234 }
235 self.advance_by(1);
236
237 loop {
238 self.skip_whitespace();
239 match self.remaining().first() {
240 Some(&b'}') => {
241 self.advance_by(1);
242 break;
243 }
244 None => {
245 return Err(SerdeError::InvalidInput {
246 message: "unexpected end of input in object".into(),
247 });
248 }
249 Some(&b'"') => {}
250 Some(_) => {
251 return Err(SerdeError::InvalidInput {
252 message: "expected key".into(),
253 });
254 }
255 }
256
257 let key = self.parse_key()?;
258
259 self.skip_whitespace();
260 if self.remaining().first() != Some(&b':') {
261 return Err(SerdeError::InvalidInput {
262 message: "expected colon".into(),
263 });
264 }
265 self.advance_by(1);
266 self.skip_whitespace();
267
268 consumer(key.into_owned(), self)?;
269 }
270
271 self.depth -= 1;
272 Ok(())
273 }
274
275 fn read_boolean(&mut self, _schema: &Schema) -> Result<bool, SerdeError> {
276 self.skip_whitespace();
277 let rem = self.remaining();
278 if rem.starts_with(b"true") {
279 self.advance_by(4);
280 Ok(true)
281 } else if rem.starts_with(b"false") {
282 self.advance_by(5);
283 Ok(false)
284 } else {
285 Err(SerdeError::TypeMismatch {
286 message: "expected boolean".into(),
287 })
288 }
289 }
290
291 fn read_byte(&mut self, _schema: &Schema) -> Result<i8, SerdeError> {
292 self.read_integer_value().and_then(|n| {
293 i8::try_from(n).map_err(|_| SerdeError::InvalidInput {
294 message: "value out of range for byte".into(),
295 })
296 })
297 }
298
299 fn read_short(&mut self, _schema: &Schema) -> Result<i16, SerdeError> {
300 self.read_integer_value().and_then(|n| {
301 i16::try_from(n).map_err(|_| SerdeError::InvalidInput {
302 message: "value out of range for short".into(),
303 })
304 })
305 }
306
307 fn read_integer(&mut self, _schema: &Schema) -> Result<i32, SerdeError> {
308 self.read_integer_value().and_then(|n| {
309 i32::try_from(n).map_err(|_| SerdeError::InvalidInput {
310 message: "value out of range for integer".into(),
311 })
312 })
313 }
314
315 fn read_long(&mut self, _schema: &Schema) -> Result<i64, SerdeError> {
316 self.read_integer_value()
317 }
318
319 fn read_float(&mut self, _schema: &Schema) -> Result<f32, SerdeError> {
320 self.read_float_value().map(|f| f as f32)
321 }
322
323 fn read_double(&mut self, _schema: &Schema) -> Result<f64, SerdeError> {
324 self.read_float_value()
325 }
326
327 fn read_big_integer(&mut self, _schema: &Schema) -> Result<BigInteger, SerdeError> {
328 use std::str::FromStr;
329 self.skip_whitespace();
330 match self.remaining().first() {
331 Some(b'-') | Some(b'0'..=b'9') => {
332 let start = self.position;
333 self.consume_number();
334 let num_str =
335 std::str::from_utf8(&self.input[start..self.position]).map_err(|e| {
336 SerdeError::InvalidInput {
337 message: e.to_string(),
338 }
339 })?;
340 BigInteger::from_str(num_str).map_err(|e| SerdeError::InvalidInput {
341 message: e.to_string(),
342 })
343 }
344 _ => Err(SerdeError::TypeMismatch {
345 message: "expected number".into(),
346 }),
347 }
348 }
349
350 fn read_big_decimal(&mut self, _schema: &Schema) -> Result<BigDecimal, SerdeError> {
351 use std::str::FromStr;
352 self.skip_whitespace();
353 match self.remaining().first() {
354 Some(b'-') | Some(b'0'..=b'9') => {
355 let start = self.position;
356 self.consume_number();
357 let num_str =
358 std::str::from_utf8(&self.input[start..self.position]).map_err(|e| {
359 SerdeError::InvalidInput {
360 message: e.to_string(),
361 }
362 })?;
363 BigDecimal::from_str(num_str).map_err(|e| SerdeError::InvalidInput {
364 message: e.to_string(),
365 })
366 }
367 _ => Err(SerdeError::TypeMismatch {
368 message: "expected number".into(),
369 }),
370 }
371 }
372
373 fn read_string(&mut self, _schema: &Schema) -> Result<String, SerdeError> {
374 self.skip_whitespace();
375 let pos = self.position;
376 let input = self.input;
377 let rem = &input[pos..];
378 if rem.first() != Some(&b'"') {
379 return Err(SerdeError::TypeMismatch {
380 message: "expected string".into(),
381 });
382 }
383 let mut i = 1;
385 let mut has_escape = false;
386 while i < rem.len() {
387 if rem[i] == b'\\' {
388 has_escape = true;
389 i += 2;
390 } else if rem[i] == b'"' {
391 let raw = &input[pos + 1..pos + i];
392 self.position = pos + i + 1;
393 if !has_escape {
394 return std::str::from_utf8(raw).map(|s| s.to_owned()).map_err(|e| {
395 SerdeError::InvalidInput {
396 message: e.to_string(),
397 }
398 });
399 }
400 let s = std::str::from_utf8(raw).map_err(|e| SerdeError::InvalidInput {
401 message: e.to_string(),
402 })?;
403 return crate::deserialize::EscapedStr::new(s)
404 .to_unescaped()
405 .map(|s| s.into_owned())
406 .map_err(|e| SerdeError::InvalidInput {
407 message: e.to_string(),
408 });
409 } else {
410 i += 1;
411 }
412 }
413 Err(SerdeError::InvalidInput {
414 message: "unterminated string".into(),
415 })
416 }
417
418 fn read_blob(&mut self, _schema: &Schema) -> Result<Blob, SerdeError> {
419 let s = self.read_string(_schema)?;
420 let decoded =
421 aws_smithy_types::base64::decode(&s).map_err(|e| SerdeError::InvalidInput {
422 message: format!("invalid base64: {}", e),
423 })?;
424 Ok(Blob::new(decoded))
425 }
426
427 fn read_string_list(&mut self, _schema: &Schema) -> Result<Vec<String>, SerdeError> {
428 self.depth += 1;
429 if self.depth > self.settings.max_depth() {
430 return Err(SerdeError::custom("maximum nesting depth exceeded"));
431 }
432 self.skip_whitespace();
433 if self.remaining().first() != Some(&b'[') {
434 return Err(SerdeError::TypeMismatch {
435 message: "expected array".into(),
436 });
437 }
438 self.advance_by(1);
439 let mut out = Vec::new();
440 loop {
441 self.skip_whitespace();
442 match self.remaining().first() {
443 Some(&b']') => {
444 self.advance_by(1);
445 break;
446 }
447 None => {
448 return Err(SerdeError::InvalidInput {
449 message: "unexpected end of input in array".into(),
450 })
451 }
452 _ => out.push(self.read_string(_schema)?),
453 }
454 }
455 self.depth -= 1;
456 Ok(out)
457 }
458
459 fn read_blob_list(&mut self, _schema: &Schema) -> Result<Vec<Blob>, SerdeError> {
460 self.depth += 1;
461 if self.depth > self.settings.max_depth() {
462 return Err(SerdeError::custom("maximum nesting depth exceeded"));
463 }
464 self.skip_whitespace();
465 if self.remaining().first() != Some(&b'[') {
466 return Err(SerdeError::TypeMismatch {
467 message: "expected array".into(),
468 });
469 }
470 self.advance_by(1);
471 let mut out = Vec::new();
472 loop {
473 self.skip_whitespace();
474 match self.remaining().first() {
475 Some(&b']') => {
476 self.advance_by(1);
477 break;
478 }
479 None => {
480 return Err(SerdeError::InvalidInput {
481 message: "unexpected end of input in array".into(),
482 })
483 }
484 _ => out.push(self.read_blob(_schema)?),
485 }
486 }
487 self.depth -= 1;
488 Ok(out)
489 }
490
491 fn read_integer_list(&mut self, _schema: &Schema) -> Result<Vec<i32>, SerdeError> {
492 self.depth += 1;
493 if self.depth > self.settings.max_depth() {
494 return Err(SerdeError::custom("maximum nesting depth exceeded"));
495 }
496 self.skip_whitespace();
497 if self.remaining().first() != Some(&b'[') {
498 return Err(SerdeError::TypeMismatch {
499 message: "expected array".into(),
500 });
501 }
502 self.advance_by(1);
503 let mut out = Vec::new();
504 loop {
505 self.skip_whitespace();
506 match self.remaining().first() {
507 Some(&b']') => {
508 self.advance_by(1);
509 break;
510 }
511 None => {
512 return Err(SerdeError::InvalidInput {
513 message: "unexpected end of input in array".into(),
514 })
515 }
516 _ => out.push(self.read_integer(_schema)?),
517 }
518 }
519 self.depth -= 1;
520 Ok(out)
521 }
522
523 fn read_long_list(&mut self, _schema: &Schema) -> Result<Vec<i64>, SerdeError> {
524 self.depth += 1;
525 if self.depth > self.settings.max_depth() {
526 return Err(SerdeError::custom("maximum nesting depth exceeded"));
527 }
528 self.skip_whitespace();
529 if self.remaining().first() != Some(&b'[') {
530 return Err(SerdeError::TypeMismatch {
531 message: "expected array".into(),
532 });
533 }
534 self.advance_by(1);
535 let mut out = Vec::new();
536 loop {
537 self.skip_whitespace();
538 match self.remaining().first() {
539 Some(&b']') => {
540 self.advance_by(1);
541 break;
542 }
543 None => {
544 return Err(SerdeError::InvalidInput {
545 message: "unexpected end of input in array".into(),
546 })
547 }
548 _ => out.push(self.read_long(_schema)?),
549 }
550 }
551 self.depth -= 1;
552 Ok(out)
553 }
554
555 fn read_string_string_map(
556 &mut self,
557 _schema: &Schema,
558 ) -> Result<std::collections::HashMap<String, String>, SerdeError> {
559 self.depth += 1;
560 if self.depth > self.settings.max_depth() {
561 return Err(SerdeError::custom("maximum nesting depth exceeded"));
562 }
563 self.skip_whitespace();
564 if self.remaining().first() != Some(&b'{') {
565 return Err(SerdeError::TypeMismatch {
566 message: "expected object".into(),
567 });
568 }
569 self.advance_by(1);
570 let mut out = std::collections::HashMap::new();
571 loop {
572 self.skip_whitespace();
573 if self.remaining().first() == Some(&b'}') {
574 self.advance_by(1);
575 break;
576 }
577 if self.remaining().first() != Some(&b'"') {
578 return Err(SerdeError::InvalidInput {
579 message: "expected key".into(),
580 });
581 }
582 let key = self.parse_key()?;
583 self.skip_whitespace();
584 if self.remaining().first() != Some(&b':') {
585 return Err(SerdeError::InvalidInput {
586 message: "expected colon".into(),
587 });
588 }
589 self.advance_by(1);
590 self.skip_whitespace();
591 let val = self.read_string(_schema)?;
592 out.insert(key.into_owned(), val);
593 }
594 self.depth -= 1;
595 Ok(out)
596 }
597
598 fn read_timestamp(&mut self, schema: &Schema) -> Result<DateTime, SerdeError> {
599 self.skip_whitespace();
600 let rem = self.remaining();
601 match rem.first() {
602 Some(b'"') => {
603 let s = self.read_string(schema)?;
604 let format = if let Some(ts_trait) = schema.timestamp_format() {
606 match ts_trait.format() {
607 aws_smithy_schema::traits::TimestampFormat::HttpDate => {
608 aws_smithy_types::date_time::Format::HttpDate
609 }
610 aws_smithy_schema::traits::TimestampFormat::EpochSeconds => {
611 aws_smithy_types::date_time::Format::EpochSeconds
612 }
613 aws_smithy_schema::traits::TimestampFormat::DateTime => {
614 aws_smithy_types::date_time::Format::DateTimeWithOffset
615 }
616 }
617 } else {
618 aws_smithy_types::date_time::Format::DateTimeWithOffset
620 };
621 DateTime::from_str(&s, format)
622 .map_err(|e| SerdeError::custom(format!("invalid timestamp string: {e}")))
623 }
624 Some(b'-') | Some(b'0'..=b'9') => {
625 let start = self.position;
627 self.consume_number();
628 let num_str =
629 std::str::from_utf8(&self.input[start..self.position]).map_err(|e| {
630 SerdeError::InvalidInput {
631 message: e.to_string(),
632 }
633 })?;
634 if num_str.contains('.') || num_str.contains('e') || num_str.contains('E') {
635 let f: f64 = num_str.parse().map_err(|e: std::num::ParseFloatError| {
636 SerdeError::InvalidInput {
637 message: e.to_string(),
638 }
639 })?;
640 Ok(DateTime::from_secs_f64(f))
641 } else if num_str.starts_with('-') {
642 let n: i64 = num_str.parse().map_err(|e: std::num::ParseIntError| {
643 SerdeError::InvalidInput {
644 message: e.to_string(),
645 }
646 })?;
647 Ok(DateTime::from_secs(n))
648 } else {
649 let n: u64 = num_str.parse().map_err(|e: std::num::ParseIntError| {
650 SerdeError::InvalidInput {
651 message: e.to_string(),
652 }
653 })?;
654 Ok(DateTime::from_secs(n as i64))
655 }
656 }
657 _ => Err(SerdeError::TypeMismatch {
658 message: "expected timestamp".into(),
659 }),
660 }
661 }
662
663 fn read_document(&mut self, _schema: &Schema) -> Result<Document, SerdeError> {
664 self.depth += 1;
665 if self.depth > self.settings.max_depth() {
666 return Err(SerdeError::custom("maximum nesting depth exceeded"));
667 }
668 self.skip_whitespace();
669 let result = match self.remaining().first() {
670 Some(b'"') => Ok(Document::String(self.read_string(_schema)?)),
671 Some(b't') | Some(b'f') => Ok(Document::Bool(self.read_boolean(_schema)?)),
672 Some(b'n') => {
673 if self.remaining().starts_with(b"null") {
674 self.advance_by(4);
675 Ok(Document::Null)
676 } else {
677 Err(SerdeError::InvalidInput {
678 message: "unexpected token in document".into(),
679 })
680 }
681 }
682 Some(b'{') => {
683 self.advance_by(1);
684 let mut map = std::collections::HashMap::new();
685 loop {
686 self.skip_whitespace();
687 if self.remaining().first() == Some(&b'}') {
688 self.advance_by(1);
689 break;
690 }
691 if self.remaining().first() != Some(&b'"') {
692 return Err(SerdeError::InvalidInput {
693 message: "expected object key in document".into(),
694 });
695 }
696 let key = self.parse_key()?.into_owned();
697 self.skip_whitespace();
698 if self.remaining().first() != Some(&b':') {
699 return Err(SerdeError::InvalidInput {
700 message: "expected colon in document object".into(),
701 });
702 }
703 self.advance_by(1);
704 let value = self.read_document(_schema)?;
705 map.insert(key, value);
706 }
707 Ok(Document::Object(map))
708 }
709 Some(b'[') => {
710 self.advance_by(1);
711 let mut arr = Vec::new();
712 loop {
713 self.skip_whitespace();
714 match self.remaining().first() {
715 Some(&b']') => {
716 self.advance_by(1);
717 break;
718 }
719 None => {
720 return Err(SerdeError::InvalidInput {
721 message: "unexpected end of input in document array".into(),
722 })
723 }
724 _ => arr.push(self.read_document(_schema)?),
725 }
726 }
727 Ok(Document::Array(arr))
728 }
729 Some(c) if *c == b'-' || c.is_ascii_digit() => {
730 let rem = self.remaining();
732 let mut len = 0;
733 let mut is_float = false;
734 let mut is_negative = false;
735 for (i, &b) in rem.iter().enumerate() {
736 if b == b'-' && i == 0 {
737 is_negative = true;
738 len += 1;
739 } else if b.is_ascii_digit() || b == b'+' {
740 len += 1;
741 } else if b == b'.' || b == b'e' || b == b'E' {
742 is_float = true;
743 len += 1;
744 } else {
745 break;
746 }
747 }
748 let pos = self.position;
749 self.advance_by(len);
750 let s = std::str::from_utf8(&self.input[pos..pos + len]).map_err(|e| {
751 SerdeError::InvalidInput {
752 message: e.to_string(),
753 }
754 })?;
755 if is_float {
756 let f = s.parse::<f64>().map_err(|e| SerdeError::InvalidInput {
757 message: e.to_string(),
758 })?;
759 Ok(Document::Number(aws_smithy_types::Number::Float(f)))
760 } else if is_negative {
761 let n = s.parse::<i64>().map_err(|e| SerdeError::InvalidInput {
762 message: e.to_string(),
763 })?;
764 Ok(Document::Number(aws_smithy_types::Number::NegInt(n)))
765 } else {
766 let n = s.parse::<u64>().map_err(|e| SerdeError::InvalidInput {
767 message: e.to_string(),
768 })?;
769 Ok(Document::Number(aws_smithy_types::Number::PosInt(n)))
770 }
771 }
772 _ => Err(SerdeError::InvalidInput {
773 message: "unexpected token in document".into(),
774 }),
775 };
776 if result.is_ok() {
777 self.depth -= 1;
778 }
779 result
780 }
781
782 fn is_null(&self) -> bool {
783 let remaining = self.remaining();
784 remaining.len() >= 4
785 && &remaining[..4] == b"null"
786 && !remaining.get(4).is_some_and(|b| b.is_ascii_alphanumeric())
787 }
788
789 fn read_null(&mut self) -> Result<(), SerdeError> {
790 self.skip_whitespace();
791 if self.is_null() {
792 self.advance_by(4);
793 }
794 Ok(())
795 }
796
797 fn container_size(&self) -> Option<usize> {
798 let mut iter = json_token_iter(self.remaining());
799 match iter.next()? {
800 Ok(Token::StartArray { .. }) => {
801 let mut count = 0;
802 let mut depth = 1;
803 for token in iter {
804 match token {
805 Ok(Token::StartArray { .. }) | Ok(Token::StartObject { .. }) => {
806 if depth == 1 {
807 count += 1;
808 }
809 depth += 1;
810 }
811 Ok(Token::EndArray { .. }) | Ok(Token::EndObject { .. }) => {
812 depth -= 1;
813 if depth == 0 {
814 return Some(count);
815 }
816 }
817 Ok(Token::ValueBool { .. })
818 | Ok(Token::ValueNull { .. })
819 | Ok(Token::ValueString { .. })
820 | Ok(Token::ValueNumber { .. })
821 if depth == 1 =>
822 {
823 count += 1
824 }
825 _ => {}
826 }
827 }
828 None
829 }
830 Ok(Token::StartObject { .. }) => {
831 let mut count = 0;
832 let mut depth = 1;
833 for token in iter {
834 match token {
835 Ok(Token::StartArray { .. }) | Ok(Token::StartObject { .. }) => depth += 1,
836 Ok(Token::EndArray { .. }) | Ok(Token::EndObject { .. }) => {
837 depth -= 1;
838 if depth == 0 {
839 return Some(count);
840 }
841 }
842 Ok(Token::ObjectKey { .. }) if depth == 1 => count += 1,
843 _ => {}
844 }
845 }
846 None
847 }
848 _ => None,
849 }
850 }
851}
852
853impl<'a> JsonDeserializer<'a> {
854 fn skip_whitespace(&mut self) {
855 while self.position < self.input.len() {
856 match self.input[self.position] {
857 b' ' | b'\t' | b'\n' | b'\r' | b',' => self.position += 1,
858 _ => break,
859 }
860 }
861 }
862
863 fn consume_number(&mut self) {
864 let mut len = 0;
865 for &b in self.remaining() {
866 if b.is_ascii_digit() || b == b'-' || b == b'.' || b == b'e' || b == b'E' || b == b'+' {
867 len += 1;
868 } else {
869 break;
870 }
871 }
872 self.advance_by(len);
873 }
874
875 fn skip_value(&mut self) -> Result<(), SerdeError> {
876 self.skip_whitespace();
877 let mut depth: usize = 0;
878 loop {
879 self.skip_whitespace();
880 match self.remaining().first().copied() {
881 Some(b'{') | Some(b'[') => {
882 self.advance_by(1);
883 depth += 1;
884 }
885 Some(b'}') | Some(b']') => {
886 if depth == 0 {
887 return Err(SerdeError::InvalidInput {
888 message: "unexpected end token".into(),
889 });
890 }
891 self.advance_by(1);
892 depth -= 1;
893 if depth == 0 {
894 return Ok(());
895 }
896 }
897 Some(b'"') => {
898 let mut i = 1;
900 let rem = self.remaining();
901 while i < rem.len() {
902 if rem[i] == b'\\' {
903 i += 2; } else if rem[i] == b'"' {
905 i += 1;
906 break;
907 } else {
908 i += 1;
909 }
910 }
911 self.advance_by(i);
912 if depth > 0 {
914 self.skip_whitespace();
915 if self.remaining().first() == Some(&b':') {
916 self.advance_by(1);
917 continue; }
919 }
920 if depth == 0 {
921 return Ok(());
922 }
923 }
924 Some(b't') => {
925 if !self.remaining().starts_with(b"true") {
926 return Err(SerdeError::InvalidInput {
927 message: "expected `true`".into(),
928 });
929 }
930 self.advance_by(4);
931 if depth == 0 {
932 return Ok(());
933 }
934 }
935 Some(b'f') => {
936 if !self.remaining().starts_with(b"false") {
937 return Err(SerdeError::InvalidInput {
938 message: "expected `false`".into(),
939 });
940 }
941 self.advance_by(5);
942 if depth == 0 {
943 return Ok(());
944 }
945 }
946 Some(b'n') => {
947 if !self.remaining().starts_with(b"null") {
948 return Err(SerdeError::InvalidInput {
949 message: "expected `null`".into(),
950 });
951 }
952 self.advance_by(4);
953 if depth == 0 {
954 return Ok(());
955 }
956 }
957 Some(c) if c == b'-' || c.is_ascii_digit() => {
958 self.consume_number();
959 if depth == 0 {
960 return Ok(());
961 }
962 }
963 Some(_) => {
964 return Err(SerdeError::InvalidInput {
965 message: "unexpected token in skip_value".into(),
966 })
967 }
968 None => {
969 return Err(SerdeError::InvalidInput {
970 message: "unexpected end of input".into(),
971 })
972 }
973 }
974 }
975 }
976
977 fn read_integer_value(&mut self) -> Result<i64, SerdeError> {
978 self.skip_whitespace();
979 let rem = self.remaining();
980 let mut len = 0;
981 for &b in rem {
982 if b.is_ascii_digit() || b == b'-' || b == b'+' {
983 len += 1;
984 } else {
985 break;
986 }
987 }
988 if len == 0 {
989 return Err(SerdeError::TypeMismatch {
990 message: "expected integer".into(),
991 });
992 }
993 let s = std::str::from_utf8(&rem[..len]).map_err(|e| SerdeError::InvalidInput {
994 message: e.to_string(),
995 })?;
996 let n = s.parse::<i64>().map_err(|e| SerdeError::InvalidInput {
997 message: e.to_string(),
998 })?;
999 self.advance_by(len);
1000 Ok(n)
1001 }
1002
1003 fn read_float_value(&mut self) -> Result<f64, SerdeError> {
1004 self.skip_whitespace();
1005 let rem = self.remaining();
1006 if rem.first() == Some(&b'"') {
1008 let s = self.read_string(&aws_smithy_schema::prelude::STRING)?;
1009 return match s.as_str() {
1010 "NaN" => Ok(f64::NAN),
1011 "Infinity" => Ok(f64::INFINITY),
1012 "-Infinity" => Ok(f64::NEG_INFINITY),
1013 _ => s.parse::<f64>().map_err(|e| SerdeError::InvalidInput {
1014 message: e.to_string(),
1015 }),
1016 };
1017 }
1018 let mut len = 0;
1019 for &b in rem {
1020 if b.is_ascii_digit() || b == b'-' || b == b'+' || b == b'.' || b == b'e' || b == b'E' {
1021 len += 1;
1022 } else {
1023 break;
1024 }
1025 }
1026 if len == 0 {
1027 return Err(SerdeError::TypeMismatch {
1028 message: "expected number".into(),
1029 });
1030 }
1031 let s = std::str::from_utf8(&rem[..len]).map_err(|e| SerdeError::InvalidInput {
1032 message: e.to_string(),
1033 })?;
1034 let n = s.parse::<f64>().map_err(|e| SerdeError::InvalidInput {
1035 message: e.to_string(),
1036 })?;
1037 self.advance_by(len);
1038 Ok(n)
1039 }
1040}
1041
1042#[cfg(test)]
1043mod tests {
1044 use super::*;
1045
1046 fn dummy_schema() -> &'static aws_smithy_schema::Schema {
1047 &aws_smithy_schema::prelude::STRING
1048 }
1049
1050 #[test]
1051 fn test_read_boolean() {
1052 let mut deser = JsonDeserializer::new(b"true", Arc::new(JsonCodecSettings::default()));
1053 assert!(deser.read_boolean(dummy_schema()).unwrap());
1054
1055 let mut deser = JsonDeserializer::new(b"false", Arc::new(JsonCodecSettings::default()));
1056 assert!(!(deser.read_boolean(dummy_schema()).unwrap()));
1057 }
1058
1059 #[test]
1060 fn test_read_integer() {
1061 let mut deser = JsonDeserializer::new(b"42", Arc::new(JsonCodecSettings::default()));
1062 assert_eq!(deser.read_integer(dummy_schema()).unwrap(), 42);
1063
1064 let mut deser = JsonDeserializer::new(b"-123", Arc::new(JsonCodecSettings::default()));
1065 assert_eq!(deser.read_integer(dummy_schema()).unwrap(), -123);
1066 }
1067
1068 #[test]
1069 fn test_read_long() {
1070 let mut deser = JsonDeserializer::new(
1071 b"9223372036854775807",
1072 Arc::new(JsonCodecSettings::default()),
1073 );
1074 assert_eq!(deser.read_long(dummy_schema()).unwrap(), i64::MAX);
1075 }
1076
1077 #[test]
1078 fn test_read_float() {
1079 let mut deser = JsonDeserializer::new(b"3.15", Arc::new(JsonCodecSettings::default()));
1080 assert!((deser.read_float(dummy_schema()).unwrap() - 3.15).abs() < 0.01);
1081 }
1082
1083 #[test]
1084 fn test_read_double() {
1085 let mut deser = JsonDeserializer::new(b"2.72", Arc::new(JsonCodecSettings::default()));
1086 assert!((deser.read_double(dummy_schema()).unwrap() - 2.72).abs() < 0.001);
1087 }
1088
1089 #[test]
1090 fn test_read_string() {
1091 let mut deser =
1092 JsonDeserializer::new(br#""hello world""#, Arc::new(JsonCodecSettings::default()));
1093 assert_eq!(deser.read_string(dummy_schema()).unwrap(), "hello world");
1094
1095 let mut deser =
1096 JsonDeserializer::new(br#""hello\nworld""#, Arc::new(JsonCodecSettings::default()));
1097 assert_eq!(deser.read_string(dummy_schema()).unwrap(), "hello\nworld");
1098 }
1099
1100 #[test]
1101 fn test_is_null() {
1102 let deser = JsonDeserializer::new(b"null", Arc::new(JsonCodecSettings::default()));
1103 assert!(deser.is_null());
1104
1105 let deser = JsonDeserializer::new(b"42", Arc::new(JsonCodecSettings::default()));
1106 assert!(!deser.is_null());
1107 }
1108
1109 #[test]
1110 fn test_read_byte_range() {
1111 let mut deser = JsonDeserializer::new(b"127", Arc::new(JsonCodecSettings::default()));
1112 assert_eq!(deser.read_byte(dummy_schema()).unwrap(), 127);
1113
1114 let mut deser = JsonDeserializer::new(b"128", Arc::new(JsonCodecSettings::default()));
1115 assert!(deser.read_byte(dummy_schema()).is_err());
1116 }
1117
1118 #[test]
1119 fn test_read_struct() {
1120 use aws_smithy_schema::Schema;
1121
1122 #[derive(Debug, Default, PartialEq)]
1123 struct Person {
1124 first_name: String,
1125 last_name: String,
1126 age: i32,
1127 }
1128
1129 static FIRST_NAME: Schema = Schema::new_member(
1130 aws_smithy_schema::shape_id!("test", "Person"),
1131 aws_smithy_schema::ShapeType::String,
1132 "firstName",
1133 0,
1134 );
1135 static LAST_NAME: Schema = Schema::new_member(
1136 aws_smithy_schema::shape_id!("test", "Person"),
1137 aws_smithy_schema::ShapeType::String,
1138 "lastName",
1139 1,
1140 );
1141 static AGE: Schema = Schema::new_member(
1142 aws_smithy_schema::shape_id!("test", "Person"),
1143 aws_smithy_schema::ShapeType::Integer,
1144 "age",
1145 2,
1146 );
1147 static PERSON_SCHEMA: Schema = Schema::new_struct(
1148 aws_smithy_schema::shape_id!("test", "Person"),
1149 aws_smithy_schema::ShapeType::Structure,
1150 &[&FIRST_NAME, &LAST_NAME, &AGE],
1151 );
1152
1153 fn consume_person(
1154 person: &mut Person,
1155 schema: &Schema,
1156 deser: &mut dyn ShapeDeserializer,
1157 ) -> Result<(), SerdeError> {
1158 match schema.member_name() {
1159 Some("firstName") => person.first_name = deser.read_string(schema)?,
1160 Some("lastName") => person.last_name = deser.read_string(schema)?,
1161 Some("age") => person.age = deser.read_integer(schema)?,
1162 _ => {}
1163 }
1164 Ok(())
1165 }
1166
1167 let json = br#"{"lastName":"Smithy","firstName":"Alice","age":30}"#;
1168 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1169 let mut person = Person::default();
1170 deser
1171 .read_struct(&PERSON_SCHEMA, &mut |member, d| {
1172 consume_person(&mut person, member, d)
1173 })
1174 .unwrap();
1175 assert_eq!(
1176 person,
1177 Person {
1178 first_name: "Alice".to_string(),
1179 last_name: "Smithy".to_string(),
1180 age: 30
1181 }
1182 );
1183
1184 let json =
1185 br#"{"firstName": "Alice","age":12345678, "lastName":"\"Smithy\""}"#;
1186 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1187 let mut person = Person::default();
1188 deser
1189 .read_struct(&PERSON_SCHEMA, &mut |member, d| {
1190 consume_person(&mut person, member, d)
1191 })
1192 .unwrap();
1193 assert_eq!(
1194 person,
1195 Person {
1196 first_name: "Alice".to_string(),
1197 last_name: "\"Smithy\"".to_string(),
1198 age: 12345678
1199 }
1200 );
1201 }
1202
1203 #[test]
1204 fn test_read_list() {
1205 let json = b"[1, 2, 3, 4, 5]";
1206 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1207 let capacity = deser.container_size().unwrap_or(0);
1208 let mut result = Vec::with_capacity(capacity);
1209 let allocated_capacity = result.capacity();
1210 deser
1211 .read_list(dummy_schema(), &mut |deser| {
1212 result.push(deser.read_integer(dummy_schema())?);
1213 Ok(())
1214 })
1215 .unwrap();
1216 assert_eq!(result, vec![1, 2, 3, 4, 5]);
1217 assert_eq!(result.capacity(), allocated_capacity);
1219
1220 let json = b"[]";
1221 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1222 let capacity = deser.container_size().unwrap_or(0);
1223 let mut result = Vec::<i32>::with_capacity(capacity);
1224 let allocated_capacity = result.capacity();
1225 deser
1226 .read_list(dummy_schema(), &mut |deser| {
1227 result.push(deser.read_integer(dummy_schema())?);
1228 Ok(())
1229 })
1230 .unwrap();
1231 assert_eq!(result, Vec::<i32>::new());
1232 assert_eq!(result.capacity(), allocated_capacity);
1234
1235 let json = br#"["hello", "world"]"#;
1236 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1237 let capacity = deser.container_size().unwrap_or(0);
1238 let mut result = Vec::with_capacity(capacity);
1239 let allocated_capacity = result.capacity();
1240 deser
1241 .read_list(dummy_schema(), &mut |deser| {
1242 result.push(deser.read_string(dummy_schema())?);
1243 Ok(())
1244 })
1245 .unwrap();
1246 assert_eq!(result, vec!["hello", "world"]);
1247 assert_eq!(result.capacity(), allocated_capacity);
1249 }
1250
1251 #[test]
1252 fn test_container_size() {
1253 let deser =
1254 JsonDeserializer::new(b"[1, 2, 3, 4, 5]", Arc::new(JsonCodecSettings::default()));
1255 assert_eq!(deser.container_size(), Some(5));
1256
1257 let deser = JsonDeserializer::new(b"[]", Arc::new(JsonCodecSettings::default()));
1258 assert_eq!(deser.container_size(), Some(0));
1259
1260 let deser = JsonDeserializer::new(
1261 br#"{"a": 1, "b": 2, "c": 3}"#,
1262 Arc::new(JsonCodecSettings::default()),
1263 );
1264 assert_eq!(deser.container_size(), Some(3));
1265
1266 let deser = JsonDeserializer::new(b"{}", Arc::new(JsonCodecSettings::default()));
1267 assert_eq!(deser.container_size(), Some(0));
1268
1269 let deser = JsonDeserializer::new(
1270 b"[[1, 2], [3, 4], [5, 6]]",
1271 Arc::new(JsonCodecSettings::default()),
1272 );
1273 assert_eq!(deser.container_size(), Some(3));
1274
1275 let deser = JsonDeserializer::new(b"42", Arc::new(JsonCodecSettings::default()));
1276 assert_eq!(deser.container_size(), None);
1277 }
1278
1279 #[test]
1280 fn test_read_map() {
1281 use std::collections::HashMap;
1282
1283 let json = br#"{"a": 1, "b": 2, "c": 3}"#;
1284 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1285 let calculated_capacity = deser.container_size().unwrap_or(0);
1286 let mut result = HashMap::with_capacity(calculated_capacity);
1287 let allocated_capacity = result.capacity();
1288 deser
1289 .read_map(dummy_schema(), &mut |key, deser| {
1290 result.insert(key, deser.read_integer(dummy_schema())?);
1291 Ok(())
1292 })
1293 .unwrap();
1294 assert_eq!(result.len(), 3);
1295 assert_eq!(result.get("a"), Some(&1));
1296 assert_eq!(result.get("b"), Some(&2));
1297 assert_eq!(result.get("c"), Some(&3));
1298 assert_eq!(result.capacity(), allocated_capacity);
1300
1301 let json = b"{}";
1302 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1303 let calculated_capacity = deser.container_size().unwrap_or(0);
1304 let mut result = HashMap::<String, i32>::with_capacity(calculated_capacity);
1305 let allocated_capacity = result.capacity();
1306 deser
1307 .read_map(dummy_schema(), &mut |key, deser| {
1308 result.insert(key, deser.read_integer(dummy_schema())?);
1309 Ok(())
1310 })
1311 .unwrap();
1312 assert_eq!(result, HashMap::<String, i32>::new());
1313 assert_eq!(result.capacity(), allocated_capacity);
1315
1316 let json = br#"{"name": "Alice", "city": "Seattle"}"#;
1317 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1318 let calculated_capacity = deser.container_size().unwrap_or(0);
1319 let mut result = HashMap::with_capacity(calculated_capacity);
1320 let allocated_capacity = result.capacity();
1321 deser
1322 .read_map(dummy_schema(), &mut |key, deser| {
1323 result.insert(key, deser.read_string(dummy_schema())?);
1324 Ok(())
1325 })
1326 .unwrap();
1327 assert_eq!(result.len(), 2);
1328 assert_eq!(result.get("name"), Some(&"Alice".to_string()));
1329 assert_eq!(result.get("city"), Some(&"Seattle".to_string()));
1330 assert_eq!(result.capacity(), allocated_capacity);
1332 }
1333
1334 #[test]
1335 fn test_nested_complex_deserialization() {
1336 use aws_smithy_schema::Schema;
1337 use std::collections::HashMap;
1338
1339 #[derive(Debug, Default, PartialEq)]
1340 struct Address {
1341 street: String,
1342 city: String,
1343 zip: i32,
1344 }
1345 #[derive(Debug, Default, PartialEq)]
1346 struct Company {
1347 name: String,
1348 employees: Vec<String>,
1349 metadata: HashMap<String, i32>,
1350 active: bool,
1351 }
1352 #[derive(Debug, Default, PartialEq)]
1353 struct User {
1354 id: i64,
1355 name: String,
1356 scores: Vec<f64>,
1357 address: Address,
1358 companies: Vec<Company>,
1359 tags: HashMap<String, String>,
1360 }
1361
1362 static ADDR_STREET: Schema = Schema::new_member(
1364 aws_smithy_schema::shape_id!("test", "Address"),
1365 aws_smithy_schema::ShapeType::String,
1366 "street",
1367 0,
1368 );
1369 static ADDR_CITY: Schema = Schema::new_member(
1370 aws_smithy_schema::shape_id!("test", "Address"),
1371 aws_smithy_schema::ShapeType::String,
1372 "city",
1373 1,
1374 );
1375 static ADDR_ZIP: Schema = Schema::new_member(
1376 aws_smithy_schema::shape_id!("test", "Address"),
1377 aws_smithy_schema::ShapeType::Integer,
1378 "zip",
1379 2,
1380 );
1381 static ADDRESS_SCHEMA: Schema = Schema::new_struct(
1382 aws_smithy_schema::shape_id!("test", "Address"),
1383 aws_smithy_schema::ShapeType::Structure,
1384 &[&ADDR_STREET, &ADDR_CITY, &ADDR_ZIP],
1385 );
1386
1387 static COMP_NAME: Schema = Schema::new_member(
1389 aws_smithy_schema::shape_id!("test", "Company"),
1390 aws_smithy_schema::ShapeType::String,
1391 "name",
1392 0,
1393 );
1394 static COMP_EMPLOYEES: Schema = Schema::new_member(
1395 aws_smithy_schema::shape_id!("test", "Company"),
1396 aws_smithy_schema::ShapeType::List,
1397 "employees",
1398 1,
1399 );
1400 static COMP_METADATA: Schema = Schema::new_member(
1401 aws_smithy_schema::shape_id!("test", "Company"),
1402 aws_smithy_schema::ShapeType::Map,
1403 "metadata",
1404 2,
1405 );
1406 static COMP_ACTIVE: Schema = Schema::new_member(
1407 aws_smithy_schema::shape_id!("test", "Company"),
1408 aws_smithy_schema::ShapeType::Boolean,
1409 "active",
1410 3,
1411 );
1412 static COMPANY_SCHEMA: Schema = Schema::new_struct(
1413 aws_smithy_schema::shape_id!("test", "Company"),
1414 aws_smithy_schema::ShapeType::Structure,
1415 &[&COMP_NAME, &COMP_EMPLOYEES, &COMP_METADATA, &COMP_ACTIVE],
1416 );
1417
1418 static USER_ID: Schema = Schema::new_member(
1420 aws_smithy_schema::shape_id!("test", "User"),
1421 aws_smithy_schema::ShapeType::Long,
1422 "id",
1423 0,
1424 );
1425 static USER_NAME: Schema = Schema::new_member(
1426 aws_smithy_schema::shape_id!("test", "User"),
1427 aws_smithy_schema::ShapeType::String,
1428 "name",
1429 1,
1430 );
1431 static USER_SCORES: Schema = Schema::new_member(
1432 aws_smithy_schema::shape_id!("test", "User"),
1433 aws_smithy_schema::ShapeType::List,
1434 "scores",
1435 2,
1436 );
1437 static USER_ADDRESS: Schema = Schema::new_member(
1438 aws_smithy_schema::shape_id!("test", "User"),
1439 aws_smithy_schema::ShapeType::Structure,
1440 "address",
1441 3,
1442 );
1443 static USER_COMPANIES: Schema = Schema::new_member(
1444 aws_smithy_schema::shape_id!("test", "User"),
1445 aws_smithy_schema::ShapeType::List,
1446 "companies",
1447 4,
1448 );
1449 static USER_TAGS: Schema = Schema::new_member(
1450 aws_smithy_schema::shape_id!("test", "User"),
1451 aws_smithy_schema::ShapeType::Map,
1452 "tags",
1453 5,
1454 );
1455 static USER_SCHEMA: Schema = Schema::new_struct(
1456 aws_smithy_schema::shape_id!("test", "User"),
1457 aws_smithy_schema::ShapeType::Structure,
1458 &[
1459 &USER_ID,
1460 &USER_NAME,
1461 &USER_SCORES,
1462 &USER_ADDRESS,
1463 &USER_COMPANIES,
1464 &USER_TAGS,
1465 ],
1466 );
1467
1468 fn consume_address(
1469 addr: &mut Address,
1470 schema: &Schema,
1471 deser: &mut dyn ShapeDeserializer,
1472 ) -> Result<(), SerdeError> {
1473 match schema.member_name() {
1474 Some("street") => addr.street = deser.read_string(schema)?,
1475 Some("city") => addr.city = deser.read_string(schema)?,
1476 Some("zip") => addr.zip = deser.read_integer(schema)?,
1477 _ => {}
1478 }
1479 Ok(())
1480 }
1481
1482 fn consume_company(
1483 comp: &mut Company,
1484 schema: &Schema,
1485 deser: &mut dyn ShapeDeserializer,
1486 ) -> Result<(), SerdeError> {
1487 match schema.member_name() {
1488 Some("name") => comp.name = deser.read_string(schema)?,
1489 Some("active") => comp.active = deser.read_boolean(schema)?,
1490 Some("employees") => {
1491 let mut v = Vec::new();
1492 deser.read_list(schema, &mut |d| {
1493 v.push(d.read_string(dummy_schema())?);
1494 Ok(())
1495 })?;
1496 comp.employees = v;
1497 }
1498 Some("metadata") => {
1499 let mut m = HashMap::new();
1500 deser.read_map(schema, &mut |k, d| {
1501 m.insert(k, d.read_integer(dummy_schema())?);
1502 Ok(())
1503 })?;
1504 comp.metadata = m;
1505 }
1506 _ => {}
1507 }
1508 Ok(())
1509 }
1510
1511 fn consume_user(
1512 user: &mut User,
1513 schema: &Schema,
1514 deser: &mut dyn ShapeDeserializer,
1515 ) -> Result<(), SerdeError> {
1516 match schema.member_name() {
1517 Some("id") => user.id = deser.read_long(schema)?,
1518 Some("name") => user.name = deser.read_string(schema)?,
1519 Some("scores") => {
1520 let mut v = Vec::new();
1521 deser.read_list(schema, &mut |d| {
1522 v.push(d.read_double(dummy_schema())?);
1523 Ok(())
1524 })?;
1525 user.scores = v;
1526 }
1527 Some("address") => {
1528 let mut addr = Address::default();
1529 deser.read_struct(&ADDRESS_SCHEMA, &mut |member, d| {
1530 consume_address(&mut addr, member, d)
1531 })?;
1532 user.address = addr;
1533 }
1534 Some("companies") => {
1535 let mut v = Vec::new();
1536 deser.read_list(schema, &mut |d| {
1537 let mut comp = Company::default();
1538 d.read_struct(&COMPANY_SCHEMA, &mut |member, d| {
1539 consume_company(&mut comp, member, d)
1540 })?;
1541 v.push(comp);
1542 Ok(())
1543 })?;
1544 user.companies = v;
1545 }
1546 Some("tags") => {
1547 let mut m = HashMap::new();
1548 deser.read_map(schema, &mut |k, d| {
1549 m.insert(k, d.read_string(dummy_schema())?);
1550 Ok(())
1551 })?;
1552 user.tags = m;
1553 }
1554 _ => {}
1555 }
1556 Ok(())
1557 }
1558
1559 let json = br#"{
1560 "id": 12345,
1561 "name": "John Doe",
1562 "scores": [95.5, 87.3, 92.1],
1563 "address": {
1564 "street": "123 Main St",
1565 "city": "Seattle",
1566 "zip": 98101
1567 },
1568 "companies": [
1569 {
1570 "name": "TechCorp",
1571 "employees": ["Alice", "Bob"],
1572 "metadata": {"founded": 2010, "size": 500},
1573 "active": true
1574 },
1575 {
1576 "name": "StartupInc",
1577 "employees": ["Charlie"],
1578 "metadata": {"founded": 2020},
1579 "active": false
1580 }
1581 ],
1582 "tags": {"role": "admin", "level": "senior"}
1583 }"#;
1584
1585 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1586 let mut user = User::default();
1587 deser
1588 .read_struct(&USER_SCHEMA, &mut |member, d| {
1589 consume_user(&mut user, member, d)
1590 })
1591 .unwrap();
1592
1593 assert_eq!(user.id, 12345);
1594 assert_eq!(user.name, "John Doe");
1595 assert_eq!(user.scores, vec![95.5, 87.3, 92.1]);
1596 assert_eq!(user.address.street, "123 Main St");
1597 assert_eq!(user.address.city, "Seattle");
1598 assert_eq!(user.address.zip, 98101);
1599 assert_eq!(user.companies.len(), 2);
1600 assert_eq!(user.companies[0].name, "TechCorp");
1601 assert_eq!(user.companies[0].employees, vec!["Alice", "Bob"]);
1602 assert_eq!(user.companies[0].metadata.get("founded"), Some(&2010));
1603 assert_eq!(user.companies[0].metadata.get("size"), Some(&500));
1604 assert!(user.companies[0].active);
1605 assert_eq!(user.companies[1].name, "StartupInc");
1606 assert_eq!(user.companies[1].employees, vec!["Charlie"]);
1607 assert_eq!(user.companies[1].metadata.get("founded"), Some(&2020));
1608 assert!(!user.companies[1].active);
1609 assert_eq!(user.tags.get("role"), Some(&"admin".to_string()));
1610 assert_eq!(user.tags.get("level"), Some(&"senior".to_string()));
1611 }
1612
1613 #[test]
1614 fn test_json_name_deserialization() {
1615 use aws_smithy_schema::Schema;
1616
1617 static FOO_MEMBER: Schema = Schema::new_member(
1618 aws_smithy_schema::shape_id!("test", "MyStruct"),
1619 aws_smithy_schema::ShapeType::String,
1620 "foo",
1621 0,
1622 );
1623 static BAR_MEMBER: Schema = Schema::new_member(
1625 aws_smithy_schema::shape_id!("test", "MyStruct"),
1626 aws_smithy_schema::ShapeType::Integer,
1627 "bar",
1628 1,
1629 )
1630 .with_json_name("Baz");
1631 static STRUCT_SCHEMA: Schema = Schema::new_struct(
1632 aws_smithy_schema::shape_id!("test", "MyStruct"),
1633 aws_smithy_schema::ShapeType::Structure,
1634 &[&FOO_MEMBER, &BAR_MEMBER],
1635 );
1636
1637 let json = br#"{"foo":"hello","Baz":42}"#;
1638
1639 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1641 let (mut foo, mut bar) = (None::<String>, None::<i32>);
1642 deser
1643 .read_struct(&STRUCT_SCHEMA, &mut |member, d| {
1644 match member.member_name() {
1645 Some("foo") => foo = Some(d.read_string(member)?),
1646 Some("bar") => bar = Some(d.read_integer(member)?),
1647 _ => {}
1648 }
1649 Ok(())
1650 })
1651 .unwrap();
1652 assert_eq!(foo.as_deref(), Some("hello"));
1653 assert_eq!(bar, Some(42));
1654
1655 let mut deser = JsonDeserializer::new(
1657 json,
1658 Arc::new(JsonCodecSettings::builder().use_json_name(false).build()),
1659 );
1660 let (mut foo, mut bar) = (None::<String>, None::<i32>);
1661 deser
1662 .read_struct(&STRUCT_SCHEMA, &mut |member, d| {
1663 match member.member_name() {
1664 Some("foo") => foo = Some(d.read_string(member)?),
1665 Some("bar") => bar = Some(d.read_integer(member)?),
1666 _ => {}
1667 }
1668 Ok(())
1669 })
1670 .unwrap();
1671 assert_eq!(foo.as_deref(), Some("hello"));
1672 assert_eq!(bar, None); }
1674
1675 fn timestamp_schema() -> &'static aws_smithy_schema::Schema {
1676 &aws_smithy_schema::prelude::TIMESTAMP
1677 }
1678
1679 #[test]
1680 fn test_read_timestamp_positive_integer() {
1681 let mut deser =
1682 JsonDeserializer::new(b"1700000000", Arc::new(JsonCodecSettings::default()));
1683 let ts = deser.read_timestamp(timestamp_schema()).unwrap();
1684 assert_eq!(ts, DateTime::from_secs(1700000000));
1685 }
1686
1687 #[test]
1688 fn test_read_timestamp_negative_integer() {
1689 let mut deser = JsonDeserializer::new(b"-1000", Arc::new(JsonCodecSettings::default()));
1690 let ts = deser.read_timestamp(timestamp_schema()).unwrap();
1691 assert_eq!(ts, DateTime::from_secs(-1000));
1692 }
1693
1694 #[test]
1695 fn test_read_timestamp_float() {
1696 let mut deser =
1698 JsonDeserializer::new(b"1.615218678973E9", Arc::new(JsonCodecSettings::default()));
1699 let ts = deser.read_timestamp(timestamp_schema()).unwrap();
1700 assert_eq!(ts, DateTime::from_secs_f64(1.615218678973E9));
1701 }
1702
1703 #[test]
1704 fn test_read_timestamp_float_simple() {
1705 let mut deser =
1706 JsonDeserializer::new(b"1700000000.5", Arc::new(JsonCodecSettings::default()));
1707 let ts = deser.read_timestamp(timestamp_schema()).unwrap();
1708 assert_eq!(ts, DateTime::from_secs_f64(1700000000.5));
1709 }
1710
1711 #[test]
1712 fn test_read_timestamp_string_datetime() {
1713 let mut deser = JsonDeserializer::new(
1714 br#""2023-11-14T22:13:20Z""#,
1715 Arc::new(JsonCodecSettings::default()),
1716 );
1717 let ts = deser.read_timestamp(timestamp_schema()).unwrap();
1718 assert_eq!(ts, DateTime::from_secs(1700000000));
1719 }
1720
1721 #[test]
1722 fn test_read_timestamp_invalid() {
1723 let mut deser = JsonDeserializer::new(b"true", Arc::new(JsonCodecSettings::default()));
1724 assert!(deser.read_timestamp(timestamp_schema()).is_err());
1725 }
1726
1727 #[test]
1728 fn test_skip_value_empty_array() {
1729 use aws_smithy_schema::ShapeType;
1731 static KNOWN_MEMBER: Schema = Schema::new_member(
1732 aws_smithy_schema::shape_id!("test", "S"),
1733 ShapeType::String,
1734 "known",
1735 0,
1736 );
1737 static MEMBERS: &[&Schema] = &[&KNOWN_MEMBER];
1738 static TEST_SCHEMA: Schema = Schema::new_struct(
1739 aws_smithy_schema::shape_id!("test", "S"),
1740 ShapeType::Structure,
1741 MEMBERS,
1742 );
1743
1744 let json = br#"{"known":"yes","Items":[],"extra":true}"#;
1745 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1746 let mut known_val = String::new();
1747 deser
1748 .read_struct(&TEST_SCHEMA, &mut |member, deser| {
1749 if member.member_name() == Some("known") {
1750 known_val = deser.read_string(dummy_schema())?;
1751 }
1752 Ok(())
1753 })
1754 .unwrap();
1755 assert_eq!(known_val, "yes");
1756 }
1757
1758 #[test]
1759 fn test_skip_value_nested_objects() {
1760 use aws_smithy_schema::ShapeType;
1761 static D_MEMBER: Schema = Schema::new_member(
1762 aws_smithy_schema::shape_id!("test", "S"),
1763 ShapeType::String,
1764 "d",
1765 0,
1766 );
1767 static MEMBERS: &[&Schema] = &[&D_MEMBER];
1768 static TEST_SCHEMA: Schema = Schema::new_struct(
1769 aws_smithy_schema::shape_id!("test", "S"),
1770 ShapeType::Structure,
1771 MEMBERS,
1772 );
1773
1774 let json = br#"{"a":{"b":[1,2,{"c":3}]},"d":"ok"}"#;
1775 let mut deser = JsonDeserializer::new(json, Arc::new(JsonCodecSettings::default()));
1776 let mut d_val = String::new();
1777 deser
1778 .read_struct(&TEST_SCHEMA, &mut |member, deser| {
1779 if member.member_name() == Some("d") {
1780 d_val = deser.read_string(dummy_schema())?;
1781 }
1782 Ok(())
1783 })
1784 .unwrap();
1785 assert_eq!(d_val, "ok");
1786 }
1787
1788 #[test]
1794 fn regression_truncated_list_does_not_infinite_loop() {
1795 let mut deser = JsonDeserializer::new(b"[", Arc::new(JsonCodecSettings::default()));
1799 let err = deser
1800 .read_list(dummy_schema(), &mut |d| {
1801 d.read_integer(dummy_schema()).map(|_| ())
1802 })
1803 .expect_err("truncated list input must be rejected");
1804 assert!(
1805 matches!(err, SerdeError::InvalidInput { .. }),
1806 "expected InvalidInput, got {err:?}"
1807 );
1808 }
1809
1810 #[test]
1811 fn regression_truncated_string_list_does_not_infinite_loop() {
1812 let mut deser = JsonDeserializer::new(b"[", Arc::new(JsonCodecSettings::default()));
1815 let err = deser
1816 .read_string_list(dummy_schema())
1817 .expect_err("truncated string list input must be rejected");
1818 assert!(
1819 matches!(err, SerdeError::InvalidInput { .. }),
1820 "expected InvalidInput, got {err:?}"
1821 );
1822 }
1823
1824 #[test]
1825 fn regression_truncated_document_array_does_not_infinite_loop() {
1826 let mut deser = JsonDeserializer::new(b"[", Arc::new(JsonCodecSettings::default()));
1828 let err = deser
1829 .read_document(dummy_schema())
1830 .expect_err("truncated document array must be rejected");
1831 assert!(
1832 matches!(err, SerdeError::InvalidInput { .. }),
1833 "expected InvalidInput, got {err:?}"
1834 );
1835 }
1836
1837 #[test]
1838 fn regression_unterminated_object_key_does_not_panic() {
1839 use aws_smithy_schema::Schema;
1843
1844 static MEMBER: Schema = Schema::new_member(
1845 aws_smithy_schema::shape_id!("test", "S"),
1846 aws_smithy_schema::ShapeType::String,
1847 "m",
1848 0,
1849 );
1850 static SCHEMA: Schema = Schema::new_struct(
1851 aws_smithy_schema::shape_id!("test", "S"),
1852 aws_smithy_schema::ShapeType::Structure,
1853 &[&MEMBER],
1854 );
1855
1856 let mut deser = JsonDeserializer::new(br#"{""#, Arc::new(JsonCodecSettings::default()));
1857 let err = deser
1858 .read_struct(&SCHEMA, &mut |_, _| Ok(()))
1859 .expect_err("unterminated object key must be rejected");
1860 assert!(
1861 matches!(err, SerdeError::InvalidInput { .. }),
1862 "expected InvalidInput, got {err:?}"
1863 );
1864 }
1865
1866 #[test]
1867 fn regression_skip_value_truncated_true_does_not_panic() {
1868 use aws_smithy_schema::Schema;
1872
1873 static MEMBER: Schema = Schema::new_member(
1874 aws_smithy_schema::shape_id!("test", "S"),
1875 aws_smithy_schema::ShapeType::String,
1876 "known",
1877 0,
1878 );
1879 static SCHEMA: Schema = Schema::new_struct(
1880 aws_smithy_schema::shape_id!("test", "S"),
1881 aws_smithy_schema::ShapeType::Structure,
1882 &[&MEMBER],
1883 );
1884
1885 let input = br#"{"":t"#;
1889 let mut deser = JsonDeserializer::new(input, Arc::new(JsonCodecSettings::default()));
1890 let err = deser
1891 .read_struct(&SCHEMA, &mut |_, _| Ok(()))
1892 .expect_err("truncated `true` literal must be rejected");
1893 assert!(
1894 matches!(err, SerdeError::InvalidInput { .. }),
1895 "expected InvalidInput, got {err:?}"
1896 );
1897 }
1898
1899 #[test]
1900 fn regression_skip_value_rejects_malformed_true_literal() {
1901 use aws_smithy_schema::Schema;
1906
1907 static MEMBER: Schema = Schema::new_member(
1908 aws_smithy_schema::shape_id!("test", "S"),
1909 aws_smithy_schema::ShapeType::String,
1910 "known",
1911 0,
1912 );
1913 static SCHEMA: Schema = Schema::new_struct(
1914 aws_smithy_schema::shape_id!("test", "S"),
1915 aws_smithy_schema::ShapeType::Structure,
1916 &[&MEMBER],
1917 );
1918
1919 for bad in [
1920 &br#"{"":t!!!}"#[..],
1921 &br#"{"":f!!!!}"#[..],
1922 &br#"{"":n!!!}"#[..],
1923 ] {
1924 let mut deser = JsonDeserializer::new(bad, Arc::new(JsonCodecSettings::default()));
1925 let result = deser.read_struct(&SCHEMA, &mut |_, _| Ok(()));
1926 assert!(
1927 matches!(result, Err(SerdeError::InvalidInput { .. })),
1928 "expected InvalidInput for malformed input {:?}, got {:?}",
1929 std::str::from_utf8(bad).unwrap_or("<non-utf8>"),
1930 result
1931 );
1932 }
1933 }
1934
1935 #[test]
1936 fn regression_truncated_struct_does_not_infinite_loop() {
1937 use aws_smithy_schema::Schema;
1942
1943 static MEMBER: Schema = Schema::new_member(
1944 aws_smithy_schema::shape_id!("test", "S"),
1945 aws_smithy_schema::ShapeType::String,
1946 "m",
1947 0,
1948 );
1949 static SCHEMA: Schema = Schema::new_struct(
1950 aws_smithy_schema::shape_id!("test", "S"),
1951 aws_smithy_schema::ShapeType::Structure,
1952 &[&MEMBER],
1953 );
1954
1955 let mut deser = JsonDeserializer::new(b"{", Arc::new(JsonCodecSettings::default()));
1956 let err = deser
1957 .read_struct(&SCHEMA, &mut |_, _| Ok(()))
1958 .expect_err("truncated struct input must be rejected");
1959 assert!(
1960 matches!(err, SerdeError::InvalidInput { .. }),
1961 "expected InvalidInput, got {err:?}"
1962 );
1963 }
1964
1965 #[test]
1966 fn regression_truncated_map_does_not_infinite_loop() {
1967 let mut deser = JsonDeserializer::new(b"{", Arc::new(JsonCodecSettings::default()));
1969 let err = deser
1970 .read_map(dummy_schema(), &mut |_, _| Ok(()))
1971 .expect_err("truncated map input must be rejected");
1972 assert!(
1973 matches!(err, SerdeError::InvalidInput { .. }),
1974 "expected InvalidInput, got {err:?}"
1975 );
1976 }
1977
1978 fn build_nested(open: &str, close: &str, n: usize) -> Vec<u8> {
1990 build_nested_with_inner(open, "", close, n)
1991 }
1992
1993 fn build_nested_with_inner(open: &str, inner: &str, close: &str, n: usize) -> Vec<u8> {
1996 let mut out = String::with_capacity(open.len() * n + inner.len() + close.len() * n);
1997 for _ in 0..n {
1998 out.push_str(open);
1999 }
2000 out.push_str(inner);
2001 for _ in 0..n {
2002 out.push_str(close);
2003 }
2004 out.into_bytes()
2005 }
2006
2007 fn recursive_struct_schema() -> &'static Schema {
2012 static MEMBER_A: Schema = Schema::new_member(
2013 aws_smithy_schema::shape_id!("test", "Rec"),
2014 aws_smithy_schema::ShapeType::Structure,
2015 "a",
2016 0,
2017 );
2018 static RECURSIVE: Schema = Schema::new_struct(
2019 aws_smithy_schema::shape_id!("test", "Rec"),
2020 aws_smithy_schema::ShapeType::Structure,
2021 &[&MEMBER_A],
2022 );
2023 &RECURSIVE
2024 }
2025
2026 fn recursive_struct_consumer(
2028 _member: &Schema,
2029 deser: &mut dyn ShapeDeserializer,
2030 ) -> Result<(), SerdeError> {
2031 deser.read_struct(recursive_struct_schema(), &mut recursive_struct_consumer)
2032 }
2033
2034 fn recursive_list_consumer(deser: &mut dyn ShapeDeserializer) -> Result<(), SerdeError> {
2036 deser.read_list(dummy_schema(), &mut recursive_list_consumer)
2037 }
2038
2039 fn recursive_map_consumer(
2041 _key: String,
2042 deser: &mut dyn ShapeDeserializer,
2043 ) -> Result<(), SerdeError> {
2044 deser.read_map(dummy_schema(), &mut recursive_map_consumer)
2045 }
2046
2047 fn assert_depth_error(err: SerdeError) {
2048 match err {
2049 SerdeError::Custom { ref message } => {
2050 assert!(
2051 message.contains("maximum nesting depth exceeded"),
2052 "wrong error message: {message}"
2053 );
2054 }
2055 other => panic!("expected Custom depth error, got {other:?}"),
2056 }
2057 }
2058
2059 #[test]
2060 fn depth_limit_read_struct_rejects_deeply_nested() {
2061 let payload = build_nested(r#"{"a":"#, "}", 200);
2065 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2066 let err = deser
2067 .read_struct(recursive_struct_schema(), &mut recursive_struct_consumer)
2068 .expect_err("deeply nested struct must be rejected");
2069 assert_depth_error(err);
2070 }
2071
2072 #[test]
2073 fn depth_limit_read_struct_accepts_under_limit() {
2074 let payload = build_nested_with_inner(r#"{"a":"#, "{}", "}", 100);
2077 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2078 deser
2079 .read_struct(recursive_struct_schema(), &mut recursive_struct_consumer)
2080 .expect("100-level nesting should succeed");
2081 }
2082
2083 #[test]
2084 fn depth_limit_read_list_rejects_deeply_nested() {
2085 let payload = build_nested("[", "]", 200);
2086 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2087 let err = deser
2088 .read_list(dummy_schema(), &mut recursive_list_consumer)
2089 .expect_err("deeply nested list must be rejected");
2090 assert_depth_error(err);
2091 }
2092
2093 #[test]
2094 fn depth_limit_read_list_accepts_under_limit() {
2095 let payload = build_nested("[", "]", 100);
2097 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2098 deser
2099 .read_list(dummy_schema(), &mut recursive_list_consumer)
2100 .expect("100-level nesting should succeed");
2101 }
2102
2103 #[test]
2104 fn depth_limit_read_map_rejects_deeply_nested() {
2105 let payload = build_nested(r#"{"k":"#, "}", 200);
2106 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2107 let err = deser
2108 .read_map(dummy_schema(), &mut recursive_map_consumer)
2109 .expect_err("deeply nested map must be rejected");
2110 assert_depth_error(err);
2111 }
2112
2113 #[test]
2114 fn depth_limit_read_map_accepts_under_limit() {
2115 let payload = build_nested_with_inner(r#"{"k":"#, "{}", "}", 100);
2116 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2117 deser
2118 .read_map(dummy_schema(), &mut recursive_map_consumer)
2119 .expect("100-level nesting should succeed");
2120 }
2121
2122 #[test]
2123 fn depth_limit_read_document_rejects_deeply_nested_object() {
2124 let payload = build_nested(r#"{"k":"#, "}", 200);
2127 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2128 let err = deser
2129 .read_document(dummy_schema())
2130 .expect_err("deeply nested document must be rejected");
2131 assert_depth_error(err);
2132 }
2133
2134 #[test]
2135 fn depth_limit_read_document_rejects_deeply_nested_array() {
2136 let payload = build_nested("[", "]", 200);
2137 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2138 let err = deser
2139 .read_document(dummy_schema())
2140 .expect_err("deeply nested document array must be rejected");
2141 assert_depth_error(err);
2142 }
2143
2144 #[test]
2145 fn depth_limit_read_document_accepts_under_limit() {
2146 let payload = build_nested_with_inner(r#"{"k":"#, "{}", "}", 100);
2147 let mut deser = JsonDeserializer::new(&payload, Arc::new(JsonCodecSettings::default()));
2148 deser
2149 .read_document(dummy_schema())
2150 .expect("100-level nesting should succeed");
2151 }
2152
2153 #[test]
2154 fn depth_limit_respects_custom_max_depth_setting() {
2155 let settings = JsonCodecSettings::builder().max_depth(16).build();
2157
2158 let payload = build_nested("[", "]", 20);
2160 let mut deser = JsonDeserializer::new(&payload, Arc::new(settings));
2161 let err = deser
2162 .read_list(dummy_schema(), &mut recursive_list_consumer)
2163 .expect_err("20-level nesting must exceed custom limit of 16");
2164 assert_depth_error(err);
2165
2166 let settings_ok = JsonCodecSettings::builder().max_depth(16).build();
2168 let payload_ok = build_nested("[", "]", 10);
2169 let mut deser_ok = JsonDeserializer::new(&payload_ok, Arc::new(settings_ok));
2170 deser_ok
2171 .read_list(dummy_schema(), &mut recursive_list_consumer)
2172 .expect("10-level nesting should succeed under custom limit");
2173 }
2174}