aws_smithy_schema/schema/serde/deserializer.rs
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
8use crate::Schema;
9use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
10use 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/// ```
50pub 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}