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, 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: &[u8]) -> Result<(), SerdeError> {
149 self.write_member_key(schema);
150 self.encoder.blob_bytes(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 use aws_smithy_types::Blob;
181
182 use crate::codec::CborCodec;
183
184 fn round_trip(f: impl FnOnce(&mut CborSerializer)) -> Vec<u8> {
185 let codec = CborCodec::default();
186 let mut ser = codec.create_serializer();
187 f(&mut ser);
188 ser.finish()
189 }
190
191 #[test]
192 fn test_write_boolean() {
193 let bytes = round_trip(|s| s.write_boolean(&BOOLEAN, true).unwrap());
194 let mut dec = crate::Decoder::new(&bytes);
195 assert_eq!(dec.boolean().unwrap(), true);
196 }
197
198 #[test]
199 fn test_write_integer() {
200 let bytes = round_trip(|s| s.write_integer(&INTEGER, 42).unwrap());
201 let mut dec = crate::Decoder::new(&bytes);
202 assert_eq!(dec.integer().unwrap(), 42);
203 }
204
205 #[test]
206 fn test_write_long() {
207 let bytes = round_trip(|s| s.write_long(&LONG, i64::MAX).unwrap());
208 let mut dec = crate::Decoder::new(&bytes);
209 assert_eq!(dec.long().unwrap(), i64::MAX);
210 }
211
212 #[test]
213 fn test_write_float_nan() {
214 let bytes = round_trip(|s| s.write_float(&FLOAT, f32::NAN).unwrap());
215 let mut dec = crate::Decoder::new(&bytes);
216 assert!(dec.float().unwrap().is_nan());
217 }
218
219 #[test]
220 fn test_write_double_infinity() {
221 let bytes = round_trip(|s| s.write_double(&DOUBLE, f64::INFINITY).unwrap());
222 let mut dec = crate::Decoder::new(&bytes);
223 assert_eq!(dec.double().unwrap(), f64::INFINITY);
224 }
225
226 #[test]
227 fn test_write_string() {
228 let bytes = round_trip(|s| s.write_string(&STRING, "hello").unwrap());
229 let mut dec = crate::Decoder::new(&bytes);
230 assert_eq!(dec.str().unwrap().as_ref(), "hello");
231 }
232
233 #[test]
234 fn test_write_blob() {
235 let blob = Blob::new(b"binary data");
236 let bytes = round_trip(|s| s.write_blob(&BLOB, blob.as_ref()).unwrap());
237 let mut dec = crate::Decoder::new(&bytes);
238 assert_eq!(dec.blob().unwrap(), blob);
239 }
240
241 #[test]
242 fn test_write_timestamp() {
243 let ts = DateTime::from_secs_f64(1700000000.5);
244 let bytes = round_trip(|s| s.write_timestamp(&TIMESTAMP, &ts).unwrap());
245 let mut dec = crate::Decoder::new(&bytes);
246 let decoded = dec.timestamp().unwrap();
247 assert_eq!(decoded.as_secs_f64(), 1700000000.5);
249 }
250
251 #[test]
252 fn test_write_null() {
253 let bytes = round_trip(|s| s.write_null(&STRING).unwrap());
254 let mut dec = crate::Decoder::new(&bytes);
255 dec.null().unwrap();
256 }
257
258 #[test]
259 fn test_write_list() {
260 let list_schema = Schema::new(shape_id!("test", "List"), ShapeType::List);
261 let bytes = round_trip(|s| {
262 s.write_list(&list_schema, &|s| {
263 s.write_integer(&INTEGER, 1)?;
264 s.write_integer(&INTEGER, 2)?;
265 s.write_integer(&INTEGER, 3)?;
266 Ok(())
267 })
268 .unwrap()
269 });
270 let mut dec = crate::Decoder::new(&bytes);
271 let len = dec.list().unwrap();
273 assert!(len.is_none()); assert_eq!(dec.integer().unwrap(), 1);
275 assert_eq!(dec.integer().unwrap(), 2);
276 assert_eq!(dec.integer().unwrap(), 3);
277 }
278
279 #[test]
280 fn test_write_struct() {
281 static NAME_MEMBER: Schema =
282 Schema::new_member(shape_id!("test", "Struct"), ShapeType::String, "name", 0);
283 static AGE_MEMBER: Schema =
284 Schema::new_member(shape_id!("test", "Struct"), ShapeType::Integer, "age", 1);
285 static STRUCT_SCHEMA: Schema = Schema::new_struct(
286 shape_id!("test", "Struct"),
287 ShapeType::Structure,
288 &[&NAME_MEMBER, &AGE_MEMBER],
289 );
290
291 struct TestStruct;
292 impl SerializableStruct for TestStruct {
293 fn serialize_members(&self, s: &mut dyn ShapeSerializer) -> Result<(), SerdeError> {
294 s.write_string(&NAME_MEMBER, "Alice")?;
295 s.write_integer(&AGE_MEMBER, 30)?;
296 Ok(())
297 }
298 }
299
300 let bytes = round_trip(|s| s.write_struct(&STRUCT_SCHEMA, &TestStruct).unwrap());
301 let mut dec = crate::Decoder::new(&bytes);
302 let len = dec.map().unwrap();
303 assert!(len.is_none()); assert_eq!(dec.str().unwrap().as_ref(), "name");
305 assert_eq!(dec.str().unwrap().as_ref(), "Alice");
306 assert_eq!(dec.str().unwrap().as_ref(), "age");
307 assert_eq!(dec.integer().unwrap(), 30);
308 }
309
310 #[test]
311 fn test_write_map() {
312 let map_schema = Schema::new(shape_id!("test", "Map"), ShapeType::Map);
313 let bytes = round_trip(|s| {
314 s.write_map(&map_schema, &|s| {
315 s.write_string(&STRING, "key1")?;
316 s.write_string(&STRING, "val1")?;
317 Ok(())
318 })
319 .unwrap()
320 });
321 let mut dec = crate::Decoder::new(&bytes);
322 let len = dec.map().unwrap();
323 assert!(len.is_none());
324 assert_eq!(dec.str().unwrap().as_ref(), "key1");
325 assert_eq!(dec.str().unwrap().as_ref(), "val1");
326 }
327}