1use aws_smithy_schema::codec::FinishSerializer;
9use aws_smithy_schema::serde::{SerdeError, SerializableStruct, ShapeSerializer};
10use aws_smithy_schema::Schema;
11use aws_smithy_types::{BigDecimal, BigInteger, Blob, DateTime, Document};
12
13pub struct CborSerializer {
18 encoder: crate::Encoder,
19}
20
21impl CborSerializer {
22 pub(crate) fn new() -> Self {
23 Self {
24 encoder: crate::Encoder::new(Vec::new()),
25 }
26 }
27
28 #[inline]
30 fn write_member_key(&mut self, schema: &Schema) {
31 if let Some(name) = schema.member_name() {
32 self.encoder.str(name);
33 }
34 }
35}
36
37impl FinishSerializer for CborSerializer {
38 fn finish(self) -> Vec<u8> {
39 self.encoder.into_writer()
40 }
41}
42
43impl ShapeSerializer for CborSerializer {
44 fn write_struct(
45 &mut self,
46 schema: &Schema,
47 value: &dyn SerializableStruct,
48 ) -> Result<(), SerdeError> {
49 self.write_member_key(schema);
50 self.encoder.begin_map();
51 value.serialize_members(self)?;
52 self.encoder.end();
53 Ok(())
54 }
55
56 fn write_list(
57 &mut self,
58 schema: &Schema,
59 write_elements: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
60 ) -> Result<(), SerdeError> {
61 self.write_member_key(schema);
62 self.encoder.begin_array();
63 write_elements(self)?;
64 self.encoder.end();
65 Ok(())
66 }
67
68 fn write_map(
69 &mut self,
70 schema: &Schema,
71 write_entries: &dyn Fn(&mut dyn ShapeSerializer) -> Result<(), SerdeError>,
72 ) -> Result<(), SerdeError> {
73 self.write_member_key(schema);
74 self.encoder.begin_map();
75 write_entries(self)?;
76 self.encoder.end();
77 Ok(())
78 }
79
80 fn write_boolean(&mut self, schema: &Schema, value: bool) -> Result<(), SerdeError> {
81 self.write_member_key(schema);
82 self.encoder.boolean(value);
83 Ok(())
84 }
85
86 fn write_byte(&mut self, schema: &Schema, value: i8) -> Result<(), SerdeError> {
87 self.write_member_key(schema);
88 self.encoder.byte(value);
89 Ok(())
90 }
91
92 fn write_short(&mut self, schema: &Schema, value: i16) -> Result<(), SerdeError> {
93 self.write_member_key(schema);
94 self.encoder.short(value);
95 Ok(())
96 }
97
98 fn write_integer(&mut self, schema: &Schema, value: i32) -> Result<(), SerdeError> {
99 self.write_member_key(schema);
100 self.encoder.integer(value);
101 Ok(())
102 }
103
104 fn write_long(&mut self, schema: &Schema, value: i64) -> Result<(), SerdeError> {
105 self.write_member_key(schema);
106 self.encoder.long(value);
107 Ok(())
108 }
109
110 fn write_float(&mut self, schema: &Schema, value: f32) -> Result<(), SerdeError> {
111 self.write_member_key(schema);
112 self.encoder.float(value);
113 Ok(())
114 }
115
116 fn write_double(&mut self, schema: &Schema, value: f64) -> Result<(), SerdeError> {
117 self.write_member_key(schema);
118 self.encoder.double(value);
119 Ok(())
120 }
121
122 fn write_big_integer(
123 &mut self,
124 _schema: &Schema,
125 _value: &BigInteger,
126 ) -> Result<(), SerdeError> {
127 Err(SerdeError::UnsupportedOperation {
128 message: "CBOR big integer not yet supported (smithy-rs#4611)".into(),
129 })
130 }
131
132 fn write_big_decimal(
133 &mut self,
134 _schema: &Schema,
135 _value: &BigDecimal,
136 ) -> Result<(), SerdeError> {
137 Err(SerdeError::UnsupportedOperation {
138 message: "CBOR big decimal not yet supported (smithy-rs#4611)".into(),
139 })
140 }
141
142 fn write_string(&mut self, schema: &Schema, value: &str) -> Result<(), SerdeError> {
143 self.write_member_key(schema);
144 self.encoder.str(value);
145 Ok(())
146 }
147
148 fn write_blob(&mut self, schema: &Schema, value: &Blob) -> Result<(), SerdeError> {
149 self.write_member_key(schema);
150 self.encoder.blob(value);
151 Ok(())
152 }
153
154 fn write_timestamp(&mut self, schema: &Schema, value: &DateTime) -> Result<(), SerdeError> {
155 self.write_member_key(schema);
156 self.encoder.timestamp(value);
157 Ok(())
158 }
159
160 fn write_document(&mut self, _schema: &Schema, _value: &Document) -> Result<(), SerdeError> {
161 Err(SerdeError::UnsupportedOperation {
162 message: "document types are not supported by rpcv2Cbor protocol".into(),
163 })
164 }
165
166 fn write_null(&mut self, schema: &Schema) -> Result<(), SerdeError> {
167 self.write_member_key(schema);
168 self.encoder.null();
169 Ok(())
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176 use aws_smithy_schema::codec::{Codec, FinishSerializer};
177 use aws_smithy_schema::prelude::*;
178 use aws_smithy_schema::serde::ShapeSerializer;
179 use aws_smithy_schema::{shape_id, ShapeType};
180
181 use crate::codec::CborCodec;
182
183 fn round_trip(f: impl FnOnce(&mut CborSerializer)) -> Vec<u8> {
184 let codec = CborCodec::default();
185 let mut ser = codec.create_serializer();
186 f(&mut ser);
187 ser.finish()
188 }
189
190 #[test]
191 fn test_write_boolean() {
192 let bytes = round_trip(|s| s.write_boolean(&BOOLEAN, true).unwrap());
193 let mut dec = crate::Decoder::new(&bytes);
194 assert_eq!(dec.boolean().unwrap(), true);
195 }
196
197 #[test]
198 fn test_write_integer() {
199 let bytes = round_trip(|s| s.write_integer(&INTEGER, 42).unwrap());
200 let mut dec = crate::Decoder::new(&bytes);
201 assert_eq!(dec.integer().unwrap(), 42);
202 }
203
204 #[test]
205 fn test_write_long() {
206 let bytes = round_trip(|s| s.write_long(&LONG, i64::MAX).unwrap());
207 let mut dec = crate::Decoder::new(&bytes);
208 assert_eq!(dec.long().unwrap(), i64::MAX);
209 }
210
211 #[test]
212 fn test_write_float_nan() {
213 let bytes = round_trip(|s| s.write_float(&FLOAT, f32::NAN).unwrap());
214 let mut dec = crate::Decoder::new(&bytes);
215 assert!(dec.float().unwrap().is_nan());
216 }
217
218 #[test]
219 fn test_write_double_infinity() {
220 let bytes = round_trip(|s| s.write_double(&DOUBLE, f64::INFINITY).unwrap());
221 let mut dec = crate::Decoder::new(&bytes);
222 assert_eq!(dec.double().unwrap(), f64::INFINITY);
223 }
224
225 #[test]
226 fn test_write_string() {
227 let bytes = round_trip(|s| s.write_string(&STRING, "hello").unwrap());
228 let mut dec = crate::Decoder::new(&bytes);
229 assert_eq!(dec.str().unwrap().as_ref(), "hello");
230 }
231
232 #[test]
233 fn test_write_blob() {
234 let blob = Blob::new(b"binary data");
235 let bytes = round_trip(|s| s.write_blob(&BLOB, &blob).unwrap());
236 let mut dec = crate::Decoder::new(&bytes);
237 assert_eq!(dec.blob().unwrap(), blob);
238 }
239
240 #[test]
241 fn test_write_timestamp() {
242 let ts = DateTime::from_secs_f64(1700000000.5);
243 let bytes = round_trip(|s| s.write_timestamp(&TIMESTAMP, &ts).unwrap());
244 let mut dec = crate::Decoder::new(&bytes);
245 let decoded = dec.timestamp().unwrap();
246 assert_eq!(decoded.as_secs_f64(), 1700000000.5);
248 }
249
250 #[test]
251 fn test_write_null() {
252 let bytes = round_trip(|s| s.write_null(&STRING).unwrap());
253 let mut dec = crate::Decoder::new(&bytes);
254 dec.null().unwrap();
255 }
256
257 #[test]
258 fn test_write_list() {
259 let list_schema = Schema::new(shape_id!("test", "List"), ShapeType::List);
260 let bytes = round_trip(|s| {
261 s.write_list(&list_schema, &|s| {
262 s.write_integer(&INTEGER, 1)?;
263 s.write_integer(&INTEGER, 2)?;
264 s.write_integer(&INTEGER, 3)?;
265 Ok(())
266 })
267 .unwrap()
268 });
269 let mut dec = crate::Decoder::new(&bytes);
270 let len = dec.list().unwrap();
272 assert!(len.is_none()); assert_eq!(dec.integer().unwrap(), 1);
274 assert_eq!(dec.integer().unwrap(), 2);
275 assert_eq!(dec.integer().unwrap(), 3);
276 }
277
278 #[test]
279 fn test_write_struct() {
280 static NAME_MEMBER: Schema =
281 Schema::new_member(shape_id!("test", "Struct"), ShapeType::String, "name", 0);
282 static AGE_MEMBER: Schema =
283 Schema::new_member(shape_id!("test", "Struct"), ShapeType::Integer, "age", 1);
284 static STRUCT_SCHEMA: Schema = Schema::new_struct(
285 shape_id!("test", "Struct"),
286 ShapeType::Structure,
287 &[&NAME_MEMBER, &AGE_MEMBER],
288 );
289
290 struct TestStruct;
291 impl SerializableStruct for TestStruct {
292 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
293 s.write_string(&NAME_MEMBER, "Alice")?;
294 s.write_integer(&AGE_MEMBER, 30)?;
295 Ok(())
296 }
297 }
298
299 let bytes = round_trip(|s| s.write_struct(&STRUCT_SCHEMA, &TestStruct).unwrap());
300 let mut dec = crate::Decoder::new(&bytes);
301 let len = dec.map().unwrap();
302 assert!(len.is_none()); assert_eq!(dec.str().unwrap().as_ref(), "name");
304 assert_eq!(dec.str().unwrap().as_ref(), "Alice");
305 assert_eq!(dec.str().unwrap().as_ref(), "age");
306 assert_eq!(dec.integer().unwrap(), 30);
307 }
308
309 #[test]
310 fn test_write_map() {
311 let map_schema = Schema::new(shape_id!("test", "Map"), ShapeType::Map);
312 let bytes = round_trip(|s| {
313 s.write_map(&map_schema, &|s| {
314 s.write_string(&STRING, "key1")?;
315 s.write_string(&STRING, "val1")?;
316 Ok(())
317 })
318 .unwrap()
319 });
320 let mut dec = crate::Decoder::new(&bytes);
321 let len = dec.map().unwrap();
322 assert!(len.is_none());
323 assert_eq!(dec.str().unwrap().as_ref(), "key1");
324 assert_eq!(dec.str().unwrap().as_ref(), "val1");
325 }
326}