1 + | /*
|
2 + | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 + | * SPDX-License-Identifier: Apache-2.0
|
4 + | */
|
5 + |
|
6 + | //! Shape deserialization interfaces for the Smithy data model.
|
7 + |
|
8 + | use crate::Schema;
|
9 + | use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
|
10 + | use std::error::Error;
|
11 + |
|
12 + | /// Deserializes Smithy shapes from a serial format.
|
13 + | ///
|
14 + | /// This trait provides a format-agnostic API for deserializing the Smithy data model.
|
15 + | /// Implementations read from a serial format and create data objects based on schemas.
|
16 + | ///
|
17 + | /// The deserializer uses a consumer pattern for aggregate types (structures, lists, maps)
|
18 + | /// to avoid trait object limitations and enable efficient deserialization without
|
19 + | /// intermediate allocations.
|
20 + | ///
|
21 + | /// # Consumer Pattern
|
22 + | ///
|
23 + | /// For aggregate types, the deserializer calls a consumer function for each element/member.
|
24 + | /// The consumer receives mutable state and updates it with each deserialized value.
|
25 + | /// This pattern:
|
26 + | /// - Avoids trait object issues with generic methods
|
27 + | /// - Enables zero-cost abstractions (closures can be inlined)
|
28 + | /// - Allows caller to control deserialization order and state management
|
29 + | /// - Matches the SEP's recommendation for compiled typed languages
|
30 + | ///
|
31 + | /// # Example
|
32 + | ///
|
33 + | /// ```ignore
|
34 + | /// // Deserializing a structure
|
35 + | /// let mut builder = MyStructBuilder::default();
|
36 + | /// deserializer.read_struct(
|
37 + | /// &MY_STRUCT_SCHEMA,
|
38 + | /// builder,
|
39 + | /// |mut builder, member, deser| {
|
40 + | /// match member.member_index() {
|
41 + | /// 0 => builder.field1 = Some(deser.read_string(member)?),
|
42 + | /// 1 => builder.field2 = Some(deser.read_i32(member)?),
|
43 + | /// _ => {}
|
44 + | /// }
|
45 + | /// Ok(builder)
|
46 + | /// },
|
47 + | /// )?;
|
48 + | /// let my_struct = builder.build();
|
49 + | /// ```
|
50 + | pub trait ShapeDeserializer {
|
51 + | /// The error type returned by deserialization operations.
|
52 + | type Error: Error;
|
53 + |
|
54 + | /// Reads a structure from the deserializer.
|
55 + | ///
|
56 + | /// The structure deserialization is driven by a consumer callback that is called
|
57 + | /// for each member. The consumer receives the current state, the member schema,
|
58 + | /// and the deserializer, and returns the updated state.
|
59 + | ///
|
60 + | /// # Arguments
|
61 + | ///
|
62 + | /// * `schema` - The schema of the structure being deserialized
|
63 + | /// * `state` - Initial state (typically a builder)
|
64 + | /// * `consumer` - Callback invoked for each member with (state, member_schema, deserializer)
|
65 + | ///
|
66 + | /// # Returns
|
67 + | ///
|
68 + | /// The final state after processing all members
|
69 + | fn read_struct<T, F>(
|
70 + | &mut self,
|
71 + | schema: &dyn Schema,
|
72 + | state: T,
|
73 + | consumer: F,
|
74 + | ) -> Result<T, Self::Error>
|
75 + | where
|
76 + | F: FnMut(T, &dyn Schema, &mut Self) -> Result<T, Self::Error>;
|
77 + |
|
78 + | /// Reads a list from the deserializer.
|
79 + | ///
|
80 + | /// The list deserialization is driven by a consumer callback that is called
|
81 + | /// for each element. The consumer receives the current state and the deserializer,
|
82 + | /// and returns the updated state.
|
83 + | ///
|
84 + | /// # Arguments
|
85 + | ///
|
86 + | /// * `schema` - The schema of the list being deserialized
|
87 + | /// * `state` - Initial state (typically a Vec or collection)
|
88 + | /// * `consumer` - Callback invoked for each element with (state, deserializer)
|
89 + | ///
|
90 + | /// # Returns
|
91 + | ///
|
92 + | /// The final state after processing all elements
|
93 + | fn read_list<T, F>(
|
94 + | &mut self,
|
95 + | schema: &dyn Schema,
|
96 + | state: T,
|
97 + | consumer: F,
|
98 + | ) -> Result<T, Self::Error>
|
99 + | where
|
100 + | F: FnMut(T, &mut Self) -> Result<T, Self::Error>;
|
101 + |
|
102 + | /// Reads a map from the deserializer.
|
103 + | ///
|
104 + | /// The map deserialization is driven by a consumer callback that is called
|
105 + | /// for each entry. The consumer receives the current state, the key, and the
|
106 + | /// deserializer, and returns the updated state.
|
107 + | ///
|
108 + | /// # Arguments
|
109 + | ///
|
110 + | /// * `schema` - The schema of the map being deserialized
|
111 + | /// * `state` - Initial state (typically a HashMap or collection)
|
112 + | /// * `consumer` - Callback invoked for each entry with (state, key, deserializer)
|
113 + | ///
|
114 + | /// # Returns
|
115 + | ///
|
116 + | /// The final state after processing all entries
|
117 + | fn read_map<T, F>(
|
118 + | &mut self,
|
119 + | schema: &dyn Schema,
|
120 + | state: T,
|
121 + | consumer: F,
|
122 + | ) -> Result<T, Self::Error>
|
123 + | where
|
124 + | F: FnMut(T, String, &mut Self) -> Result<T, Self::Error>;
|
125 + |
|
126 + | /// Reads a boolean value.
|
127 + | fn read_boolean(&mut self, schema: &dyn Schema) -> Result<bool, Self::Error>;
|
128 + |
|
129 + | /// Reads a byte (i8) value.
|
130 + | fn read_byte(&mut self, schema: &dyn Schema) -> Result<i8, Self::Error>;
|
131 + |
|
132 + | /// Reads a short (i16) value.
|
133 + | fn read_short(&mut self, schema: &dyn Schema) -> Result<i16, Self::Error>;
|
134 + |
|
135 + | /// Reads an integer (i32) value.
|
136 + | fn read_integer(&mut self, schema: &dyn Schema) -> Result<i32, Self::Error>;
|
137 + |
|
138 + | /// Reads a long (i64) value.
|
139 + | fn read_long(&mut self, schema: &dyn Schema) -> Result<i64, Self::Error>;
|
140 + |
|
141 + | /// Reads a float (f32) value.
|
142 + | fn read_float(&mut self, schema: &dyn Schema) -> Result<f32, Self::Error>;
|
143 + |
|
144 + | /// Reads a double (f64) value.
|
145 + | fn read_double(&mut self, schema: &dyn Schema) -> Result<f64, Self::Error>;
|
146 + |
|
147 + | /// Reads a big integer value.
|
148 + | fn read_big_integer(&mut self, schema: &dyn Schema) -> Result<BigInteger, Self::Error>;
|
149 + |
|
150 + | /// Reads a big decimal value.
|
151 + | fn read_big_decimal(&mut self, schema: &dyn Schema) -> Result<BigDecimal, Self::Error>;
|
152 + |
|
153 + | /// Reads a string value.
|
154 + | fn read_string(&mut self, schema: &dyn Schema) -> Result<String, Self::Error>;
|
155 + |
|
156 + | /// Reads a blob (byte array) value.
|
157 + | fn read_blob(&mut self, schema: &dyn Schema) -> Result<Blob, Self::Error>;
|
158 + |
|
159 + | /// Reads a timestamp value.
|
160 + | fn read_timestamp(&mut self, schema: &dyn Schema) -> Result<DateTime, Self::Error>;
|
161 + |
|
162 + | /// Reads a document value.
|
163 + | fn read_document(&mut self, schema: &dyn Schema) -> Result<Document, Self::Error>;
|
164 + |
|
165 + | /// Checks if the current value is null.
|
166 + | ///
|
167 + | /// This is used for sparse collections where null values are significant.
|
168 + | fn is_null(&self) -> bool;
|
169 + |
|
170 + | /// Returns the size of the current container if known.
|
171 + | ///
|
172 + | /// This is an optimization hint that allows pre-allocating collections
|
173 + | /// with the correct capacity. Returns `None` if the size is unknown or
|
174 + | /// not applicable.
|
175 + | fn container_size(&self) -> Option<usize>;
|
176 + | }
|