1use alloc::vec::Vec;
18
19use super::values::{Constants, Value};
20
21#[derive(Debug, PartialEq)]
23pub enum EncoderError {
24 TooMuchNesting,
25 DuplicateMapKey,
26}
27
28pub fn write(value: Value, encoded_cbor: &mut Vec<u8>) -> Result<(), EncoderError> {
32 write_nested(value, encoded_cbor, Some(i8::MAX))
33}
34
35pub fn write_nested(
39 value: Value,
40 encoded_cbor: &mut Vec<u8>,
41 max_nest: Option<i8>,
42) -> Result<(), EncoderError> {
43 let mut writer = Writer::new(encoded_cbor);
44 writer.encode_cbor(value, max_nest)
45}
46
47struct Writer<'a> {
48 encoded_cbor: &'a mut Vec<u8>,
49}
50
51impl<'a> Writer<'a> {
52 pub fn new(encoded_cbor: &mut Vec<u8>) -> Writer {
53 Writer { encoded_cbor }
54 }
55
56 fn encode_cbor(
57 &mut self,
58 value: Value,
59 remaining_depth: Option<i8>,
60 ) -> Result<(), EncoderError> {
61 if remaining_depth.map_or(false, |d| d < 0) {
62 return Err(EncoderError::TooMuchNesting);
63 }
64 let type_label = value.type_label();
65 match value {
66 Value::Unsigned(unsigned) => self.start_item(type_label, unsigned),
67 Value::Negative(negative) => self.start_item(type_label, -(negative + 1) as u64),
68 Value::ByteString(byte_string) => {
69 self.start_item(type_label, byte_string.len() as u64);
70 self.encoded_cbor.extend(byte_string);
71 }
72 Value::TextString(text_string) => {
73 self.start_item(type_label, text_string.len() as u64);
74 self.encoded_cbor.extend(text_string.into_bytes());
75 }
76 Value::Array(array) => {
77 self.start_item(type_label, array.len() as u64);
78 for el in array {
79 self.encode_cbor(el, remaining_depth.map(|d| d - 1))?;
80 }
81 }
82 Value::Map(mut map) => {
83 map.sort_by(|a, b| a.0.cmp(&b.0));
84 let map_len = map.len();
85 map.dedup_by(|a, b| a.0.eq(&b.0));
86 if map_len != map.len() {
87 return Err(EncoderError::DuplicateMapKey);
88 }
89 self.start_item(type_label, map_len as u64);
90 for (k, v) in map {
91 self.encode_cbor(k, remaining_depth.map(|d| d - 1))?;
92 self.encode_cbor(v, remaining_depth.map(|d| d - 1))?;
93 }
94 }
95 Value::Tag(tag, inner_value) => {
96 self.start_item(type_label, tag);
97 self.encode_cbor(*inner_value, remaining_depth.map(|d| d - 1))?;
98 }
99 Value::Simple(simple_value) => self.start_item(type_label, simple_value as u64),
100 }
101 Ok(())
102 }
103
104 fn start_item(&mut self, type_label: u8, size: u64) {
105 let (mut first_byte, shift) = match size {
106 0..=23 => (size as u8, 0),
107 24..=0xFF => (Constants::ADDITIONAL_INFORMATION_1_BYTE, 1),
108 0x100..=0xFFFF => (Constants::ADDITIONAL_INFORMATION_2_BYTES, 2),
109 0x10000..=0xFFFF_FFFF => (Constants::ADDITIONAL_INFORMATION_4_BYTES, 4),
110 _ => (Constants::ADDITIONAL_INFORMATION_8_BYTES, 8),
111 };
112 first_byte |= type_label << Constants::MAJOR_TYPE_BIT_SHIFT;
113 self.encoded_cbor.push(first_byte);
114
115 for i in (0..shift).rev() {
116 self.encoded_cbor.push((size >> (i * 8)) as u8);
117 }
118 }
119}
120
121#[cfg(test)]
122mod test {
123 use alloc::vec;
124
125 use super::*;
126 use crate::{
127 cbor_array, cbor_array_vec, cbor_bytes, cbor_false, cbor_int, cbor_map, cbor_null,
128 cbor_tagged, cbor_text, cbor_true, cbor_undefined,
129 };
130
131 fn write_return(value: Value) -> Option<Vec<u8>> {
132 let mut encoded_cbor = Vec::new();
133 if write(value, &mut encoded_cbor).is_ok() {
134 Some(encoded_cbor)
135 } else {
136 None
137 }
138 }
139
140 #[test]
141 fn test_write_unsigned() {
142 let cases = vec![
143 (0, vec![0x00]),
144 (1, vec![0x01]),
145 (10, vec![0x0A]),
146 (23, vec![0x17]),
147 (24, vec![0x18, 0x18]),
148 (25, vec![0x18, 0x19]),
149 (100, vec![0x18, 0x64]),
150 (1000, vec![0x19, 0x03, 0xE8]),
151 (1000000, vec![0x1A, 0x00, 0x0F, 0x42, 0x40]),
152 (0xFFFFFFFF, vec![0x1A, 0xFF, 0xFF, 0xFF, 0xFF]),
153 (
154 0x100000000,
155 vec![0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
156 ),
157 (
158 core::i64::MAX,
159 vec![0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
160 ),
161 ];
162 for (unsigned, correct_cbor) in cases {
163 assert_eq!(write_return(cbor_int!(unsigned)), Some(correct_cbor));
164 }
165 }
166
167 #[test]
168 fn test_write_negative() {
169 let cases = vec![
170 (-1, vec![0x20]),
171 (-10, vec![0x29]),
172 (-23, vec![0x36]),
173 (-24, vec![0x37]),
174 (-25, vec![0x38, 0x18]),
175 (-100, vec![0x38, 0x63]),
176 (-1000, vec![0x39, 0x03, 0xE7]),
177 (-4294967296, vec![0x3A, 0xFF, 0xFF, 0xFF, 0xFF]),
178 (
179 -4294967297,
180 vec![0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00],
181 ),
182 (
183 core::i64::MIN,
184 vec![0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
185 ),
186 ];
187 for (negative, correct_cbor) in cases {
188 assert_eq!(write_return(cbor_int!(negative)), Some(correct_cbor));
189 }
190 }
191
192 #[test]
193 fn test_write_byte_string() {
194 let cases = vec![
195 (vec![], vec![0x40]),
196 (
197 vec![0x01, 0x02, 0x03, 0x04],
198 vec![0x44, 0x01, 0x02, 0x03, 0x04],
199 ),
200 ];
201 for (byte_string, correct_cbor) in cases {
202 assert_eq!(write_return(cbor_bytes!(byte_string)), Some(correct_cbor));
203 }
204 }
205
206 #[test]
207 fn test_write_text_string() {
208 let unicode_3byte = vec![0xE6, 0xB0, 0xB4];
209 let cases = vec![
210 ("", vec![0x60]),
211 ("a", vec![0x61, 0x61]),
212 ("IETF", vec![0x64, 0x49, 0x45, 0x54, 0x46]),
213 ("\"\\", vec![0x62, 0x22, 0x5C]),
214 ("ü", vec![0x62, 0xC3, 0xBC]),
215 (
216 core::str::from_utf8(&unicode_3byte).unwrap(),
217 vec![0x63, 0xE6, 0xB0, 0xB4],
218 ),
219 ("𐅑", vec![0x64, 0xF0, 0x90, 0x85, 0x91]),
220 ];
221 for (text_string, correct_cbor) in cases {
222 assert_eq!(write_return(cbor_text!(text_string)), Some(correct_cbor));
223 }
224 }
225
226 #[test]
227 fn test_write_array() {
228 let value_vec: Vec<_> = (1..26).collect();
229 let expected_cbor = vec![
230 0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
232 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19,
233 ];
234 assert_eq!(
235 write_return(cbor_array_vec!(value_vec)),
236 Some(expected_cbor)
237 );
238 }
239
240 #[test]
241 fn test_write_map() {
242 let value_map = cbor_map! {
243 0 => "a",
244 23 => "b",
245 24 => "c",
246 core::u8::MAX as i64 => "d",
247 256 => "e",
248 core::u16::MAX as i64 => "f",
249 65536 => "g",
250 core::u32::MAX as i64 => "h",
251 4294967296_i64 => "i",
252 core::i64::MAX => "j",
253 -1 => "k",
254 -24 => "l",
255 -25 => "m",
256 -256 => "n",
257 -257 => "o",
258 -65537 => "p",
259 -4294967296_i64 => "q",
260 -4294967297_i64 => "r",
261 core::i64::MIN => "s",
262 b"a" => 2,
263 b"bar" => 3,
264 b"foo" => 4,
265 "" => ".",
266 "e" => "E",
267 "aa" => "AA",
268 };
269 let expected_cbor = vec![
270 0xb8, 0x19, 0x00, 0x61, 0x61, 0x17, 0x61, 0x62, 0x18, 0x18, 0x61, 0x63, 0x18, 0xFF, 0x61, 0x64, 0x19, 0x01, 0x00, 0x61, 0x65, 0x19, 0xFF, 0xFF, 0x61, 0x66, 0x1A, 0x00, 0x01, 0x00, 0x00, 0x61, 0x67, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x68, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x69, 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x6a, 0x20, 0x61, 0x6b, 0x37, 0x61, 0x6c, 0x38, 0x18, 0x61, 0x6d, 0x38, 0xFF, 0x61, 0x6e, 0x39, 0x01, 0x00, 0x61, 0x6f, 0x3A, 0x00, 0x01, 0x00, 0x00, 0x61, 0x70, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x71, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x73, 0x41, b'a', 0x02, 0x43, b'b', b'a', b'r', 0x03, 0x43, b'f', b'o', b'o', 0x04, 0x60, 0x61, 0x2e, 0x61, 0x65, 0x61, 0x45, 0x62, 0x61, 0x61, 0x62, 0x41, 0x41, ];
319 assert_eq!(write_return(value_map), Some(expected_cbor));
320 }
321
322 #[test]
323 fn test_write_map_sorted() {
324 let sorted_map = cbor_map! {
325 0 => "a",
326 1 => "b",
327 -1 => "c",
328 -2 => "d",
329 b"a" => "e",
330 b"b" => "f",
331 "" => "g",
332 "c" => "h",
333 };
334 let unsorted_map = cbor_map! {
335 1 => "b",
336 -2 => "d",
337 b"b" => "f",
338 "c" => "h",
339 "" => "g",
340 b"a" => "e",
341 -1 => "c",
342 0 => "a",
343 };
344 assert_eq!(write_return(sorted_map), write_return(unsorted_map));
345 }
346
347 #[test]
348 fn test_write_map_duplicates() {
349 let duplicate0 = cbor_map! {
350 0 => "a",
351 -1 => "c",
352 b"a" => "e",
353 "c" => "g",
354 0 => "b",
355 };
356 assert_eq!(write_return(duplicate0), None);
357 let duplicate1 = cbor_map! {
358 0 => "a",
359 -1 => "c",
360 b"a" => "e",
361 "c" => "g",
362 -1 => "d",
363 };
364 assert_eq!(write_return(duplicate1), None);
365 let duplicate2 = cbor_map! {
366 0 => "a",
367 -1 => "c",
368 b"a" => "e",
369 "c" => "g",
370 b"a" => "f",
371 };
372 assert_eq!(write_return(duplicate2), None);
373 let duplicate3 = cbor_map! {
374 0 => "a",
375 -1 => "c",
376 b"a" => "e",
377 "c" => "g",
378 "c" => "h",
379 };
380 assert_eq!(write_return(duplicate3), None);
381 }
382
383 #[test]
384 fn test_write_map_with_array() {
385 let value_map = cbor_map! {
386 "a" => 1,
387 "b" => cbor_array![2, 3],
388 };
389 let expected_cbor = vec![
390 0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03,
395 ];
396 assert_eq!(write_return(value_map), Some(expected_cbor));
397 }
398
399 #[test]
400 fn test_write_nested_map() {
401 let value_map = cbor_map! {
402 "a" => 1,
403 "b" => cbor_map! {
404 "c" => 2,
405 "d" => 3,
406 },
407 };
408 let expected_cbor = vec![
409 0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0xa2, 0x61, 0x63, 0x02, 0x61, 0x64, 0x03,
416 ];
417 assert_eq!(write_return(value_map), Some(expected_cbor));
418 }
419
420 #[test]
421 fn test_write_tagged() {
422 let cases = vec![
423 (cbor_tagged!(6, cbor_int!(0x42)), vec![0xc6, 0x18, 0x42]),
424 (cbor_tagged!(1, cbor_true!()), vec![0xc1, 0xf5]),
425 (
426 cbor_tagged!(
427 1000,
428 cbor_map! {
429 "a" => 1,
430 "b" => cbor_array![2, 3],
431 }
432 ),
433 vec![
434 0xd9, 0x03, 0xe8, 0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03,
439 ],
440 ),
441 ];
442 for (value, correct_cbor) in cases {
443 assert_eq!(write_return(value), Some(correct_cbor));
444 }
445 }
446
447 #[test]
448 fn test_write_simple() {
449 let cases = vec![
450 (cbor_false!(), vec![0xF4]),
451 (cbor_true!(), vec![0xF5]),
452 (cbor_null!(), vec![0xF6]),
453 (cbor_undefined!(), vec![0xF7]),
454 ];
455 for (value, correct_cbor) in cases {
456 assert_eq!(write_return(value), Some(correct_cbor));
457 }
458 }
459
460 #[test]
461 fn test_write_single_levels() {
462 let simple_array: Value = cbor_array![2];
463 let simple_map: Value = cbor_map! {"b" => 3};
464 let positive_cases = vec![
465 (cbor_int!(1), 0),
466 (cbor_bytes!(vec![0x01, 0x02, 0x03, 0x04]), 0),
467 (cbor_text!("a"), 0),
468 (cbor_array![], 0),
469 (cbor_map! {}, 0),
470 (simple_array.clone(), 1),
471 (simple_map.clone(), 1),
472 ];
473 let negative_cases = vec![(simple_array.clone(), 0), (simple_map.clone(), 0)];
474 for (value, level) in positive_cases {
475 let mut buf = Vec::new();
476 let mut writer = Writer::new(&mut buf);
477 assert!(writer.encode_cbor(value, Some(level)).is_ok());
478 }
479 for (value, level) in negative_cases {
480 let mut buf = Vec::new();
481 let mut writer = Writer::new(&mut buf);
482 assert!(!writer.encode_cbor(value, Some(level)).is_ok());
483 }
484 }
485
486 #[test]
487 fn test_write_nested_map_levels() {
488 let cbor_map: Value = cbor_map! {
489 "a" => 1,
490 "b" => cbor_map! {
491 "c" => 2,
492 "d" => 3,
493 },
494 };
495
496 let mut buf = Vec::new();
497 let mut writer = Writer::new(&mut buf);
498 assert!(writer.encode_cbor(cbor_map.clone(), Some(2)).is_ok());
499 assert!(writer.encode_cbor(cbor_map.clone(), None).is_ok());
500 writer = Writer::new(&mut buf);
501 assert!(writer.encode_cbor(cbor_map, Some(1)).is_err());
502 }
503
504 #[test]
505 fn test_write_unbalanced_nested_containers() {
506 let cbor_array: Value = cbor_array![
507 1,
508 2,
509 3,
510 cbor_map! {
511 "a" => 1,
512 "b" => cbor_map! {
513 "c" => 2,
514 "d" => 3,
515 },
516 },
517 ];
518
519 let mut buf = Vec::new();
520 let mut writer = Writer::new(&mut buf);
521 assert!(writer.encode_cbor(cbor_array.clone(), Some(3)).is_ok());
522 writer = Writer::new(&mut buf);
523 assert!(writer.encode_cbor(cbor_array, Some(2)).is_err());
524 }
525
526 #[test]
527 fn test_write_overly_nested() {
528 let cbor_map: Value = cbor_map! {
529 "a" => 1,
530 "b" => cbor_map! {
531 "c" => 2,
532 "d" => 3,
533 "h" => cbor_map! {
534 "e" => 4,
535 "f" => 5,
536 "g" => cbor_array![
537 6,
538 7,
539 cbor_array![
540 8
541 ]
542 ],
543 },
544 },
545 };
546
547 let mut buf = Vec::new();
548 let mut writer = Writer::new(&mut buf);
549 assert!(writer.encode_cbor(cbor_map.clone(), Some(5)).is_ok());
550 assert!(writer.encode_cbor(cbor_map.clone(), None).is_ok());
551 writer = Writer::new(&mut buf);
552 assert!(writer.encode_cbor(cbor_map, Some(4)).is_err());
553 }
554}