1 + | /*
|
2 + | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 + | * SPDX-License-Identifier: Apache-2.0
|
4 + | */
|
5 + |
|
6 + | //! Serialization and deserialization interfaces for the Smithy data model.
|
7 + |
|
8 + | mod deserializer;
|
9 + | mod serializer;
|
10 + |
|
11 + | pub use deserializer::ShapeDeserializer;
|
12 + | pub use serializer::{SerializableStruct, ShapeSerializer};
|
13 + |
|
14 + | #[cfg(test)]
|
15 + | mod test {
|
16 + | use crate::schema::serde::{ShapeDeserializer, ShapeSerializer};
|
17 + | use crate::schema::{prelude::*, Schema};
|
18 + | use std::fmt;
|
19 + |
|
20 + | // Mock error type for testing
|
21 + | #[derive(Debug)]
|
22 + | struct MockError(String);
|
23 + |
|
24 + | impl fmt::Display for MockError {
|
25 + | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
26 + | write!(f, "{}", self.0)
|
27 + | }
|
28 + | }
|
29 + |
|
30 + | impl std::error::Error for MockError {}
|
31 + |
|
32 + | // Mock serializer for testing
|
33 + | struct MockSerializer {
|
34 + | output: Vec<String>,
|
35 + | }
|
36 + |
|
37 + | impl ShapeSerializer for MockSerializer {
|
38 + | type Output = Vec<String>;
|
39 + | type Error = MockError;
|
40 + |
|
41 + | fn finish(self) -> Result<Self::Output, Self::Error> {
|
42 + | Ok(self.output)
|
43 + | }
|
44 + |
|
45 + | fn write_struct<F>(
|
46 + | &mut self,
|
47 + | schema: &dyn Schema,
|
48 + | write_members: F,
|
49 + | ) -> Result<(), Self::Error>
|
50 + | where
|
51 + | F: FnOnce(&mut Self) -> Result<(), Self::Error>,
|
52 + | {
|
53 + | self.output
|
54 + | .push(format!("struct({})", schema.shape_id().as_str()));
|
55 + | write_members(self)?;
|
56 + | self.output.push("end_struct".to_string());
|
57 + | Ok(())
|
58 + | }
|
59 + |
|
60 + | fn write_list<F>(
|
61 + | &mut self,
|
62 + | schema: &dyn Schema,
|
63 + | write_elements: F,
|
64 + | ) -> Result<(), Self::Error>
|
65 + | where
|
66 + | F: FnOnce(&mut Self) -> Result<(), Self::Error>,
|
67 + | {
|
68 + | self.output
|
69 + | .push(format!("list({})", schema.shape_id().as_str()));
|
70 + | write_elements(self)?;
|
71 + | self.output.push("end_list".to_string());
|
72 + | Ok(())
|
73 + | }
|
74 + |
|
75 + | fn write_map<F>(&mut self, schema: &dyn Schema, write_entries: F) -> Result<(), Self::Error>
|
76 + | where
|
77 + | F: FnOnce(&mut Self) -> Result<(), Self::Error>,
|
78 + | {
|
79 + | self.output
|
80 + | .push(format!("map({})", schema.shape_id().as_str()));
|
81 + | write_entries(self)?;
|
82 + | self.output.push("end_map".to_string());
|
83 + | Ok(())
|
84 + | }
|
85 + |
|
86 + | fn write_boolean(&mut self, _schema: &dyn Schema, value: bool) -> Result<(), Self::Error> {
|
87 + | self.output.push(format!("bool({})", value));
|
88 + | Ok(())
|
89 + | }
|
90 + |
|
91 + | fn write_byte(&mut self, _schema: &dyn Schema, value: i8) -> Result<(), Self::Error> {
|
92 + | self.output.push(format!("byte({})", value));
|
93 + | Ok(())
|
94 + | }
|
95 + |
|
96 + | fn write_short(&mut self, _schema: &dyn Schema, value: i16) -> Result<(), Self::Error> {
|
97 + | self.output.push(format!("short({})", value));
|
98 + | Ok(())
|
99 + | }
|
100 + |
|
101 + | fn write_integer(&mut self, _schema: &dyn Schema, value: i32) -> Result<(), Self::Error> {
|
102 + | self.output.push(format!("int({})", value));
|
103 + | Ok(())
|
104 + | }
|
105 + |
|
106 + | fn write_long(&mut self, _schema: &dyn Schema, value: i64) -> Result<(), Self::Error> {
|
107 + | self.output.push(format!("long({})", value));
|
108 + | Ok(())
|
109 + | }
|
110 + |
|
111 + | fn write_float(&mut self, _schema: &dyn Schema, value: f32) -> Result<(), Self::Error> {
|
112 + | self.output.push(format!("float({})", value));
|
113 + | Ok(())
|
114 + | }
|
115 + |
|
116 + | fn write_double(&mut self, _schema: &dyn Schema, value: f64) -> Result<(), Self::Error> {
|
117 + | self.output.push(format!("double({})", value));
|
118 + | Ok(())
|
119 + | }
|
120 + |
|
121 + | fn write_big_integer(
|
122 + | &mut self,
|
123 + | _schema: &dyn Schema,
|
124 + | value: &crate::BigInteger,
|
125 + | ) -> Result<(), Self::Error> {
|
126 + | self.output.push(format!("bigint({})", value.as_ref()));
|
127 + | Ok(())
|
128 + | }
|
129 + |
|
130 + | fn write_big_decimal(
|
131 + | &mut self,
|
132 + | _schema: &dyn Schema,
|
133 + | value: &crate::BigDecimal,
|
134 + | ) -> Result<(), Self::Error> {
|
135 + | self.output.push(format!("bigdec({})", value.as_ref()));
|
136 + | Ok(())
|
137 + | }
|
138 + |
|
139 + | fn write_string(&mut self, _schema: &dyn Schema, value: &str) -> Result<(), Self::Error> {
|
140 + | self.output.push(format!("string({})", value));
|
141 + | Ok(())
|
142 + | }
|
143 + |
|
144 + | fn write_blob(
|
145 + | &mut self,
|
146 + | _schema: &dyn Schema,
|
147 + | value: &crate::Blob,
|
148 + | ) -> Result<(), Self::Error> {
|
149 + | self.output
|
150 + | .push(format!("blob({} bytes)", value.as_ref().len()));
|
151 + | Ok(())
|
152 + | }
|
153 + |
|
154 + | fn write_timestamp(
|
155 + | &mut self,
|
156 + | _schema: &dyn Schema,
|
157 + | value: &crate::DateTime,
|
158 + | ) -> Result<(), Self::Error> {
|
159 + | self.output.push(format!("timestamp({})", value));
|
160 + | Ok(())
|
161 + | }
|
162 + |
|
163 + | fn write_document(
|
164 + | &mut self,
|
165 + | _schema: &dyn Schema,
|
166 + | _value: &crate::Document,
|
167 + | ) -> Result<(), Self::Error> {
|
168 + | self.output.push("document".to_string());
|
169 + | Ok(())
|
170 + | }
|
171 + |
|
172 + | fn write_null(&mut self, _schema: &dyn Schema) -> Result<(), Self::Error> {
|
173 + | self.output.push("null".to_string());
|
174 + | Ok(())
|
175 + | }
|
176 + | }
|
177 + |
|
178 + | // Mock deserializer for testing
|
179 + | struct MockDeserializer {
|
180 + | values: Vec<String>,
|
181 + | index: usize,
|
182 + | }
|
183 + |
|
184 + | impl MockDeserializer {
|
185 + | fn new(values: Vec<String>) -> Self {
|
186 + | Self { values, index: 0 }
|
187 + | }
|
188 + | }
|
189 + |
|
190 + | impl ShapeDeserializer for MockDeserializer {
|
191 + | type Error = MockError;
|
192 + |
|
193 + | fn read_struct<T, F>(
|
194 + | &mut self,
|
195 + | _schema: &dyn Schema,
|
196 + | state: T,
|
197 + | mut consumer: F,
|
198 + | ) -> Result<T, Self::Error>
|
199 + | where
|
200 + | F: FnMut(T, &dyn Schema, &mut Self) -> Result<T, Self::Error>,
|
201 + | {
|
202 + | // Simulate reading 2 members
|
203 + | let state = consumer(state, &STRING, self)?;
|
204 + | let state = consumer(state, &INTEGER, self)?;
|
205 + | Ok(state)
|
206 + | }
|
207 + |
|
208 + | fn read_list<T, F>(
|
209 + | &mut self,
|
210 + | _schema: &dyn Schema,
|
211 + | mut state: T,
|
212 + | mut consumer: F,
|
213 + | ) -> Result<T, Self::Error>
|
214 + | where
|
215 + | F: FnMut(T, &mut Self) -> Result<T, Self::Error>,
|
216 + | {
|
217 + | // Simulate reading 3 elements
|
218 + | for _ in 0..3 {
|
219 + | state = consumer(state, self)?;
|
220 + | }
|
221 + | Ok(state)
|
222 + | }
|
223 + |
|
224 + | fn read_map<T, F>(
|
225 + | &mut self,
|
226 + | _schema: &dyn Schema,
|
227 + | mut state: T,
|
228 + | mut consumer: F,
|
229 + | ) -> Result<T, Self::Error>
|
230 + | where
|
231 + | F: FnMut(T, String, &mut Self) -> Result<T, Self::Error>,
|
232 + | {
|
233 + | // Simulate reading 2 entries
|
234 + | state = consumer(state, "key1".to_string(), self)?;
|
235 + | state = consumer(state, "key2".to_string(), self)?;
|
236 + | Ok(state)
|
237 + | }
|
238 + |
|
239 + | fn read_boolean(&mut self, _schema: &dyn Schema) -> Result<bool, Self::Error> {
|
240 + | Ok(true)
|
241 + | }
|
242 + |
|
243 + | fn read_byte(&mut self, _schema: &dyn Schema) -> Result<i8, Self::Error> {
|
244 + | Ok(42)
|
245 + | }
|
246 + |
|
247 + | fn read_short(&mut self, _schema: &dyn Schema) -> Result<i16, Self::Error> {
|
248 + | Ok(1000)
|
249 + | }
|
250 + |
|
251 + | fn read_integer(&mut self, _schema: &dyn Schema) -> Result<i32, Self::Error> {
|
252 + | Ok(123456)
|
253 + | }
|
254 + |
|
255 + | fn read_long(&mut self, _schema: &dyn Schema) -> Result<i64, Self::Error> {
|
256 + | Ok(9876543210)
|
257 + | }
|
258 + |
|
259 + | fn read_float(&mut self, _schema: &dyn Schema) -> Result<f32, Self::Error> {
|
260 + | Ok(3.14)
|
261 + | }
|
262 + |
|
263 + | fn read_double(&mut self, _schema: &dyn Schema) -> Result<f64, Self::Error> {
|
264 + | Ok(2.71828)
|
265 + | }
|
266 + |
|
267 + | fn read_big_integer(
|
268 + | &mut self,
|
269 + | _schema: &dyn Schema,
|
270 + | ) -> Result<crate::BigInteger, Self::Error> {
|
271 + | use std::str::FromStr;
|
272 + | Ok(crate::BigInteger::from_str("12345").unwrap())
|
273 + | }
|
274 + |
|
275 + | fn read_big_decimal(
|
276 + | &mut self,
|
277 + | _schema: &dyn Schema,
|
278 + | ) -> Result<crate::BigDecimal, Self::Error> {
|
279 + | use std::str::FromStr;
|
280 + | Ok(crate::BigDecimal::from_str("123.45").unwrap())
|
281 + | }
|
282 + |
|
283 + | fn read_string(&mut self, _schema: &dyn Schema) -> Result<String, Self::Error> {
|
284 + | if self.index < self.values.len() {
|
285 + | let value = self.values[self.index].clone();
|
286 + | self.index += 1;
|
287 + | Ok(value)
|
288 + | } else {
|
289 + | Ok("default".to_string())
|
290 + | }
|
291 + | }
|
292 + |
|
293 + | fn read_blob(&mut self, _schema: &dyn Schema) -> Result<crate::Blob, Self::Error> {
|
294 + | Ok(crate::Blob::new(vec![1, 2, 3, 4]))
|
295 + | }
|
296 + |
|
297 + | fn read_timestamp(&mut self, _schema: &dyn Schema) -> Result<crate::DateTime, Self::Error> {
|
298 + | Ok(crate::DateTime::from_secs(1234567890))
|
299 + | }
|
300 + |
|
301 + | fn read_document(&mut self, _schema: &dyn Schema) -> Result<crate::Document, Self::Error> {
|
302 + | Ok(crate::Document::Null)
|
303 + | }
|
304 + |
|
305 + | fn is_null(&mut self) -> bool {
|
306 + | false
|
307 + | }
|
308 + |
|
309 + | fn container_size(&mut self) -> Option<usize> {
|
310 + | Some(10)
|
311 + | }
|
312 + | }
|
313 + |
|
314 + | #[test]
|
315 + | fn test_serializer_simple_types() {
|
316 + | let mut ser = MockSerializer { output: Vec::new() };
|
317 + |
|
318 + | ser.write_boolean(&BOOLEAN, true).unwrap();
|
319 + | ser.write_integer(&INTEGER, 42).unwrap();
|
320 + | ser.write_string(&STRING, "hello").unwrap();
|
321 + |
|
322 + | let output = ser.finish().unwrap();
|
323 + | assert_eq!(output, vec!["bool(true)", "int(42)", "string(hello)"]);
|
324 + | }
|
325 + |
|
326 + | #[test]
|
327 + | fn test_serializer_struct() {
|
328 + | let mut ser = MockSerializer { output: Vec::new() };
|
329 + |
|
330 + | ser.write_struct(&STRING, |s| {
|
331 + | s.write_string(&STRING, "field1")?;
|
332 + | s.write_integer(&INTEGER, 123)?;
|
333 + | Ok(())
|
334 + | })
|
335 + | .unwrap();
|
336 + |
|
337 + | let output = ser.finish().unwrap();
|
338 + | assert_eq!(
|
339 + | output,
|
340 + | vec![
|
341 + | "struct(smithy.api#String)",
|
342 + | "string(field1)",
|
343 + | "int(123)",
|
344 + | "end_struct"
|
345 + | ]
|
346 + | );
|
347 + | }
|
348 + |
|
349 + | #[test]
|
350 + | fn test_deserializer_simple_types() {
|
351 + | let mut deser = MockDeserializer::new(vec!["test".to_string()]);
|
352 + |
|
353 + | assert_eq!(deser.read_boolean(&BOOLEAN).unwrap(), true);
|
354 + | assert_eq!(deser.read_integer(&INTEGER).unwrap(), 123456);
|
355 + | assert_eq!(deser.read_string(&STRING).unwrap(), "test");
|
356 + | assert_eq!(deser.container_size(), Some(10));
|
357 + | assert!(!deser.is_null());
|
358 + | }
|
359 + |
|
360 + | #[test]
|
361 + | fn test_deserializer_struct() {
|
362 + | let mut deser = MockDeserializer::new(vec!["value1".to_string(), "value2".to_string()]);
|
363 + |
|
364 + | let mut fields = Vec::new();
|
365 + | deser
|
366 + | .read_struct(&STRING, &mut fields, |fields, _member, d| {
|
367 + | fields.push(d.read_string(&STRING)?);
|
368 + | Ok(fields)
|
369 + | })
|
370 + | .unwrap();
|
371 + |
|
372 + | assert_eq!(fields, vec!["value1", "value2"]);
|
373 + | }
|
374 + |
|
375 + | #[test]
|
376 + | fn test_deserializer_list() {
|
377 + | let mut deser =
|
378 + | MockDeserializer::new(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
|
379 + |
|
380 + | let mut elements = Vec::new();
|
381 + | deser
|
382 + | .read_list(&STRING, &mut elements, |elements, d| {
|
383 + | elements.push(d.read_string(&STRING)?);
|
384 + | Ok(elements)
|
385 + | })
|
386 + | .unwrap();
|
387 + |
|
388 + | assert_eq!(elements, vec!["a", "b", "c"]);
|
389 + | }
|
390 + |
|
391 + | #[test]
|
392 + | fn test_deserializer_map() {
|
393 + | let mut deser = MockDeserializer::new(vec!["val1".to_string(), "val2".to_string()]);
|
394 + |
|
395 + | let mut entries = Vec::new();
|
396 + | deser
|
397 + | .read_map(&STRING, &mut entries, |entries, key, d| {
|
398 + | let value = d.read_string(&STRING)?;
|
399 + | entries.push((key, value));
|
400 + | Ok(entries)
|
401 + | })
|
402 + | .unwrap();
|
403 + |
|
404 + | assert_eq!(
|
405 + | entries,
|
406 + | vec![
|
407 + | ("key1".to_string(), "val1".to_string()),
|
408 + | ("key2".to_string(), "val2".to_string())
|
409 + | ]
|
410 + | );
|
411 + | }
|
412 + | }
|