1use bytes::{Buf, BufMut, Bytes, BytesMut};
27use std::collections::HashMap;
28
29use super::value::AmfValue;
30use crate::error::AmfError;
31
32const MARKER_UNDEFINED: u8 = 0x00;
34const MARKER_NULL: u8 = 0x01;
35const MARKER_FALSE: u8 = 0x02;
36const MARKER_TRUE: u8 = 0x03;
37const MARKER_INTEGER: u8 = 0x04;
38const MARKER_DOUBLE: u8 = 0x05;
39const MARKER_STRING: u8 = 0x06;
40const MARKER_XML_DOC: u8 = 0x07;
41const MARKER_DATE: u8 = 0x08;
42const MARKER_ARRAY: u8 = 0x09;
43const MARKER_OBJECT: u8 = 0x0A;
44const MARKER_XML: u8 = 0x0B;
45const MARKER_BYTE_ARRAY: u8 = 0x0C;
46
47const MAX_NESTING_DEPTH: usize = 64;
49
50const AMF3_INT_MAX: i32 = 0x0FFFFFFF;
52const AMF3_INT_MIN: i32 = -0x10000000;
53
54pub struct Amf3Decoder {
56 string_refs: Vec<String>,
58 object_refs: Vec<AmfValue>,
60 trait_refs: Vec<TraitDef>,
62 lenient: bool,
64 depth: usize,
66}
67
68#[derive(Clone, Debug)]
70struct TraitDef {
71 class_name: String,
72 is_dynamic: bool,
73 properties: Vec<String>,
74}
75
76impl Amf3Decoder {
77 pub fn new() -> Self {
79 Self {
80 string_refs: Vec::new(),
81 object_refs: Vec::new(),
82 trait_refs: Vec::new(),
83 lenient: true,
84 depth: 0,
85 }
86 }
87
88 pub fn reset(&mut self) {
90 self.string_refs.clear();
91 self.object_refs.clear();
92 self.trait_refs.clear();
93 self.depth = 0;
94 }
95
96 pub fn decode(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
98 if buf.is_empty() {
99 return Err(AmfError::UnexpectedEof);
100 }
101
102 self.depth += 1;
103 if self.depth > MAX_NESTING_DEPTH {
104 return Err(AmfError::NestingTooDeep);
105 }
106
107 let marker = buf.get_u8();
108 let result = self.decode_value(marker, buf);
109 self.depth -= 1;
110 result
111 }
112
113 fn decode_value(&mut self, marker: u8, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
114 match marker {
115 MARKER_UNDEFINED => Ok(AmfValue::Undefined),
116 MARKER_NULL => Ok(AmfValue::Null),
117 MARKER_FALSE => Ok(AmfValue::Boolean(false)),
118 MARKER_TRUE => Ok(AmfValue::Boolean(true)),
119 MARKER_INTEGER => self.decode_integer(buf),
120 MARKER_DOUBLE => self.decode_double(buf),
121 MARKER_STRING => self.decode_string(buf),
122 MARKER_DATE => self.decode_date(buf),
123 MARKER_ARRAY => self.decode_array(buf),
124 MARKER_OBJECT => self.decode_object(buf),
125 MARKER_BYTE_ARRAY => self.decode_byte_array(buf),
126 MARKER_XML | MARKER_XML_DOC => self.decode_xml(buf),
127 _ => {
128 if self.lenient {
129 Ok(AmfValue::Undefined)
130 } else {
131 Err(AmfError::UnknownMarker(marker))
132 }
133 }
134 }
135 }
136
137 fn decode_integer(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
138 let value = self.read_u29(buf)?;
139 let signed = if value & 0x10000000 != 0 {
141 (value as i32) | !0x1FFFFFFF
142 } else {
143 value as i32
144 };
145 Ok(AmfValue::Integer(signed))
146 }
147
148 fn decode_double(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
149 if buf.remaining() < 8 {
150 return Err(AmfError::UnexpectedEof);
151 }
152 Ok(AmfValue::Number(buf.get_f64()))
153 }
154
155 fn decode_string(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
156 let s = self.read_string(buf)?;
157 Ok(AmfValue::String(s))
158 }
159
160 fn decode_date(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
161 let header = self.read_u29(buf)?;
162
163 if header & 1 == 0 {
164 let idx = (header >> 1) as usize;
166 if idx >= self.object_refs.len() {
167 return Err(AmfError::InvalidReference(idx as u16));
168 }
169 return Ok(self.object_refs[idx].clone());
170 }
171
172 if buf.remaining() < 8 {
173 return Err(AmfError::UnexpectedEof);
174 }
175
176 let timestamp = buf.get_f64();
177 let value = AmfValue::Date(timestamp);
178 self.object_refs.push(value.clone());
179 Ok(value)
180 }
181
182 fn decode_array(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
183 let header = self.read_u29(buf)?;
184
185 if header & 1 == 0 {
186 let idx = (header >> 1) as usize;
188 if idx >= self.object_refs.len() {
189 return Err(AmfError::InvalidReference(idx as u16));
190 }
191 return Ok(self.object_refs[idx].clone());
192 }
193
194 let dense_count = (header >> 1) as usize;
195
196 let arr_idx = self.object_refs.len();
198 self.object_refs.push(AmfValue::Null);
199
200 let mut assoc = HashMap::new();
202 loop {
203 let key = self.read_string(buf)?;
204 if key.is_empty() {
205 break;
206 }
207 let value = self.decode(buf)?;
208 assoc.insert(key, value);
209 }
210
211 let mut dense = Vec::with_capacity(dense_count.min(1024));
213 for _ in 0..dense_count {
214 dense.push(self.decode(buf)?);
215 }
216
217 let value = if assoc.is_empty() {
218 AmfValue::Array(dense)
219 } else {
220 for (i, v) in dense.into_iter().enumerate() {
222 assoc.insert(i.to_string(), v);
223 }
224 AmfValue::EcmaArray(assoc)
225 };
226
227 self.object_refs[arr_idx] = value.clone();
228 Ok(value)
229 }
230
231 fn decode_object(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
232 let header = self.read_u29(buf)?;
233
234 if header & 1 == 0 {
235 let idx = (header >> 1) as usize;
237 if idx >= self.object_refs.len() {
238 return Err(AmfError::InvalidReference(idx as u16));
239 }
240 return Ok(self.object_refs[idx].clone());
241 }
242
243 let obj_idx = self.object_refs.len();
245 self.object_refs.push(AmfValue::Null);
246
247 let trait_def = if header & 2 == 0 {
248 let idx = (header >> 2) as usize;
250 if idx >= self.trait_refs.len() {
251 return Err(AmfError::InvalidReference(idx as u16));
252 }
253 self.trait_refs[idx].clone()
254 } else {
255 let is_dynamic = (header & 8) != 0;
257 let sealed_count = (header >> 4) as usize;
258
259 let class_name = self.read_string(buf)?;
260
261 let mut properties = Vec::with_capacity(sealed_count);
262 for _ in 0..sealed_count {
263 properties.push(self.read_string(buf)?);
264 }
265
266 let trait_def = TraitDef {
267 class_name,
268 is_dynamic,
269 properties,
270 };
271 self.trait_refs.push(trait_def.clone());
272 trait_def
273 };
274
275 let mut props = HashMap::new();
276
277 for prop_name in &trait_def.properties {
279 let value = self.decode(buf)?;
280 props.insert(prop_name.clone(), value);
281 }
282
283 if trait_def.is_dynamic {
285 loop {
286 let key = self.read_string(buf)?;
287 if key.is_empty() {
288 break;
289 }
290 let value = self.decode(buf)?;
291 props.insert(key, value);
292 }
293 }
294
295 let value = if trait_def.class_name.is_empty() {
296 AmfValue::Object(props)
297 } else {
298 AmfValue::TypedObject {
299 class_name: trait_def.class_name,
300 properties: props,
301 }
302 };
303
304 self.object_refs[obj_idx] = value.clone();
305 Ok(value)
306 }
307
308 fn decode_byte_array(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
309 let header = self.read_u29(buf)?;
310
311 if header & 1 == 0 {
312 let idx = (header >> 1) as usize;
313 if idx >= self.object_refs.len() {
314 return Err(AmfError::InvalidReference(idx as u16));
315 }
316 return Ok(self.object_refs[idx].clone());
317 }
318
319 let len = (header >> 1) as usize;
320 if buf.remaining() < len {
321 return Err(AmfError::UnexpectedEof);
322 }
323
324 let data = buf.copy_to_bytes(len).to_vec();
325 let value = AmfValue::ByteArray(data);
326 self.object_refs.push(value.clone());
327 Ok(value)
328 }
329
330 fn decode_xml(&mut self, buf: &mut Bytes) -> Result<AmfValue, AmfError> {
331 let header = self.read_u29(buf)?;
332
333 if header & 1 == 0 {
334 let idx = (header >> 1) as usize;
335 if idx >= self.object_refs.len() {
336 return Err(AmfError::InvalidReference(idx as u16));
337 }
338 return Ok(self.object_refs[idx].clone());
339 }
340
341 let len = (header >> 1) as usize;
342 if buf.remaining() < len {
343 return Err(AmfError::UnexpectedEof);
344 }
345
346 let bytes = buf.copy_to_bytes(len);
347 let s = String::from_utf8(bytes.to_vec()).map_err(|_| AmfError::InvalidUtf8)?;
348 let value = AmfValue::Xml(s);
349 self.object_refs.push(value.clone());
350 Ok(value)
351 }
352
353 fn read_u29(&mut self, buf: &mut Bytes) -> Result<u32, AmfError> {
355 let mut value: u32 = 0;
356
357 for i in 0..4 {
358 if buf.is_empty() {
359 return Err(AmfError::UnexpectedEof);
360 }
361
362 let byte = buf.get_u8();
363
364 if i < 3 {
365 value = (value << 7) | ((byte & 0x7F) as u32);
366 if byte & 0x80 == 0 {
367 return Ok(value);
368 }
369 } else {
370 value = (value << 8) | (byte as u32);
372 return Ok(value);
373 }
374 }
375
376 Ok(value)
377 }
378
379 fn read_string(&mut self, buf: &mut Bytes) -> Result<String, AmfError> {
381 let header = self.read_u29(buf)?;
382
383 if header & 1 == 0 {
384 let idx = (header >> 1) as usize;
386 if idx >= self.string_refs.len() {
387 return Err(AmfError::InvalidReference(idx as u16));
388 }
389 return Ok(self.string_refs[idx].clone());
390 }
391
392 let len = (header >> 1) as usize;
393 if len == 0 {
394 return Ok(String::new());
395 }
396
397 if buf.remaining() < len {
398 return Err(AmfError::UnexpectedEof);
399 }
400
401 let bytes = buf.copy_to_bytes(len);
402 let s = String::from_utf8(bytes.to_vec()).map_err(|_| AmfError::InvalidUtf8)?;
403
404 self.string_refs.push(s.clone());
406 Ok(s)
407 }
408}
409
410impl Default for Amf3Decoder {
411 fn default() -> Self {
412 Self::new()
413 }
414}
415
416pub struct Amf3Encoder {
418 buf: BytesMut,
419 string_refs: HashMap<String, usize>,
420}
421
422impl Amf3Encoder {
423 pub fn new() -> Self {
425 Self {
426 buf: BytesMut::with_capacity(256),
427 string_refs: HashMap::new(),
428 }
429 }
430
431 pub fn finish(&mut self) -> Bytes {
433 self.string_refs.clear();
434 self.buf.split().freeze()
435 }
436
437 pub fn encode(&mut self, value: &AmfValue) {
439 match value {
440 AmfValue::Undefined => self.buf.put_u8(MARKER_UNDEFINED),
441 AmfValue::Null => self.buf.put_u8(MARKER_NULL),
442 AmfValue::Boolean(false) => self.buf.put_u8(MARKER_FALSE),
443 AmfValue::Boolean(true) => self.buf.put_u8(MARKER_TRUE),
444 AmfValue::Integer(i) if *i >= AMF3_INT_MIN && *i <= AMF3_INT_MAX => {
445 self.buf.put_u8(MARKER_INTEGER);
446 self.write_u29(*i as u32 & 0x1FFFFFFF);
447 }
448 AmfValue::Integer(i) => {
449 self.buf.put_u8(MARKER_DOUBLE);
450 self.buf.put_f64(*i as f64);
451 }
452 AmfValue::Number(n) => {
453 self.buf.put_u8(MARKER_DOUBLE);
454 self.buf.put_f64(*n);
455 }
456 AmfValue::String(s) => {
457 self.buf.put_u8(MARKER_STRING);
458 self.write_string(s);
459 }
460 AmfValue::Array(elements) => {
461 self.buf.put_u8(MARKER_ARRAY);
462 let header = ((elements.len() as u32) << 1) | 1;
463 self.write_u29(header);
464 self.write_u29(1); for elem in elements {
467 self.encode(elem);
468 }
469 }
470 AmfValue::Object(props) | AmfValue::EcmaArray(props) => {
471 self.buf.put_u8(MARKER_OBJECT);
472 let header = (0 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | 1;
474 self.write_u29(header);
475 self.write_string(""); for (key, val) in props {
477 self.write_string(key);
478 self.encode(val);
479 }
480 self.write_string(""); }
482 AmfValue::TypedObject {
483 class_name,
484 properties,
485 } => {
486 self.buf.put_u8(MARKER_OBJECT);
487 let header = (0 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | 1;
488 self.write_u29(header);
489 self.write_string(class_name);
490 for (key, val) in properties {
491 self.write_string(key);
492 self.encode(val);
493 }
494 self.write_string("");
495 }
496 AmfValue::Date(timestamp) => {
497 self.buf.put_u8(MARKER_DATE);
498 self.write_u29(1); self.buf.put_f64(*timestamp);
500 }
501 AmfValue::Xml(s) => {
502 self.buf.put_u8(MARKER_XML);
503 let header = ((s.len() as u32) << 1) | 1;
504 self.write_u29(header);
505 self.buf.put_slice(s.as_bytes());
506 }
507 AmfValue::ByteArray(data) => {
508 self.buf.put_u8(MARKER_BYTE_ARRAY);
509 let header = ((data.len() as u32) << 1) | 1;
510 self.write_u29(header);
511 self.buf.put_slice(data);
512 }
513 }
514 }
515
516 fn write_u29(&mut self, value: u32) {
518 let value = value & 0x1FFFFFFF;
519
520 if value < 0x80 {
521 self.buf.put_u8(value as u8);
522 } else if value < 0x4000 {
523 self.buf.put_u8(((value >> 7) | 0x80) as u8);
524 self.buf.put_u8((value & 0x7F) as u8);
525 } else if value < 0x200000 {
526 self.buf.put_u8(((value >> 14) | 0x80) as u8);
527 self.buf.put_u8(((value >> 7) | 0x80) as u8);
528 self.buf.put_u8((value & 0x7F) as u8);
529 } else {
530 self.buf.put_u8(((value >> 22) | 0x80) as u8);
531 self.buf.put_u8(((value >> 15) | 0x80) as u8);
532 self.buf.put_u8(((value >> 8) | 0x80) as u8);
533 self.buf.put_u8((value & 0xFF) as u8);
534 }
535 }
536
537 fn write_string(&mut self, s: &str) {
539 if s.is_empty() {
540 self.write_u29(1); return;
542 }
543
544 if let Some(&idx) = self.string_refs.get(s) {
545 self.write_u29((idx as u32) << 1);
547 } else {
548 let idx = self.string_refs.len();
550 self.string_refs.insert(s.to_string(), idx);
551 let header = ((s.len() as u32) << 1) | 1;
552 self.write_u29(header);
553 self.buf.put_slice(s.as_bytes());
554 }
555 }
556}
557
558impl Default for Amf3Encoder {
559 fn default() -> Self {
560 Self::new()
561 }
562}
563
564#[cfg(test)]
565mod tests {
566 use super::*;
567
568 #[test]
569 fn test_u29_encoding() {
570 let mut encoder = Amf3Encoder::new();
571
572 encoder.write_u29(0);
574 encoder.write_u29(127);
575 encoder.write_u29(128);
576 encoder.write_u29(16383);
577 encoder.write_u29(16384);
578 encoder.write_u29(2097151);
579 encoder.write_u29(2097152);
580
581 let encoded = encoder.finish();
582
583 let mut decoder = Amf3Decoder::new();
584 let mut buf = encoded;
585
586 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 0);
587 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 127);
588 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 128);
589 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 16383);
590 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 16384);
591 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 2097151);
592 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 2097152);
593 }
594
595 #[test]
596 fn test_string_roundtrip() {
597 let mut encoder = Amf3Encoder::new();
598 encoder.encode(&AmfValue::String("hello".into()));
599 let encoded = encoder.finish();
600
601 let mut decoder = Amf3Decoder::new();
602 let mut buf = encoded;
603 let decoded = decoder.decode(&mut buf).unwrap();
604 assert_eq!(decoded, AmfValue::String("hello".into()));
605 }
606
607 #[test]
608 fn test_null_and_undefined() {
609 let mut encoder = Amf3Encoder::new();
610
611 encoder.encode(&AmfValue::Null);
612 encoder.encode(&AmfValue::Undefined);
613
614 let encoded = encoder.finish();
615 let mut decoder = Amf3Decoder::new();
616 let mut buf = encoded;
617
618 let null = decoder.decode(&mut buf).unwrap();
619 assert_eq!(null, AmfValue::Null);
620
621 let undef = decoder.decode(&mut buf).unwrap();
622 assert_eq!(undef, AmfValue::Undefined);
623 }
624
625 #[test]
626 fn test_boolean_values() {
627 let mut encoder = Amf3Encoder::new();
628
629 encoder.encode(&AmfValue::Boolean(true));
630 encoder.encode(&AmfValue::Boolean(false));
631
632 let encoded = encoder.finish();
633 let mut decoder = Amf3Decoder::new();
634 let mut buf = encoded;
635
636 let true_val = decoder.decode(&mut buf).unwrap();
637 assert_eq!(true_val, AmfValue::Boolean(true));
638
639 let false_val = decoder.decode(&mut buf).unwrap();
640 assert_eq!(false_val, AmfValue::Boolean(false));
641 }
642
643 #[test]
644 fn test_integer_values() {
645 let mut encoder = Amf3Encoder::new();
646
647 encoder.encode(&AmfValue::Integer(42));
649 encoder.encode(&AmfValue::Integer(-42));
651 encoder.encode(&AmfValue::Integer(0));
653 encoder.encode(&AmfValue::Integer(0x0FFFFFFF));
655 encoder.encode(&AmfValue::Integer(-0x10000000));
657
658 let encoded = encoder.finish();
659 let mut decoder = Amf3Decoder::new();
660 let mut buf = encoded;
661
662 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Integer(42));
663 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Integer(-42));
664 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Integer(0));
665 assert_eq!(
666 decoder.decode(&mut buf).unwrap(),
667 AmfValue::Integer(0x0FFFFFFF)
668 );
669 assert_eq!(
670 decoder.decode(&mut buf).unwrap(),
671 AmfValue::Integer(-0x10000000)
672 );
673 }
674
675 #[test]
676 fn test_integer_overflow_as_double() {
677 let mut encoder = Amf3Encoder::new();
678
679 encoder.encode(&AmfValue::Integer(i32::MAX));
681
682 let encoded = encoder.finish();
683 let mut decoder = Amf3Decoder::new();
684 let mut buf = encoded;
685
686 let result = decoder.decode(&mut buf).unwrap();
688 if let AmfValue::Number(n) = result {
689 assert_eq!(n as i32, i32::MAX);
690 } else {
691 panic!("Expected Number for overflow integer");
692 }
693 }
694
695 #[test]
696 fn test_double_values() {
697 let mut encoder = Amf3Encoder::new();
698
699 encoder.encode(&AmfValue::Number(3.14159));
700 encoder.encode(&AmfValue::Number(-273.15));
701 encoder.encode(&AmfValue::Number(0.0));
702
703 let encoded = encoder.finish();
704 let mut decoder = Amf3Decoder::new();
705 let mut buf = encoded;
706
707 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Number(3.14159));
708 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Number(-273.15));
709 assert_eq!(decoder.decode(&mut buf).unwrap(), AmfValue::Number(0.0));
710 }
711
712 #[test]
713 fn test_empty_string() {
714 let mut encoder = Amf3Encoder::new();
715 encoder.encode(&AmfValue::String(String::new()));
716
717 let encoded = encoder.finish();
718 let mut decoder = Amf3Decoder::new();
719 let mut buf = encoded;
720
721 let result = decoder.decode(&mut buf).unwrap();
722 assert_eq!(result, AmfValue::String(String::new()));
723 }
724
725 #[test]
726 fn test_array_roundtrip() {
727 let mut encoder = Amf3Encoder::new();
728
729 let array = AmfValue::Array(vec![
730 AmfValue::Number(1.0),
731 AmfValue::String("two".into()),
732 AmfValue::Boolean(true),
733 ]);
734
735 encoder.encode(&array);
736
737 let encoded = encoder.finish();
738 let mut decoder = Amf3Decoder::new();
739 let mut buf = encoded;
740
741 let result = decoder.decode(&mut buf).unwrap();
742 if let AmfValue::Array(elements) = result {
743 assert_eq!(elements.len(), 3);
744 assert_eq!(elements[0], AmfValue::Number(1.0));
745 assert_eq!(elements[1], AmfValue::String("two".into()));
746 assert_eq!(elements[2], AmfValue::Boolean(true));
747 } else {
748 panic!("Expected Array");
749 }
750 }
751
752 #[test]
753 fn test_object_roundtrip() {
754 let mut encoder = Amf3Encoder::new();
755
756 let mut props = HashMap::new();
757 props.insert("name".to_string(), AmfValue::String("test".into()));
758 props.insert("value".to_string(), AmfValue::Number(123.0));
759
760 encoder.encode(&AmfValue::Object(props));
761
762 let encoded = encoder.finish();
763 let mut decoder = Amf3Decoder::new();
764 let mut buf = encoded;
765
766 let result = decoder.decode(&mut buf).unwrap();
767 if let AmfValue::Object(dec_props) = result {
768 assert_eq!(dec_props.get("name").unwrap().as_str(), Some("test"));
769 assert_eq!(dec_props.get("value").unwrap().as_number(), Some(123.0));
770 } else {
771 panic!("Expected Object");
772 }
773 }
774
775 #[test]
776 fn test_date_roundtrip() {
777 let mut encoder = Amf3Encoder::new();
778
779 let timestamp = 1700000000000.0;
780 encoder.encode(&AmfValue::Date(timestamp));
781
782 let encoded = encoder.finish();
783 let mut decoder = Amf3Decoder::new();
784 let mut buf = encoded;
785
786 let result = decoder.decode(&mut buf).unwrap();
787 assert_eq!(result, AmfValue::Date(timestamp));
788 }
789
790 #[test]
791 fn test_byte_array_roundtrip() {
792 let mut encoder = Amf3Encoder::new();
793
794 let data = vec![0x01, 0x02, 0x03, 0x04, 0x05];
795 encoder.encode(&AmfValue::ByteArray(data.clone()));
796
797 let encoded = encoder.finish();
798 let mut decoder = Amf3Decoder::new();
799 let mut buf = encoded;
800
801 let result = decoder.decode(&mut buf).unwrap();
802 assert_eq!(result, AmfValue::ByteArray(data));
803 }
804
805 #[test]
806 fn test_xml_roundtrip() {
807 let mut encoder = Amf3Encoder::new();
808
809 let xml = "<root><child>text</child></root>".to_string();
810 encoder.encode(&AmfValue::Xml(xml.clone()));
811
812 let encoded = encoder.finish();
813 let mut decoder = Amf3Decoder::new();
814 let mut buf = encoded;
815
816 let result = decoder.decode(&mut buf).unwrap();
817 assert_eq!(result, AmfValue::Xml(xml));
818 }
819
820 #[test]
821 fn test_decoder_reset() {
822 let mut encoder = Amf3Encoder::new();
823 encoder.encode(&AmfValue::String("test".into()));
824 let encoded = encoder.finish();
825
826 let mut decoder = Amf3Decoder::new();
827 let mut buf = encoded.clone();
828 let _ = decoder.decode(&mut buf).unwrap();
829
830 decoder.reset();
832 let mut buf2 = encoded;
833 let result = decoder.decode(&mut buf2).unwrap();
834 assert_eq!(result, AmfValue::String("test".into()));
835 }
836
837 #[test]
838 fn test_string_references() {
839 let mut encoder = Amf3Encoder::new();
840
841 encoder.encode(&AmfValue::String("repeated".into()));
843 encoder.encode(&AmfValue::String("repeated".into()));
844 encoder.encode(&AmfValue::String("repeated".into()));
845
846 let encoded = encoder.finish();
847 let mut decoder = Amf3Decoder::new();
848 let mut buf = encoded;
849
850 assert_eq!(
852 decoder.decode(&mut buf).unwrap(),
853 AmfValue::String("repeated".into())
854 );
855 assert_eq!(
856 decoder.decode(&mut buf).unwrap(),
857 AmfValue::String("repeated".into())
858 );
859 assert_eq!(
860 decoder.decode(&mut buf).unwrap(),
861 AmfValue::String("repeated".into())
862 );
863 }
864
865 #[test]
866 fn test_u29_boundary_values() {
867 let mut encoder = Amf3Encoder::new();
869
870 encoder.write_u29(0);
872 encoder.write_u29(127);
873
874 encoder.write_u29(128);
876 encoder.write_u29(16383);
877
878 encoder.write_u29(16384);
880 encoder.write_u29(2097151);
881
882 encoder.write_u29(2097152);
884 encoder.write_u29(0x1FFFFFFF); let encoded = encoder.finish();
887 let mut decoder = Amf3Decoder::new();
888 let mut buf = encoded;
889
890 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 0);
891 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 127);
892 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 128);
893 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 16383);
894 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 16384);
895 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 2097151);
896 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 2097152);
897 assert_eq!(decoder.read_u29(&mut buf).unwrap(), 0x1FFFFFFF);
898 }
899
900 #[test]
901 fn test_decode_empty_buffer() {
902 let mut decoder = Amf3Decoder::new();
903 let mut buf = Bytes::new();
904 let result = decoder.decode(&mut buf);
905 assert!(matches!(result, Err(AmfError::UnexpectedEof)));
906 }
907
908 #[test]
909 fn test_lenient_mode_unknown_marker() {
910 let mut decoder = Amf3Decoder::new();
911 let mut buf = Bytes::from_static(&[0xFF]); let result = decoder.decode(&mut buf).unwrap();
913 assert_eq!(result, AmfValue::Undefined);
914 }
915
916 #[test]
917 fn test_ecma_array_as_object() {
918 let mut encoder = Amf3Encoder::new();
919
920 let mut props = HashMap::new();
921 props.insert("key1".to_string(), AmfValue::Number(1.0));
922 props.insert("key2".to_string(), AmfValue::String("value".into()));
923
924 encoder.encode(&AmfValue::EcmaArray(props));
925
926 let encoded = encoder.finish();
927 let mut decoder = Amf3Decoder::new();
928 let mut buf = encoded;
929
930 let result = decoder.decode(&mut buf).unwrap();
932 if let AmfValue::Object(dec_props) = result {
933 assert!(dec_props.contains_key("key1") || dec_props.contains_key("key2"));
934 } else {
935 panic!("Expected Object (from EcmaArray)");
936 }
937 }
938}