aws_smithy_schema/schema/
codec.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Codec trait for creating shape serializers and deserializers.
7//!
8//! A codec represents a specific serialization format (e.g., JSON, XML, CBOR)
9//! and provides methods to create serializers and deserializers for that format.
10
11pub mod http_string;
12
13use crate::serde::{ShapeDeserializer, ShapeSerializer};
14
15/// Trait for serializers that can produce a final byte output.
16///
17/// This is separate from [`ShapeSerializer`] to preserve object safety on
18/// `ShapeSerializer` (which is used as `&mut dyn ShapeSerializer` in generated code).
19pub trait FinishSerializer {
20    /// Consumes the serializer and returns the serialized bytes.
21    fn finish(self) -> Vec<u8>;
22}
23
24/// A codec for a specific serialization format.
25///
26/// Codecs are responsible for creating [`ShapeSerializer`] and [`ShapeDeserializer`]
27/// instances that can serialize and deserialize shapes to and from a specific format.
28///
29/// # Examples
30///
31/// Implementing a custom codec:
32///
33/// ```ignore
34/// use aws_smithy_schema::codec::Codec;
35/// use aws_smithy_schema::serde::{ShapeSerializer, ShapeDeserializer};
36///
37/// struct MyCodec {
38///     // codec configuration
39/// }
40///
41/// impl Codec for MyCodec {
42///     type Serializer = MySerializer;
43///     type Deserializer = MyDeserializer;
44///
45///     fn create_serializer(&self) -> Self::Serializer {
46///         MySerializer::new()
47///     }
48///
49///     fn create_deserializer(&self, input: &[u8]) -> Self::Deserializer {
50///         MyDeserializer::new(input)
51///     }
52/// }
53/// ```
54pub trait Codec {
55    /// The serializer type for this codec.
56    type Serializer: ShapeSerializer + FinishSerializer;
57
58    /// The deserializer type for this codec.
59    type Deserializer<'a>: ShapeDeserializer;
60
61    /// Creates a new serializer for this codec.
62    fn create_serializer(&self) -> Self::Serializer;
63
64    /// Creates a new deserializer for this codec from the given input bytes.
65    fn create_deserializer<'a>(&self, input: &'a [u8]) -> Self::Deserializer<'a>;
66}
67
68#[cfg(test)]
69mod test {
70    use super::*;
71    use crate::serde::{SerdeError, SerializableStruct, ShapeDeserializer, ShapeSerializer};
72    use crate::{prelude::*, Schema};
73
74    // Mock serializer
75    struct MockSerializer {
76        output: Vec<u8>,
77    }
78
79    impl MockSerializer {
80        fn finish(self) -> Vec<u8> {
81            self.output
82        }
83    }
84
85    impl FinishSerializer for MockSerializer {
86        fn finish(self) -> Vec<u8> {
87            self.output
88        }
89    }
90
91    impl ShapeSerializer for MockSerializer {
92        fn write_struct(
93            &mut self,
94            _schema: &Schema,
95            _value: &dyn SerializableStruct,
96        ) -> Result<(), SerdeError> {
97            Ok(())
98        }
99
100        fn write_list(
101            &mut self,
102            _schema: &Schema,
103            _write_elements: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
104        ) -> Result<(), SerdeError> {
105            Ok(())
106        }
107
108        fn write_map(
109            &mut self,
110            _schema: &Schema,
111            _write_entries: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
112        ) -> Result<(), SerdeError> {
113            Ok(())
114        }
115
116        fn write_boolean(&mut self, _schema: &Schema, _value: bool) -> Result<(), SerdeError> {
117            Ok(())
118        }
119
120        fn write_byte(&mut self, _schema: &Schema, _value: i8) -> Result<(), SerdeError> {
121            Ok(())
122        }
123
124        fn write_short(&mut self, _schema: &Schema, _value: i16) -> Result<(), SerdeError> {
125            Ok(())
126        }
127
128        fn write_integer(&mut self, _schema: &Schema, _value: i32) -> Result<(), SerdeError> {
129            Ok(())
130        }
131
132        fn write_long(&mut self, _schema: &Schema, _value: i64) -> Result<(), SerdeError> {
133            Ok(())
134        }
135
136        fn write_float(&mut self, _schema: &Schema, _value: f32) -> Result<(), SerdeError> {
137            Ok(())
138        }
139
140        fn write_double(&mut self, _schema: &Schema, _value: f64) -> Result<(), SerdeError> {
141            Ok(())
142        }
143
144        fn write_big_integer(
145            &mut self,
146            _schema: &Schema,
147            _value: &aws_smithy_types::BigInteger,
148        ) -> Result<(), SerdeError> {
149            Ok(())
150        }
151
152        fn write_big_decimal(
153            &mut self,
154            _schema: &Schema,
155            _value: &aws_smithy_types::BigDecimal,
156        ) -> Result<(), SerdeError> {
157            Ok(())
158        }
159
160        fn write_string(&mut self, _schema: &Schema, _value: &str) -> Result<(), SerdeError> {
161            Ok(())
162        }
163
164        fn write_blob(
165            &mut self,
166            _schema: &Schema,
167            _value: &aws_smithy_types::Blob,
168        ) -> Result<(), SerdeError> {
169            Ok(())
170        }
171
172        fn write_timestamp(
173            &mut self,
174            _schema: &Schema,
175            _value: &aws_smithy_types::DateTime,
176        ) -> Result<(), SerdeError> {
177            Ok(())
178        }
179
180        fn write_document(
181            &mut self,
182            _schema: &Schema,
183            _value: &aws_smithy_types::Document,
184        ) -> Result<(), SerdeError> {
185            Ok(())
186        }
187
188        fn write_null(&mut self, _schema: &Schema) -> Result<(), SerdeError> {
189            Ok(())
190        }
191    }
192
193    // Mock deserializer
194    struct MockDeserializer<'a> {
195        #[allow(dead_code)]
196        input: &'a [u8],
197    }
198
199    impl<'a> ShapeDeserializer for MockDeserializer<'a> {
200        fn read_struct(
201            &mut self,
202            _schema: &Schema,
203            _consumer: &mut dyn FnMut(
204                &Schema,
205                &mut dyn ShapeDeserializer,
206            ) -> Result<(), SerdeError>,
207        ) -> Result<(), SerdeError> {
208            Ok(())
209        }
210
211        fn read_list(
212            &mut self,
213            _schema: &Schema,
214            _consumer: &mut dyn FnMut(&mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
215        ) -> Result<(), SerdeError> {
216            Ok(())
217        }
218
219        fn read_map(
220            &mut self,
221            _schema: &Schema,
222            _consumer: &mut dyn FnMut(String, &mut dyn ShapeDeserializer) -> Result<(), SerdeError>,
223        ) -> Result<(), SerdeError> {
224            Ok(())
225        }
226
227        fn read_boolean(&mut self, _schema: &Schema) -> Result<bool, SerdeError> {
228            Ok(false)
229        }
230
231        fn read_byte(&mut self, _schema: &Schema) -> Result<i8, SerdeError> {
232            Ok(0)
233        }
234
235        fn read_short(&mut self, _schema: &Schema) -> Result<i16, SerdeError> {
236            Ok(0)
237        }
238
239        fn read_integer(&mut self, _schema: &Schema) -> Result<i32, SerdeError> {
240            Ok(0)
241        }
242
243        fn read_long(&mut self, _schema: &Schema) -> Result<i64, SerdeError> {
244            Ok(0)
245        }
246
247        fn read_float(&mut self, _schema: &Schema) -> Result<f32, SerdeError> {
248            Ok(0.0)
249        }
250
251        fn read_double(&mut self, _schema: &Schema) -> Result<f64, SerdeError> {
252            Ok(0.0)
253        }
254
255        fn read_big_integer(
256            &mut self,
257            _schema: &Schema,
258        ) -> Result<aws_smithy_types::BigInteger, SerdeError> {
259            use std::str::FromStr;
260            Ok(aws_smithy_types::BigInteger::from_str("0").unwrap())
261        }
262
263        fn read_big_decimal(
264            &mut self,
265            _schema: &Schema,
266        ) -> Result<aws_smithy_types::BigDecimal, SerdeError> {
267            use std::str::FromStr;
268            Ok(aws_smithy_types::BigDecimal::from_str("0").unwrap())
269        }
270
271        fn read_string(&mut self, _schema: &Schema) -> Result<String, SerdeError> {
272            Ok(String::new())
273        }
274
275        fn read_blob(&mut self, _schema: &Schema) -> Result<aws_smithy_types::Blob, SerdeError> {
276            Ok(aws_smithy_types::Blob::new(Vec::new()))
277        }
278
279        fn read_timestamp(
280            &mut self,
281            _schema: &Schema,
282        ) -> Result<aws_smithy_types::DateTime, SerdeError> {
283            Ok(aws_smithy_types::DateTime::from_secs(0))
284        }
285
286        fn read_document(
287            &mut self,
288            _schema: &Schema,
289        ) -> Result<aws_smithy_types::Document, SerdeError> {
290            Ok(aws_smithy_types::Document::Null)
291        }
292
293        fn is_null(&self) -> bool {
294            false
295        }
296
297        fn container_size(&self) -> Option<usize> {
298            None
299        }
300    }
301
302    // Mock codec
303    struct MockCodec;
304
305    impl Codec for MockCodec {
306        type Serializer = MockSerializer;
307        type Deserializer<'a> = MockDeserializer<'a>;
308
309        fn create_serializer(&self) -> Self::Serializer {
310            MockSerializer { output: Vec::new() }
311        }
312
313        fn create_deserializer<'a>(&self, input: &'a [u8]) -> Self::Deserializer<'a> {
314            MockDeserializer { input }
315        }
316    }
317
318    #[test]
319    fn test_codec_create_serializer() {
320        let codec = MockCodec;
321        let mut serializer = codec.create_serializer();
322
323        // Test that we can use the serializer
324        serializer.write_string(&STRING, "test").unwrap();
325        let output = serializer.finish();
326        assert_eq!(output, Vec::<u8>::new());
327    }
328
329    #[test]
330    fn test_codec_create_deserializer() {
331        let codec = MockCodec;
332        let input = b"test data";
333        let mut deserializer = codec.create_deserializer(input);
334
335        // Test that we can use the deserializer
336        let result = deserializer.read_string(&STRING).unwrap();
337        assert_eq!(result, "");
338    }
339
340    #[test]
341    fn test_codec_roundtrip() {
342        let codec = MockCodec;
343
344        // Serialize
345        let mut serializer = codec.create_serializer();
346        serializer.write_integer(&INTEGER, 42).unwrap();
347        let bytes = serializer.finish();
348
349        // Deserialize
350        let mut deserializer = codec.create_deserializer(&bytes);
351        let value = deserializer.read_integer(&INTEGER).unwrap();
352        assert_eq!(value, 0); // Mock deserializer always returns 0
353    }
354}